kenaz 0.3.2 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/.claude/commands/Ansuz.md +36 -35
- package/core/.claude/hooks/__tests__/task-2395-project-registration.test.js +84 -0
- package/core/.claude/hooks/_ansuz-conversation.js +1 -0
- package/core/.claude/hooks/_ansuz-conversation.test.js +6 -0
- package/core/.claude/hooks/_run-user-prompt.js +0 -4
- package/core/.claude/hooks/_run-user-prompt.test.js +2 -3
- package/core/.claude/hooks/handoff-staleness.js +2 -2
- package/core/.claude/hooks/turn-context.js +50 -2
- package/core/.claude/settings.json +0 -37
- package/core/.collaboration/core/task-api.js +4 -12
- package/core/.formation/README.md +21 -146
- package/core/.formation/bifrost/codex-doctor.js +37 -2
- package/core/.formation/bifrost/codex-doctor.test.js +18 -0
- package/core/.formation/bifrost/launch.js +1 -1
- package/core/.formation/bifrost/openai/codex-hook-shim.js +6 -0
- package/core/.formation/bifrost/openai/codex-hook-shim.test.js +11 -1
- package/core/.formation/bifrost/setup-codex.js +3 -0
- package/core/.formation/spec/task_operations.parity.test.js +0 -1
- package/core/.formation/tools/dashboard-models-chain.test.js +0 -6
- package/core/.formation/tools/dispatch-detail/cross-project-worktree.md +1 -9
- package/core/.formation/tools/dispatch-detail/worktree-subagent-mode.md +2 -2
- package/core/.formation/tools/dispatch.js +28 -549
- package/core/.formation/tools/mcp-allowlist.test.js +0 -1
- package/core/.formation/tools/post-complete/task2345.test.js +0 -5
- package/core/.formation/tools/pre-dispatch-snapshot.test.js +0 -100
- package/core/.formation/tools/prompt.js +66 -1607
- package/core/.formation/tools/prompt.test.js +43 -582
- package/core/.kenaz/claude-hooks-manifest.json +16 -16
- package/core/.specialist/Ansuz/RULES.md +6 -10
- package/core/.specialist/tools/__tests__/freya-cli-contract.test.js +0 -1
- package/core/.specialist/tools/__tests__/task-2218-boot-session-id.test.js +17 -1
- package/core/.specialist/tools/__tests__/task-2222-session-identity-interleave.test.js +17 -1
- package/core/.specialist/tools/__tests__/task-2254-handoff-archive-contract.test.js +6 -5
- package/core/.specialist/tools/ansuz-boot-fast.js +44 -100
- package/core/.specialist/tools/ansuz-boot-fast.test.js +45 -1
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dev/plans/ANSUZ_SLIM_PLAN.md +68 -0
- package/core/plugins/kenaz/commands/Amelia.md +1 -1
- package/core/plugins/kenaz/commands/Ansuz.md +36 -35
- package/core/plugins/kenaz/hooks/hooks.json +1 -5
- package/core/plugins/kenaz/hooks/kenaz-hook.js +0 -4
- package/core/plugins/kenaz/scripts/kenaz-mode.js +11 -1
- package/core/plugins/kenaz/scripts/kenaz.test.js +1 -1
- package/core/plugins/kenaz/scripts/sync.js +6 -2
- package/core/plugins/kenaz/scripts/ygg.js +13 -1
- package/core/plugins/kenaz/skills/product_manager/SKILL.md +12 -12
- package/lib/cli.js +47 -6
- package/lib/cli.test.js +24 -0
- package/lib/dashboard.js +10 -0
- package/package.json +11 -7
- package/vendor/install-kenaz-cli.js +18 -7
- package/core/.formation/tools/broadcast.js +0 -103
- package/core/.formation/tools/dispatch-dryrun.test.js +0 -54
- package/core/.formation/tools/dispatch-notifier.js +0 -84
- package/core/.formation/tools/formations.js +0 -1203
- package/core/.formation/tools/headless-branch-recovery.test.js +0 -64
- package/core/.formation/tools/headless-dryrun.test.js +0 -79
- package/core/.formation/tools/headless-v2.js +0 -659
- package/core/.formation/tools/headless.js +0 -1071
- package/core/.formation/tools/legacy-scheduler.js +0 -1994
- package/core/.formation/tools/logger.js +0 -273
- package/core/.formation/tools/memory-loader.js +0 -422
- package/core/.formation/tools/process-state.js +0 -33
- package/core/.formation/tools/remote-conflict.js +0 -98
- package/core/.formation/tools/runner.js +0 -1332
- package/core/.formation/tools/task-utils.js +0 -344
- package/core/.formation/tools/task2028-headless-worktree.test.js +0 -112
- package/core/.formation/tools/tests/headless-mcp-args-plumbing.test.js +0 -123
- package/core/.formation/tools/worktree-leak.test.js +0 -162
- package/core/.specialist/tools/__tests__/task-1863-boot-lease-reuse.test.js +0 -99
- package/core/.specialist/tools/__tests__/task-1977-banner-cap.test.js +0 -129
|
@@ -31,8 +31,3 @@ test('post-complete sources contain no observe / huginn-think spawn path', () =>
|
|
|
31
31
|
assert.doesNotMatch(src, /triggerMuninnObserver|triggerHuginn|incrementMilestoneCounter|writeMuninnSignal|milestone_counter/, `${f} still references a removed trigger`);
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
|
-
|
|
35
|
-
test('headless.js has no observe-once / watch-mode / loop-heartbeat entry points', () => {
|
|
36
|
-
const src = read('headless.js');
|
|
37
|
-
assert.doesNotMatch(src, /--observe-once|--watch-mode|--loop-heartbeat|muninn-watcher/);
|
|
38
|
-
});
|
|
@@ -30,7 +30,6 @@ const { execSync } = require('child_process');
|
|
|
30
30
|
// Requiring post-complete wires initGitMerge(deps) as a load-time side effect.
|
|
31
31
|
require('./post-complete');
|
|
32
32
|
const { _gitMergeFromWorktree } = require('./post-complete/git-merge');
|
|
33
|
-
const { detectWorktreeLeak } = require('./runner');
|
|
34
33
|
const {
|
|
35
34
|
captureDispatchDirtySnapshot,
|
|
36
35
|
readDispatchDirtySnapshot,
|
|
@@ -93,105 +92,6 @@ function teardown(tmpRoot, repo) {
|
|
|
93
92
|
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
94
93
|
}
|
|
95
94
|
|
|
96
|
-
function listBranches(repo) {
|
|
97
|
-
return (gitSafe('git branch --format=%(refname:short)', repo) || '')
|
|
98
|
-
.split('\n').map(s => s.trim()).filter(Boolean);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
102
|
-
// DEFECT-D repro (TASK_1779 run 1): pre-existing dirty files + zero-commit agent
|
|
103
|
-
// → NO leak false positive, NO salvage branch, NO marker, NO exit-code flip.
|
|
104
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
105
|
-
|
|
106
|
-
test('TASK_1785 DEFECT-D: zero-commit + only pre-existing dirt is NOT a leak (no salvage branch)', () => {
|
|
107
|
-
const { tmpRoot, repo } = setup();
|
|
108
|
-
try {
|
|
109
|
-
const sessionId = 'sess1785-neg';
|
|
110
|
-
|
|
111
|
-
// Committed baseline the user then dirties BEFORE dispatch.
|
|
112
|
-
fs.writeFileSync(path.join(repo, 'usercfg.js'), 'module.exports = { v: 1 };\n');
|
|
113
|
-
git('git add usercfg.js', repo);
|
|
114
|
-
git('git commit --no-verify -m "seed usercfg"', repo);
|
|
115
|
-
|
|
116
|
-
// PRE-EXISTING user WIP: tracked modification + untracked file.
|
|
117
|
-
const userWip = 'module.exports = { v: 1, userEdit: true };\n';
|
|
118
|
-
fs.writeFileSync(path.join(repo, 'usercfg.js'), userWip);
|
|
119
|
-
fs.writeFileSync(path.join(repo, 'user-notes.md'), 'draft\n');
|
|
120
|
-
|
|
121
|
-
// Dispatch start: snapshot captured (what setupUnitWorktree does).
|
|
122
|
-
const snap = captureDispatchDirtySnapshot(repo, { sessionId, taskId: 'TASK_1785N' });
|
|
123
|
-
assert.ok(snap && snap.dirtyPaths.includes('usercfg.js') && snap.dirtyPaths.includes('user-notes.md'),
|
|
124
|
-
`snapshot must record pre-existing dirt, got ${JSON.stringify(snap && snap.dirtyPaths)}`);
|
|
125
|
-
|
|
126
|
-
// Agent worktree with ZERO commits (default bifrost state under DEFECT-A).
|
|
127
|
-
const worktree = path.join(tmpRoot, 'wt');
|
|
128
|
-
git(`git worktree add -b task/task_1785n "${worktree}" HEAD`, repo);
|
|
129
|
-
const originalWorktreeHead = git('git rev-parse HEAD', worktree);
|
|
130
|
-
|
|
131
|
-
const child = { _formation: { sessionId, skill: 'feature_agent' } };
|
|
132
|
-
const res = detectWorktreeLeak(worktree, originalWorktreeHead, child, repo);
|
|
133
|
-
|
|
134
|
-
// NOT a leak.
|
|
135
|
-
assert.equal(res, null, `pre-existing dirt must not be a leak, got ${JSON.stringify(res)}`);
|
|
136
|
-
assert.equal(child._formationExitCode, undefined, 'exit code must remain unset');
|
|
137
|
-
assert.ok(!child._formationLeak, 'no leak record');
|
|
138
|
-
// No salvage branch, no marker.
|
|
139
|
-
assert.ok(!listBranches(repo).some(b => b.startsWith('tn1529-salvage/')),
|
|
140
|
-
'no tn1529-salvage branch may be created for pre-existing dirt');
|
|
141
|
-
assert.ok(!fs.existsSync(path.join(worktree, 'LEAK_DETECTED')), 'no LEAK_DETECTED marker');
|
|
142
|
-
// User WIP untouched in the working tree.
|
|
143
|
-
assert.equal(fs.readFileSync(path.join(repo, 'usercfg.js'), 'utf8'), userWip, 'user WIP must stay untouched');
|
|
144
|
-
} finally {
|
|
145
|
-
teardown(tmpRoot, repo);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
150
|
-
// Positive control: a file NEWLY dirtied during the dispatch window IS still
|
|
151
|
-
// detected and salvaged — and the pre-existing file is excluded from the set.
|
|
152
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
153
|
-
|
|
154
|
-
test('TASK_1785 positive control: newly-dirty file during dispatch window is still detected + salvaged', () => {
|
|
155
|
-
const { tmpRoot, repo } = setup();
|
|
156
|
-
try {
|
|
157
|
-
const sessionId = 'sess1785-pos';
|
|
158
|
-
|
|
159
|
-
fs.writeFileSync(path.join(repo, 'usercfg.js'), 'user v1\n');
|
|
160
|
-
fs.writeFileSync(path.join(repo, 'agentfile.js'), 'agent v1\n');
|
|
161
|
-
git('git add usercfg.js agentfile.js', repo);
|
|
162
|
-
git('git commit --no-verify -m "seed"', repo);
|
|
163
|
-
|
|
164
|
-
// Pre-existing user WIP before dispatch.
|
|
165
|
-
fs.writeFileSync(path.join(repo, 'usercfg.js'), 'user v1 + WIP\n');
|
|
166
|
-
|
|
167
|
-
captureDispatchDirtySnapshot(repo, { sessionId, taskId: 'TASK_1785P' });
|
|
168
|
-
|
|
169
|
-
const worktree = path.join(tmpRoot, 'wt');
|
|
170
|
-
git(`git worktree add -b task/task_1785p "${worktree}" HEAD`, repo);
|
|
171
|
-
const originalWorktreeHead = git('git rev-parse HEAD', worktree);
|
|
172
|
-
|
|
173
|
-
// DURING the dispatch window: agent write leaks to MAIN repo (zero commits).
|
|
174
|
-
const leakedContent = 'agent v2 LEAKED\n';
|
|
175
|
-
fs.writeFileSync(path.join(repo, 'agentfile.js'), leakedContent);
|
|
176
|
-
|
|
177
|
-
const child = { _formation: { sessionId, skill: 'feature_agent' } };
|
|
178
|
-
const res = detectWorktreeLeak(worktree, originalWorktreeHead, child, repo);
|
|
179
|
-
|
|
180
|
-
assert.ok(res && res.leaked === true, `true leak must still be detected, got ${JSON.stringify(res)}`);
|
|
181
|
-
assert.deepEqual(res.leakedPaths, ['agentfile.js'],
|
|
182
|
-
`only the newly-dirty path counts as leak, got ${JSON.stringify(res.leakedPaths)}`);
|
|
183
|
-
assert.equal(child._formationExitCode, 1, 'true leak must still block the dispatch');
|
|
184
|
-
assert.ok(res.salvageBranch, 'true leak must still be salvaged');
|
|
185
|
-
assert.equal(gitSafe(`git show ${res.salvageBranch}:agentfile.js`, repo), leakedContent.trim(),
|
|
186
|
-
'salvage branch must contain the leaked content');
|
|
187
|
-
// Salvage tree is HEAD + leaked paths → the pre-existing WIP is NOT on it.
|
|
188
|
-
assert.equal(gitSafe(`git show ${res.salvageBranch}:usercfg.js`, repo), 'user v1',
|
|
189
|
-
'pre-existing user WIP must NOT be included in the leak salvage');
|
|
190
|
-
} finally {
|
|
191
|
-
teardown(tmpRoot, repo);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
|
|
195
95
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
196
96
|
// DEFECT-C repro: scopePaths=[] rescue scan must NOT sweep pre-existing user WIP
|
|
197
97
|
// (tracked modification AND untracked file) into the worktree/merge.
|