feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command
Add /ultraresearch-local for structured research combining local codebase analysis with external knowledge via parallel agent swarms. Produces research briefs with triangulation, confidence ratings, and source quality assessment. New command: /ultraresearch-local with modes --quick, --local, --external, --fg. New agents: research-orchestrator (opus), docs-researcher, community-researcher, security-researcher, contrarian-researcher, gemini-bridge (all sonnet). New template: research-brief-template.md. Integration: --research flag in /ultraplan-local accepts pre-built research briefs (up to 3), enriches the interview and exploration phases. Planning orchestrator cross-references brief findings during synthesis. Design principle: Context Engineering — right information to right agent at right time. Research briefs are structured artifacts in the pipeline: ultraresearch → brief → ultraplan --research → plan → ultraexecute. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
f153f969a0
196 changed files with 43854 additions and 0 deletions
79
tests/hooks/update-check.test.mjs
Normal file
79
tests/hooks/update-check.test.mjs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// update-check.test.mjs — Tests for hooks/scripts/update-check.mjs
|
||||
// Zero external dependencies: node:test + node:assert only.
|
||||
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { resolve } from 'node:path';
|
||||
import { runHook, runHookWithEnv } from './hook-helper.mjs';
|
||||
|
||||
const SCRIPT = resolve(import.meta.dirname, '../../hooks/scripts/update-check.mjs');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Unit tests for isNewer (imported directly)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
import { isNewer, CHECK_INTERVAL_MS } from '../../hooks/scripts/update-check.mjs';
|
||||
|
||||
describe('isNewer — semver comparison', () => {
|
||||
it('returns true when remote patch is higher', () => {
|
||||
assert.equal(isNewer('2.8.1', '2.8.0'), true);
|
||||
});
|
||||
|
||||
it('returns false when versions are equal', () => {
|
||||
assert.equal(isNewer('2.8.0', '2.8.0'), false);
|
||||
});
|
||||
|
||||
it('returns false when remote is older', () => {
|
||||
assert.equal(isNewer('2.7.9', '2.8.0'), false);
|
||||
});
|
||||
|
||||
it('returns true when remote major is higher', () => {
|
||||
assert.equal(isNewer('3.0.0', '2.99.99'), true);
|
||||
});
|
||||
|
||||
it('returns true when remote minor is higher', () => {
|
||||
assert.equal(isNewer('2.9.0', '2.8.99'), true);
|
||||
});
|
||||
|
||||
it('handles different length versions', () => {
|
||||
assert.equal(isNewer('2.8.1', '2.8'), true);
|
||||
assert.equal(isNewer('2.8', '2.8.0'), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHECK_INTERVAL_MS', () => {
|
||||
it('is 24 hours in milliseconds', () => {
|
||||
assert.equal(CHECK_INTERVAL_MS, 86_400_000);
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Integration tests (subprocess via hook-helper)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
describe('update-check hook — opt-out', () => {
|
||||
it('exits silently when LLM_SECURITY_UPDATE_CHECK=off', async () => {
|
||||
const result = await runHookWithEnv(SCRIPT, '{}', {
|
||||
LLM_SECURITY_UPDATE_CHECK: 'off',
|
||||
});
|
||||
assert.equal(result.code, 0);
|
||||
assert.equal(result.stdout.trim(), '');
|
||||
});
|
||||
});
|
||||
|
||||
describe('update-check hook — graceful failures', () => {
|
||||
it('exits 0 with empty stdin', async () => {
|
||||
const result = await runHook(SCRIPT, '');
|
||||
assert.equal(result.code, 0);
|
||||
});
|
||||
|
||||
it('exits 0 with valid JSON stdin (no CLAUDE_PLUGIN_ROOT → fails to read plugin.json)', async () => {
|
||||
// Without CLAUDE_PLUGIN_ROOT set to a valid plugin, it will fail to
|
||||
// read plugin.json from the default path and exit 0 silently.
|
||||
const result = await runHookWithEnv(SCRIPT, '{}', {
|
||||
CLAUDE_PLUGIN_ROOT: '/nonexistent/path',
|
||||
});
|
||||
assert.equal(result.code, 0);
|
||||
assert.equal(result.stdout.trim(), '');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue