kenaz 0.3.9 → 0.3.11
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 +12 -16
- package/core/.claude/hooks/memory-guard.js +13 -0
- package/core/.claude/skills/code_reviewer/SKILL.md +0 -1
- package/core/.claude/skills/code_reviewer/patterns.yaml +0 -8
- package/core/.claude/skills/dev_agent/SKILL.md +3 -6
- package/core/.claude/skills/heimdall/SKILL.md +5 -6
- package/core/.claude/skills/huginn/SKILL.md +11 -38
- package/core/.collaboration/core/task-api.js +2 -218
- package/core/.collaboration/core/task-api.test.js +1 -138
- package/core/.formation/bifrost/launch.js +2 -2
- package/core/.formation/bifrost/launch.test.js +2 -2
- package/core/.formation/bifrost/shared/ansuz-boot-policy.js +3 -3
- package/core/.formation/bifrost/shared/codex-injection.js +3 -17
- package/core/.formation/bifrost/shared/consolidate.js +1 -51
- package/core/.formation/bifrost/sync.js +4 -5
- package/core/.formation/tools/__tests__/subagent-bifrost-guard.test.js +1 -1
- package/core/.formation/tools/dispatch.js +2 -2
- package/core/.formation/tools/kenaz-stats.js +259 -0
- package/core/.formation/tools/kenaz-stats.test.js +180 -0
- package/core/.formation/tools/mcp-allowlist.test.js +5 -3
- package/core/.formation/tools/post-complete/bounded-http.js +1 -40
- package/core/.formation/tools/post-complete/bounded-http.test.js +2 -89
- package/core/.formation/tools/post-complete/cognitive.js +2 -119
- package/core/.formation/tools/post-complete/testing.js +3 -21
- package/core/.formation/tools/post-complete.js +2 -428
- package/core/.formation/tools/post-complete.test.js +0 -135
- package/core/.formation/tools/prompt.js +14 -0
- package/core/.formation/tools/route-audit.test.js +8 -20
- package/core/.rule/INDEX.yaml +3 -3
- package/core/.rule/general/ddx-synapse-stack.yaml +11 -11
- package/core/.rule/general/specialist-identity-contract.yaml +5 -5
- package/core/.rule/general/synapse-code-intelligence.yaml +25 -111
- package/core/.rule/general/worktree-isolation.yaml +2 -2
- package/core/.rule/pipeline/task-execution.yaml +6 -9
- package/core/.specialist/Amelia/README.md +5 -5
- package/core/.specialist/Amelia/capability.yaml +10 -18
- package/core/.specialist/Amelia/knowledge.yaml +15 -66
- package/core/.specialist/Amelia/workflow.yaml +12 -21
- package/core/.specialist/Ansuz/RULES.md +6 -0
- package/core/.specialist/Ansuz/capability.yaml +12 -87
- package/core/.specialist/Ansuz/concepts/autonomous_agenda.yaml +1 -1
- package/core/.specialist/Ansuz/concepts/autonomy_contract.yaml +2 -3
- package/core/.specialist/Ansuz/concepts/capability_pointers.yaml +1 -3
- package/core/.specialist/Ansuz/concepts/cognitive_fluency_contract.yaml +8 -21
- package/core/.specialist/Ansuz/concepts/cognitive_systems_overview.yaml +0 -4
- package/core/.specialist/Ansuz/concepts/cognitive_systems_turn_context.yaml +1 -1
- package/core/.specialist/Ansuz/concepts/completion_tracking.yaml +0 -1
- package/core/.specialist/Ansuz/concepts/deep_knowledge_pointers.yaml +0 -3
- package/core/.specialist/Ansuz/concepts/evolvable_guardrails.yaml +3 -3
- package/core/.specialist/Ansuz/concepts/fatigue_handoff.yaml +1 -7
- package/core/.specialist/Ansuz/concepts/guardrails_immutable.yaml +3 -4
- package/core/.specialist/Ansuz/concepts/identity.yaml +1 -2
- package/core/.specialist/Ansuz/concepts/phase9_verification.yaml +0 -1
- package/core/.specialist/Ansuz/concepts/phase_protocol.yaml +3 -4
- package/core/.specialist/Ansuz/core.yaml +3 -6
- package/core/.specialist/Ansuz/elixir.yaml +6 -6
- package/core/.specialist/Ansuz/exo_cortex_tools.yaml +5 -9
- package/core/.specialist/Ansuz/guards/blind_spot_guards.yaml +2 -2
- package/core/.specialist/Ansuz/guards/lesson_guards.yaml +6 -19
- package/core/.specialist/Ansuz/identity_contract.yaml +4 -4
- package/core/.specialist/Ansuz/knowledge.yaml +13 -40
- package/core/.specialist/Ansuz/modules/ddx.yaml +2 -2
- package/core/.specialist/Ansuz/modules/prophecy.yaml +19 -19
- package/core/.specialist/Ansuz/modules/pulse_empty.yaml +6 -17
- package/core/.specialist/Ansuz/tools/ansuz-handoff-snapshot.js +3 -102
- package/core/.specialist/Ansuz/tools/ansuz-sdk-runner.js +2 -44
- package/core/.specialist/Ansuz/workflow.yaml +32 -76
- package/core/.specialist/Forseti/core.yaml +2 -7
- package/core/.specialist/Forseti/rule.yaml +1 -1
- package/core/.specialist/Heimdall/SKILL.md +2 -3
- package/core/.specialist/Heimdall/capability.yaml +22 -45
- package/core/.specialist/Heimdall/core.yaml +24 -126
- package/core/.specialist/Heimdall/principles.yaml +8 -11
- package/core/.specialist/Heimdall/rule.yaml +2 -2
- package/core/.specialist/Huginn/capability.yaml +31 -52
- package/core/.specialist/Huginn/core.yaml +43 -123
- package/core/.specialist/Huginn/principles.yaml +5 -5
- package/core/.specialist/Huginn/rule.yaml +3 -9
- package/core/.specialist/REFLECTION_TO_CONTROL.md +3 -4
- package/core/.specialist/shared/guard_schema.json +1 -1
- package/core/.specialist/shared/principles.yaml +6 -6
- package/core/.specialist/tools/__tests__/task-2409-lessons.test.js +95 -0
- package/core/.specialist/tools/ansuz-boot-fast.js +1 -0
- package/core/.specialist/tools/lessons.js +234 -0
- package/core/.specialist/tools/phase-gate.js +10 -230
- package/core/.specialist/tools/phase-gate.test.js +2 -2
- package/core/.specialist/tools/prompt-files.test.js +1 -1
- package/core/.specialist/tools/session.js +2 -89
- package/core/.system/memory/README.md +3 -0
- package/core/CLAUDE.md +6 -7
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +26 -0
- package/core/plugins/kenaz/INVENTORY.md +1 -1
- package/core/plugins/kenaz/commands/Ansuz.md +12 -16
- package/core/plugins/kenaz/scripts/kenaz.test.js +2 -1
- package/core/plugins/kenaz/scripts/ygg.js +2 -0
- package/core/plugins/kenaz/skills/code_reviewer/SKILL.md +0 -1
- package/core/plugins/kenaz/skills/code_reviewer/patterns.yaml +0 -8
- package/core/plugins/kenaz/skills/dev_agent/SKILL.md +3 -6
- package/lib/cli.js +13 -3
- package/package.json +6 -6
- package/core/.claude/hooks/handoff-snapshot-on-decision.js +0 -188
- package/core/.claude/skills/synapse_maintain/SKILL.md +0 -84
- package/core/.formation/tools/alaya-gate.js +0 -198
- package/core/.formation/tools/post-complete/health.js +0 -464
- package/core/.formation/tools/post-complete/task2038.test.js +0 -246
- package/core/.formation/tools/post-complete/task2341.test.js +0 -74
- package/core/.rule/general/cortex-tools.yaml +0 -181
- package/core/.rule/general/memory-language.yaml +0 -67
- package/core/.rule/general/memory-source-priority.yaml +0 -207
- package/core/.rule/general/synapse-cognitive-fusion.yaml +0 -301
- package/core/.specialist/Ansuz/concepts/cognitive_systems_hippocampus.yaml +0 -14
- package/core/.specialist/Ansuz/concepts/write_verification.yaml +0 -26
- package/core/.specialist/Ansuz/modules/recall.yaml +0 -45
- package/core/.specialist/tools/MEMORY_RECALL_TRIGGERS.md +0 -156
- package/core/.specialist/tools/context-injection.js +0 -395
- package/core/dev/scripts/probe/hippocampus-concurrency.js +0 -247
|
@@ -12,11 +12,6 @@ const {
|
|
|
12
12
|
checkAndUpdatePostCompleteGuard,
|
|
13
13
|
writeInboxEntryIdempotent,
|
|
14
14
|
} = require('./post-complete');
|
|
15
|
-
const {
|
|
16
|
-
saveTaskHealthSnapshot,
|
|
17
|
-
readPreTaskHealthSnapshot,
|
|
18
|
-
resolveMcpProjectPath,
|
|
19
|
-
} = require('./post-complete/health');
|
|
20
15
|
const {
|
|
21
16
|
isAutoWritePath,
|
|
22
17
|
filterOutcomeFilesForPrediction,
|
|
@@ -770,136 +765,6 @@ test('checkAndUpdatePostCompleteGuard: worktree→null still fires (TASK_1430)',
|
|
|
770
765
|
}
|
|
771
766
|
});
|
|
772
767
|
|
|
773
|
-
// ── Health snapshot enrichment tests (TASK_1431) ─────────────────────────────
|
|
774
|
-
|
|
775
|
-
test('saveTaskHealthSnapshot: delta_from_previous computed against most recent prior _after snapshot', () => {
|
|
776
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-health-delta-'));
|
|
777
|
-
try {
|
|
778
|
-
const snapshotsDir = path.join(tmpRoot, '.kenaz', 'health_snapshots');
|
|
779
|
-
fs.mkdirSync(snapshotsDir, { recursive: true });
|
|
780
|
-
|
|
781
|
-
// Write a prior _after snapshot with a slightly older timestamp
|
|
782
|
-
fs.writeFileSync(
|
|
783
|
-
path.join(snapshotsDir, 'TASK_100_after.json'),
|
|
784
|
-
JSON.stringify({
|
|
785
|
-
score: 45.0, grade: 'F (Critical)', score_version: 'memory-v1',
|
|
786
|
-
timestamp: new Date(Date.now() - 10000).toISOString(), sub_metrics: {},
|
|
787
|
-
}, null, 2)
|
|
788
|
-
);
|
|
789
|
-
|
|
790
|
-
saveTaskHealthSnapshot('TASK_200', 'after', { score: 47.0, grade: 'F (Critical)', sub_metrics: { degree_entropy: { score: 60 } } }, tmpRoot);
|
|
791
|
-
|
|
792
|
-
const saved = JSON.parse(fs.readFileSync(path.join(snapshotsDir, 'TASK_200_after.json'), 'utf8'));
|
|
793
|
-
assert.equal(saved.score, 47.0);
|
|
794
|
-
assert.equal(saved.delta_from_previous, 2.0, 'delta should be 47 - 45 = 2.0');
|
|
795
|
-
assert.equal(saved.trend_5tasks, null, 'trend_5tasks is null when <5 priors');
|
|
796
|
-
assert.ok(saved.sub_metrics && typeof saved.sub_metrics === 'object', 'sub_metrics should be present');
|
|
797
|
-
assert.ok(saved.timestamp, 'timestamp must be present');
|
|
798
|
-
} finally {
|
|
799
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
800
|
-
}
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
test('saveTaskHealthSnapshot: trend_5tasks=null when fewer than 5 prior _after snapshots', () => {
|
|
804
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-health-trend4-'));
|
|
805
|
-
try {
|
|
806
|
-
const snapshotsDir = path.join(tmpRoot, '.kenaz', 'health_snapshots');
|
|
807
|
-
fs.mkdirSync(snapshotsDir, { recursive: true });
|
|
808
|
-
|
|
809
|
-
// Write exactly 4 prior _after snapshots (one short of 5)
|
|
810
|
-
for (let i = 0; i < 4; i++) {
|
|
811
|
-
fs.writeFileSync(
|
|
812
|
-
path.join(snapshotsDir, `TASK_${100 + i}_after.json`),
|
|
813
|
-
JSON.stringify({
|
|
814
|
-
score: 45.0 + i, grade: 'F (Critical)', score_version: 'memory-v1',
|
|
815
|
-
timestamp: new Date(Date.now() - (4 - i) * 10000).toISOString(), sub_metrics: {},
|
|
816
|
-
}, null, 2)
|
|
817
|
-
);
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
saveTaskHealthSnapshot('TASK_200', 'after', { score: 50.0, grade: 'D (Poor)', sub_metrics: {} }, tmpRoot);
|
|
821
|
-
|
|
822
|
-
const saved = JSON.parse(fs.readFileSync(path.join(snapshotsDir, 'TASK_200_after.json'), 'utf8'));
|
|
823
|
-
assert.equal(saved.trend_5tasks, null, 'trend_5tasks must be null when only 4 priors exist');
|
|
824
|
-
assert.ok(typeof saved.delta_from_previous === 'number', 'delta_from_previous should be a number when 1+ prior exists');
|
|
825
|
-
} finally {
|
|
826
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
827
|
-
}
|
|
828
|
-
});
|
|
829
|
-
|
|
830
|
-
test('saveTaskHealthSnapshot: trend_5tasks computed when exactly 5 prior snapshots exist', () => {
|
|
831
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-health-trend5-'));
|
|
832
|
-
try {
|
|
833
|
-
const snapshotsDir = path.join(tmpRoot, '.kenaz', 'health_snapshots');
|
|
834
|
-
fs.mkdirSync(snapshotsDir, { recursive: true });
|
|
835
|
-
|
|
836
|
-
// 5 prior snapshots: scores 40,41,42,43,44 (newest=44 at i=4, oldest=40 at i=0)
|
|
837
|
-
for (let i = 0; i < 5; i++) {
|
|
838
|
-
fs.writeFileSync(
|
|
839
|
-
path.join(snapshotsDir, `TASK_${100 + i}_after.json`),
|
|
840
|
-
JSON.stringify({
|
|
841
|
-
score: 40.0 + i, grade: 'F (Critical)', score_version: 'memory-v1',
|
|
842
|
-
timestamp: new Date(Date.now() - (5 - i) * 10000).toISOString(), sub_metrics: {},
|
|
843
|
-
}, null, 2)
|
|
844
|
-
);
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
// current score=50; priors newest-first=[44,43,42,41,40]; 5th prior = 40
|
|
848
|
-
// trend_5tasks = 50 - 40 = 10
|
|
849
|
-
saveTaskHealthSnapshot('TASK_200', 'after', { score: 50.0, grade: 'D (Poor)', sub_metrics: {} }, tmpRoot);
|
|
850
|
-
|
|
851
|
-
const saved = JSON.parse(fs.readFileSync(path.join(snapshotsDir, 'TASK_200_after.json'), 'utf8'));
|
|
852
|
-
assert.equal(saved.trend_5tasks, 10.0, 'trend_5tasks = currentScore - score5TasksAgo = 50 - 40');
|
|
853
|
-
assert.equal(saved.delta_from_previous, 6.0, 'delta_from_previous = 50 - 44 (most recent prior)');
|
|
854
|
-
} finally {
|
|
855
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
856
|
-
}
|
|
857
|
-
});
|
|
858
|
-
|
|
859
|
-
test('saveTaskHealthSnapshot: sub_metrics object passes through from health response', () => {
|
|
860
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-health-subm-'));
|
|
861
|
-
try {
|
|
862
|
-
const snapshotsDir = path.join(tmpRoot, '.kenaz', 'health_snapshots');
|
|
863
|
-
fs.mkdirSync(snapshotsDir, { recursive: true });
|
|
864
|
-
|
|
865
|
-
const subMetrics = {
|
|
866
|
-
degree_entropy: { score: 60.5, weight: 0.25, excluded_count: 3 },
|
|
867
|
-
community_balance: { score: 45.0, weight: 0.20 },
|
|
868
|
-
};
|
|
869
|
-
saveTaskHealthSnapshot('TASK_300', 'after', { score: 52.0, grade: 'D (Poor)', sub_metrics: subMetrics }, tmpRoot);
|
|
870
|
-
|
|
871
|
-
const saved = JSON.parse(fs.readFileSync(path.join(snapshotsDir, 'TASK_300_after.json'), 'utf8'));
|
|
872
|
-
assert.deepEqual(saved.sub_metrics, subMetrics, 'sub_metrics should be stored unchanged');
|
|
873
|
-
} finally {
|
|
874
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
875
|
-
}
|
|
876
|
-
});
|
|
877
|
-
|
|
878
|
-
test('readPreTaskHealthSnapshot: old snapshot without enrichment fields loads without error', () => {
|
|
879
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'pc-health-compat-'));
|
|
880
|
-
try {
|
|
881
|
-
const snapshotsDir = path.join(tmpRoot, '.kenaz', 'health_snapshots');
|
|
882
|
-
fs.mkdirSync(snapshotsDir, { recursive: true });
|
|
883
|
-
|
|
884
|
-
// Old-format snapshot: only score, grade, timestamp (no sub_metrics/delta/trend)
|
|
885
|
-
fs.writeFileSync(
|
|
886
|
-
path.join(snapshotsDir, 'TASK_OLD_before.json'),
|
|
887
|
-
JSON.stringify({ score: 48.0, grade: 'F (Critical)', timestamp: new Date().toISOString() }, null, 2)
|
|
888
|
-
);
|
|
889
|
-
|
|
890
|
-
const sn = readPreTaskHealthSnapshot('TASK_OLD', tmpRoot);
|
|
891
|
-
assert.ok(sn, 'old snapshot should load without error');
|
|
892
|
-
assert.equal(sn.score, 48.0, 'score should be readable');
|
|
893
|
-
// New fields are absent in old snapshots — undefined is fine, not an error
|
|
894
|
-
assert.equal(sn.delta_from_previous, undefined, 'missing delta_from_previous is undefined not error');
|
|
895
|
-
assert.equal(sn.sub_metrics, undefined, 'missing sub_metrics is undefined not error');
|
|
896
|
-
} finally {
|
|
897
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
898
|
-
}
|
|
899
|
-
});
|
|
900
|
-
|
|
901
|
-
// ---- TASK_1674: untracked-path collision tests --------------------------------
|
|
902
|
-
|
|
903
768
|
test('_neutralizeUntrackedCollisions: TASK_1674 -- untracked file collides with task-branch-added path, merge proceeds and WIP preserved', () => {
|
|
904
769
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "pc-t1674-"));
|
|
905
770
|
try {
|
|
@@ -167,6 +167,10 @@ function buildSubagentPrompt(skillDef, taskInput, taskData, options = {}) {
|
|
|
167
167
|
lines.push('');
|
|
168
168
|
appendRustCheckReminder(lines, taskData, options, isIsolated);
|
|
169
169
|
|
|
170
|
+
// TASK_2409: lessons the user's Ansuz learned for this project (bounded; nothing is added when there are none).
|
|
171
|
+
const learned = projectLessons(taskData, options);
|
|
172
|
+
if (learned.facts.length) lines.push('## Project lessons', ...learned.facts, '');
|
|
173
|
+
|
|
170
174
|
lines.push('## Verify and report');
|
|
171
175
|
// Ponytail A/B 2026-10-10: the arm without this line broke an existing fixture test it never ran.
|
|
172
176
|
lines.push('Before editing, grep the callers, tests and fixtures your change reaches; fix what it breaks. Least code that completes the card: reuse existing helpers, no unrequested abstraction, option or duplicate implementation.');
|
|
@@ -179,12 +183,22 @@ function buildSubagentPrompt(skillDef, taskInput, taskData, options = {}) {
|
|
|
179
183
|
if (onBlocked && onBlocked.run) {
|
|
180
184
|
lines.push(`Blocked: \`${buildTaskApiRewriter(options)(onBlocked.run).replace(/\{task_id\}/g, taskId)}\` and explain.`);
|
|
181
185
|
}
|
|
186
|
+
for (const c of learned.checks) lines.push(`Project check: ${c.slice(2)}`);
|
|
182
187
|
lines.push('Final report <= 20 lines: files touched, tests run, commit sha, unverified items.');
|
|
183
188
|
lines.push('');
|
|
184
189
|
appendDispatchOverrides(lines, taskData);
|
|
185
190
|
return lines.join('\n');
|
|
186
191
|
}
|
|
187
192
|
|
|
193
|
+
function projectLessons(taskData, options) {
|
|
194
|
+
const none = { facts: [], checks: [] };
|
|
195
|
+
if (!options.projectPath) return none;
|
|
196
|
+
try {
|
|
197
|
+
const parsed = typeof taskData === 'string' ? JSON.parse(taskData) : taskData;
|
|
198
|
+
return require('../../.specialist/tools/lessons').dispatchLessons(options.projectPath, (parsed && parsed.scope_paths) || []);
|
|
199
|
+
} catch { return none; }
|
|
200
|
+
}
|
|
201
|
+
|
|
188
202
|
function extractTaskId(taskData) {
|
|
189
203
|
try {
|
|
190
204
|
const parsed = typeof taskData === 'string' ? JSON.parse(taskData) : taskData;
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
//
|
|
3
|
-
// .specialist, .collaboration)
|
|
2
|
+
// TASK_2411: the memory system (synapse/hippocampus/cortex recall) and its /api/synapse router are gone, so no node
|
|
3
|
+
// code (.formation, .claude/hooks, .specialist, .collaboration) may call /api/synapse/* or /api/cortex/*.
|
|
4
4
|
const { test } = require('node:test');
|
|
5
5
|
const assert = require('node:assert/strict');
|
|
6
6
|
const fs = require('fs');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
|
|
9
9
|
const ROOT = path.resolve(__dirname, '..', '..');
|
|
10
|
-
const SYNAPSE_RS = path.join(ROOT, 'dashboard', 'src-tauri', 'src', 'infrastructure', 'http_server', 'routes', 'synapse.rs');
|
|
11
10
|
const SCAN_DIRS = ['.formation', '.claude/hooks', '.specialist', '.collaboration'];
|
|
12
11
|
const SKIP = /node_modules|[\/](logs|sessions|reports|designs|research|investigations|decisions)[\/]|\.test\.js$/;
|
|
13
12
|
|
|
14
|
-
function routerPaths() {
|
|
15
|
-
const src = fs.readFileSync(SYNAPSE_RS, 'utf8');
|
|
16
|
-
const body = src.slice(src.indexOf('pub fn router()'), src.indexOf('#[cfg(test)]'));
|
|
17
|
-
return new Set([...body.matchAll(/\.route\(\s*"([^"]+)"/g)].map(m => '/api/synapse' + m[1]));
|
|
18
|
-
}
|
|
19
13
|
function walk(dir, out) {
|
|
20
14
|
if (!fs.existsSync(dir)) return out;
|
|
21
15
|
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
@@ -38,18 +32,12 @@ function calledPaths() {
|
|
|
38
32
|
return found;
|
|
39
33
|
}
|
|
40
34
|
|
|
41
|
-
test('
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
assert.ok(!r.has('/api/synapse/link-cognitive') && !r.has('/api/synapse/health'));
|
|
45
|
-
// TASK_2348: the spike bus and the reflex routes are gone
|
|
46
|
-
for (const p of ['/api/synapse/spike-bus/send', '/api/synapse/spike-bus/poll', '/api/synapse/reflex/feedback', '/api/synapse/reflex/dispatch/query', '/api/synapse/reflex/dopamine', '/api/synapse/reflex/consequence_feedback']) assert.ok(!r.has(p), p);
|
|
35
|
+
test('no node code calls the removed /api/synapse or /api/cortex routes', () => {
|
|
36
|
+
const calls = calledPaths();
|
|
37
|
+
assert.deepEqual(calls, [], 'callers of removed routes: ' + JSON.stringify(calls));
|
|
47
38
|
});
|
|
48
39
|
|
|
49
|
-
test('
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
assert.ok(calls.length >= 1, 'expected to find callers'); // turn-context.js stopped calling /turn-context (Kuzu removal)
|
|
53
|
-
const missing = calls.filter(c => !r.has(c.p));
|
|
54
|
-
assert.deepEqual(missing, [], 'callers of removed routes: ' + JSON.stringify(missing));
|
|
40
|
+
test('control: the scanner does find a /api/synapse path in a line of code', () => {
|
|
41
|
+
const line = "fetch('http://127.0.0.1:18080/api/synapse/recall')";
|
|
42
|
+
assert.ok([...line.matchAll(/\/api\/(synapse|cortex)\/[A-Za-z0-9_\-/]+/g)].length === 1);
|
|
55
43
|
});
|
package/core/.rule/INDEX.yaml
CHANGED
|
@@ -27,10 +27,10 @@ load_order:
|
|
|
27
27
|
- path: "general/sunny-access-control.yaml"
|
|
28
28
|
description: "SEC-010: Sunny 系統存取控制 - 禁止其他 Agent 存取 .system/sunny/"
|
|
29
29
|
- path: "general/synapse-code-intelligence.yaml"
|
|
30
|
-
description: "SYN-001~007: 代碼導航 — kenaz_lsp_* 代碼導航、Grep/Glob
|
|
31
|
-
# 2026-10-
|
|
30
|
+
description: "SYN-001~007: 代碼導航 — kenaz_lsp_* 代碼導航、Grep/Glob 文字與概念搜尋。記憶層 synapse_* 工具已於 2026-10-11 移除(TASK_2411)"
|
|
31
|
+
# 2026-10-11 (TASK_2411): synapse-cognitive-fusion.yaml, cortex-tools.yaml, memory-source-priority.yaml, memory-language.yaml deleted - memory system removed.
|
|
32
32
|
- path: "general/ddx-synapse-stack.yaml"
|
|
33
|
-
description: "COG-DDX-001~003: DDx 反射 — 非 trivial 問題強制先列 3+ 假說,對抗 tunneling(
|
|
33
|
+
description: "COG-DDX-001~003: DDx 反射 — 非 trivial 問題強制先列 3+ 假說,對抗 tunneling(recall 步驟改用 Grep/讀碼/記憶檔;synapse_* 已於 2026-10-11 移除)"
|
|
34
34
|
- path: "general/specialist-identity-contract.yaml"
|
|
35
35
|
description: "IDENT-001~007: Specialist 身份延續合約 — 不可變核心、可進化規則、可觀測標記、漂移指標、verify-identity.js 驗證流程"
|
|
36
36
|
- path: "general/worktree-isolation.yaml"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# .rule/general/ddx-synapse-stack.yaml
|
|
2
|
-
# COG-DDX-001: DDx
|
|
2
|
+
# COG-DDX-001: DDx reflex stack
|
|
3
|
+
# NOTE 2026-10-11 (TASK_2411): synapse_* tools were removed; recall steps use Grep + native memory. for any non-trivial problem
|
|
3
4
|
# Priority: overrides CLAUDE.md and .claude/skills/
|
|
4
5
|
# Origin: 2026-04-05 Ansuz session — user identified that DDx + Synapse + Thalamus
|
|
5
6
|
# is the strongest operating mode but is never activated without user prompt.
|
|
@@ -13,11 +14,10 @@ _meta:
|
|
|
13
14
|
last_updated: "2026-04-05"
|
|
14
15
|
related:
|
|
15
16
|
- "synapse-code-intelligence.yaml"
|
|
16
|
-
- "synapse-cognitive-fusion.yaml"
|
|
17
17
|
|
|
18
18
|
rules:
|
|
19
19
|
- id: "COG-DDX-001"
|
|
20
|
-
title: "DDx
|
|
20
|
+
title: "DDx reflex stack — mandatory on first contact with any non-trivial problem"
|
|
21
21
|
severity: "must"
|
|
22
22
|
applies_to: ["ai_agent"]
|
|
23
23
|
|
|
@@ -35,16 +35,16 @@ rules:
|
|
|
35
35
|
BEFORE the first domain tool call that touches the subject, the agent must:
|
|
36
36
|
1. List 3+ competing hypotheses with one-line evidence each
|
|
37
37
|
(differential diagnosis, not first-instinct single path)
|
|
38
|
-
2.
|
|
39
|
-
(
|
|
40
|
-
3. When modifying any code symbol:
|
|
38
|
+
2. Grep/Glob domain keywords and check native memory files / `kenaz learn list`
|
|
39
|
+
(prior lessons may already contain the answer)
|
|
40
|
+
3. When modifying any code symbol: check kenaz_lsp_references / kenaz_lsp_callers for the blast radius
|
|
41
41
|
|
|
42
42
|
These three steps are a STACK — skipping any one of them is a violation.
|
|
43
43
|
|
|
44
44
|
why: |
|
|
45
45
|
Observed failure mode (2026-04-05 TR87 session): agent tunneled 15
|
|
46
46
|
iterations on a dead hypothesis, attempted brute-force BFS search,
|
|
47
|
-
|
|
47
|
+
searched prior knowledge only reactively. User forced explicit DDx; puzzle
|
|
48
48
|
then cracked in 3 steps.
|
|
49
49
|
Lesson: principles-as-text do not trigger reflexively. The stack must be
|
|
50
50
|
a structural precommitment, not an optional heuristic.
|
|
@@ -55,12 +55,12 @@ rules:
|
|
|
55
55
|
- You are "trying variants" of a single idea after disconfirmation
|
|
56
56
|
- You are reaching for brute-force enumeration or search
|
|
57
57
|
- You cannot name 2 hypotheses besides the one you are pursuing
|
|
58
|
-
- You have not
|
|
58
|
+
- You have not searched code/native memory this session on the current topic
|
|
59
59
|
|
|
60
60
|
enforcement: |
|
|
61
61
|
- Phase 1 (needs analysis) exit requires hypotheses[] with length >= 3
|
|
62
62
|
OR an explicit note that problem is trivial (scope exception)
|
|
63
|
-
- Phase 2 (background research) exit requires
|
|
63
|
+
- Phase 2 (background research) exit requires evidence of Grep/read-code research
|
|
64
64
|
- Kernel guardrails enforce at dispatch time
|
|
65
65
|
|
|
66
66
|
examples:
|
|
@@ -69,14 +69,14 @@ rules:
|
|
|
69
69
|
H1: auth token expired/invalid (check expiry logic)
|
|
70
70
|
H2: session store disconnected (check Redis/DB)
|
|
71
71
|
H3: CORS/cookie path changed (check recent config diffs)
|
|
72
|
-
|
|
72
|
+
Grep "login auth token session", kenaz_lsp_callers on
|
|
73
73
|
the entrypoint — THEN read code.
|
|
74
74
|
design_decision: |
|
|
75
75
|
User asks "should we use Redis or Postgres pub/sub?" BEFORE recommending:
|
|
76
76
|
H1: Redis if latency < 10ms matters and durability is optional
|
|
77
77
|
H2: Postgres if ACID + existing infra reuse wins
|
|
78
78
|
H3: Neither — use in-process channels if single-node
|
|
79
|
-
|
|
79
|
+
Grep/native memory for "pub sub messaging event bus" to find prior decisions.
|
|
80
80
|
|
|
81
81
|
- id: "COG-DDX-002"
|
|
82
82
|
title: "Hypothesis death triggers immediate DDx re-enumeration"
|
|
@@ -35,8 +35,8 @@ rules:
|
|
|
35
35
|
The identity_contract.yaml is referenced (not duplicated) — the
|
|
36
36
|
self_model_seed.json NARRATIVE section encodes the contract's intent.
|
|
37
37
|
enforcement: |
|
|
38
|
-
Phase 0 actions item "[Tier 3b — 身份認識]"
|
|
39
|
-
Ansuz identity awareness. A session that skips Phase 0 has no identity.
|
|
38
|
+
Phase 0 actions item "[Tier 3b — 身份認識]" loads the self-model
|
|
39
|
+
files for Ansuz identity awareness (cortex_recall removed 2026-10-11). A session that skips Phase 0 has no identity.
|
|
40
40
|
violation: "DI-001 — no phase structure visible"
|
|
41
41
|
source: "dev/archive/ansuz/legacy/phases/phase_0.yaml → actions[Tier 3b]"
|
|
42
42
|
|
|
@@ -44,12 +44,12 @@ rules:
|
|
|
44
44
|
title: "Observable markers are evaluated at Phase 9 cognitive checkpoint"
|
|
45
45
|
rule: |
|
|
46
46
|
During Phase 9 cognitive checkpoint, the session MUST evaluate:
|
|
47
|
-
1. cognitive_checkpoint_compliance (OM-001) —
|
|
47
|
+
1. cognitive_checkpoint_compliance (OM-001) — lesson recorded (`kenaz learn add` / native memory) or explicit skip
|
|
48
48
|
2. acceptance_criteria_evaluation (OM-002) — all criteria have status
|
|
49
49
|
These two markers carry 0.45 of the total identity score. Skipping both
|
|
50
50
|
guarantees DRIFT_WARNING even if all other markers pass.
|
|
51
51
|
enforcement: |
|
|
52
|
-
Phase 9 checklist item: "cognitive_checkpoint
|
|
52
|
+
Phase 9 checklist item: "cognitive_checkpoint 已判斷(記錄教訓或明確跳過)"
|
|
53
53
|
and acceptance criteria evaluation in progress note.
|
|
54
54
|
violation: "DI-005 — Phase 9 cognitive checkpoint absent"
|
|
55
55
|
source: "dev/archive/ansuz/legacy/phases/phase_9.yaml → cognitive_checkpoint"
|
|
@@ -88,7 +88,7 @@ rules:
|
|
|
88
88
|
When evaluating identity across model substrates (e.g., Opus 4.6 vs Sonnet 4.6),
|
|
89
89
|
the following differences are acceptable and MUST NOT be flagged as drift:
|
|
90
90
|
- Response verbosity differences
|
|
91
|
-
- Different
|
|
91
|
+
- Different tool choices for equivalent lookup
|
|
92
92
|
- Analysis depth differences
|
|
93
93
|
- Phrasing variation in principles
|
|
94
94
|
Identity is evaluated on STRUCTURE (phase discipline, task system, memory usage,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# .rule/general/synapse-code-intelligence.yaml
|
|
2
|
-
#
|
|
2
|
+
# 代碼導航規則 — Agent 何時、如何使用 kenaz_lsp_* / Grep / Glob
|
|
3
3
|
# 優先級:此規則凌駕於 CLAUDE.md 和 .claude/skills/ 中的定義
|
|
4
4
|
#
|
|
5
5
|
# TASK_2335(Kuzu replacement W5a):Synapse 的代碼圖譜(search / context / impact / pulse / map /
|
|
6
6
|
# cypher / trace_route / detect_changes 等)已移除。代碼導航改由 kenaz_lsp_* 工具提供;
|
|
7
|
-
# 文字與概念搜尋用 Grep / Glob
|
|
7
|
+
# 文字與概念搜尋用 Grep / Glob。記憶層(synapse_*)已於 2026-10-11 移除(TASK_2411)。
|
|
8
8
|
# 規則編號 SYN-001~007 保持不變(其他規則與失敗記錄以編號引用)。
|
|
9
9
|
|
|
10
10
|
_meta:
|
|
@@ -23,21 +23,20 @@ rules:
|
|
|
23
23
|
title: "工具可用性偵測"
|
|
24
24
|
description: |
|
|
25
25
|
每個 session 開始時,偵測 Kenaz MCP 工具是否可用。
|
|
26
|
-
kenaz_lsp_*
|
|
26
|
+
kenaz_lsp_* 依賴 Dashboard(Rust HTTP server on port 18080);
|
|
27
27
|
Dashboard 沒啟動時,MCP 工具不會出現在工具列表中。
|
|
28
28
|
severity: "must"
|
|
29
29
|
|
|
30
30
|
detection_method: |
|
|
31
|
-
使用 ToolSearch 搜尋 "
|
|
32
|
-
- 找到 synapse_status / synapse_recall → 記憶層可用
|
|
31
|
+
使用 ToolSearch 搜尋 "kenaz_lsp"(代碼導航工具):
|
|
33
32
|
- 找到 kenaz_lsp_callers / kenaz_lsp_references → LSP 導航可用
|
|
34
|
-
- 沒找到 →
|
|
33
|
+
- 沒找到 → 不可用,降級為 Grep/Glob
|
|
35
34
|
|
|
36
35
|
on_unavailable: |
|
|
37
36
|
該 session 全程使用 Grep/Glob,不再嘗試已確認不可用的工具。
|
|
38
37
|
|
|
39
38
|
project_path_mandatory: |
|
|
40
|
-
⚠️ 所有 kenaz_lsp_*
|
|
39
|
+
⚠️ 所有 kenaz_lsp_* MCP 工具呼叫必須明確帶 projectPath 參數。
|
|
41
40
|
Dashboard 的 active project 可能指向其他專案,default project 不可靠。
|
|
42
41
|
- Core 模式:projectPath = 當前工作目錄的絕對路徑
|
|
43
42
|
- 子專案模式:projectPath = 子專案的絕對路徑(從 .kenaz/project.yaml 讀取)
|
|
@@ -50,7 +49,7 @@ rules:
|
|
|
50
49
|
title: "搜尋工具選擇決策樹"
|
|
51
50
|
description: |
|
|
52
51
|
Agent 遇到搜尋 / 導航需求時,按此決策樹選擇工具。
|
|
53
|
-
原則:文字用 Grep/Glob,符號關係用 LSP
|
|
52
|
+
原則:文字用 Grep/Glob,符號關係用 LSP。
|
|
54
53
|
severity: "should"
|
|
55
54
|
|
|
56
55
|
decision_tree: |
|
|
@@ -68,10 +67,6 @@ rules:
|
|
|
68
67
|
├── 「這個函數/類在哪裡定義?」 → kenaz_lsp_definition(projectPath, file, line | symbol)
|
|
69
68
|
├── 「這個檔案有哪些 symbol?」 → kenaz_lsp_symbols(projectPath, file)
|
|
70
69
|
│
|
|
71
|
-
├── [歷史經驗 — 需要 Synapse 記憶層可用]
|
|
72
|
-
│
|
|
73
|
-
├── 「這個 symbol / 模組有已知風險或決策嗎?」 → synapse_recall
|
|
74
|
-
│
|
|
75
70
|
├── [Bug 調查兩階段]
|
|
76
71
|
│
|
|
77
72
|
├── Step 1: 定位入口(error log 有精確路徑/URL)→ Grep 找到檔案
|
|
@@ -127,27 +122,13 @@ rules:
|
|
|
127
122
|
use_instead: "Grep (count mode)"
|
|
128
123
|
|
|
129
124
|
# =============================================================================
|
|
130
|
-
# SYN-003.5:
|
|
125
|
+
# SYN-003.5: 記憶查詢語言規則(已移除)
|
|
126
|
+
# synapse_recall/inscribe 已於 2026-10-11 移除(TASK_2411),英文限制不再適用。
|
|
131
127
|
# =============================================================================
|
|
132
128
|
- id: "SYN-003.5"
|
|
133
|
-
title: "
|
|
134
|
-
description:
|
|
135
|
-
|
|
136
|
-
非英文查詢(中文、日文等)必須先翻譯成英文再召回。
|
|
137
|
-
severity: "must"
|
|
138
|
-
|
|
139
|
-
rule: |
|
|
140
|
-
召回和寫入都必須使用英文:
|
|
141
|
-
|
|
142
|
-
召回(synapse_recall):
|
|
143
|
-
- 用戶用非英文描述需求時,翻譯成英文再查詢
|
|
144
|
-
- 例:「怎麼處理終端機的大小調整?」→ query="terminal resize fit columns rows"
|
|
145
|
-
|
|
146
|
-
寫入(synapse_inscribe / synapse_forge):
|
|
147
|
-
- Rune content 必須用英文撰寫
|
|
148
|
-
- Sigil name 和 abstract 必須用英文
|
|
149
|
-
- 原因:recall 用英文搜尋,中文 content 永遠搜不到
|
|
150
|
-
- 例:「加入 WAL 修復鎖定問題」→ content="Added WAL + busy_timeout to fix exclusive lock blocking reads"
|
|
129
|
+
title: "記憶查詢語言規則(已移除)"
|
|
130
|
+
description: "Synapse 記憶工具已移除;此條不再適用。"
|
|
131
|
+
severity: "may"
|
|
151
132
|
|
|
152
133
|
# =============================================================================
|
|
153
134
|
# SYN-004: kenaz_lsp_* 參數指南
|
|
@@ -222,24 +203,20 @@ rules:
|
|
|
222
203
|
|
|
223
204
|
refactoring: |
|
|
224
205
|
重構前評估:
|
|
225
|
-
kenaz_lsp_references → kenaz_lsp_callers
|
|
206
|
+
kenaz_lsp_references → kenaz_lsp_callers
|
|
226
207
|
1. kenaz_lsp_references 看改動的 blast radius
|
|
227
208
|
2. kenaz_lsp_callers 看跨模組呼叫者
|
|
228
|
-
3. synapse_recall 查已知風險
|
|
229
209
|
|
|
230
210
|
pre_task: |
|
|
231
211
|
開發任務前的標準動作:
|
|
232
|
-
|
|
233
|
-
1.
|
|
234
|
-
2.
|
|
235
|
-
3. Grep/Glob 找相關實現和型別定義
|
|
236
|
-
4. 修改既有 symbol 前用 kenaz_lsp_references / kenaz_lsp_callers 看影響範圍
|
|
212
|
+
Grep/Glob → kenaz_lsp_*
|
|
213
|
+
1. Grep/Glob 找相關實現和型別定義
|
|
214
|
+
2. 修改既有 symbol 前用 kenaz_lsp_references / kenaz_lsp_callers 看影響範圍
|
|
237
215
|
|
|
238
216
|
pre_code_analysis: |
|
|
239
217
|
寫代碼前的分析(修改既有 symbol 時):
|
|
240
|
-
1.
|
|
241
|
-
2.
|
|
242
|
-
3. kenaz_lsp_callers(symbol, depth=2) → 跨模組呼叫者
|
|
218
|
+
1. kenaz_lsp_references(symbol) → 爆炸半徑
|
|
219
|
+
2. kenaz_lsp_callers(symbol, depth=2) → 跨模組呼叫者
|
|
243
220
|
禁止盲寫 — 修改非 trivial symbol 前不看影響範圍是被禁止的行為(FAIL-009)。
|
|
244
221
|
|
|
245
222
|
red_flags: |
|
|
@@ -261,88 +238,29 @@ rules:
|
|
|
261
238
|
reality: "爆炸半徑由引用關係決定,不由你的直覺決定。一行改動可以跨三個模組邊界。"
|
|
262
239
|
|
|
263
240
|
post_code: |
|
|
264
|
-
|
|
241
|
+
寫代碼後的驗證:
|
|
265
242
|
1. git diff 確認實際改了哪些 symbol
|
|
266
243
|
2. 對每個改動的公開 symbol → kenaz_lsp_references 檢查是否有漏改的呼叫端
|
|
267
|
-
3. 如有 non-obvious 發現 →
|
|
244
|
+
3. 如有 non-obvious 發現 → `kenaz learn add` 或原生記憶檔留給下一個 agent
|
|
268
245
|
|
|
269
|
-
post_task: |
|
|
270
|
-
任務完成後的認知層更新(選擇性):
|
|
271
|
-
synapse_inscribe / synapse_forge
|
|
272
|
-
判斷標準:「這個發現,未來 agent 在同 symbol 附近工作時需要知道嗎?」
|
|
273
|
-
YES → synapse_inscribe(單 symbol 標註)或 synapse_forge(跨 symbol 概念)
|
|
274
|
-
NO → 跳過,不要為了寫而寫
|
|
275
246
|
|
|
276
247
|
tool_summary:
|
|
277
248
|
kenaz_lsp_callers: "誰呼叫這個 symbol(支援 depth 遞迴)"
|
|
278
249
|
kenaz_lsp_references: "所有引用位置 — 修改影響範圍"
|
|
279
250
|
kenaz_lsp_definition: "定義位置"
|
|
280
251
|
kenaz_lsp_symbols: "檔案內 symbol 列表"
|
|
281
|
-
synapse_status: "檢查記憶層狀態"
|
|
282
|
-
synapse_recall: "FTS5 召回 runes + sigils,按 confidence × recency 排序(認知層歷史知識)"
|
|
283
|
-
synapse_inscribe: "對 symbol 寫入 Rune 知識標註(insight/decision/fix/pattern/risk/summary)。supersedes 參數可取代舊 rune"
|
|
284
|
-
synapse_forge: "建立/更新 Sigil 跨 symbol 概念節點(永久,同名 upsert)"
|
|
285
|
-
synapse_sigils: "瀏覽所有 Sigil 概念圖,expand=true 附 symbol 摘要"
|
|
286
252
|
|
|
287
253
|
# =============================================================================
|
|
288
|
-
# SYN-007:
|
|
254
|
+
# SYN-007: 認知層工具(已移除)
|
|
289
255
|
# =============================================================================
|
|
290
256
|
- id: "SYN-007"
|
|
291
|
-
title: "
|
|
257
|
+
title: "認知層工具已移除"
|
|
292
258
|
description: |
|
|
293
|
-
|
|
294
|
-
|
|
259
|
+
synapse_recall / inscribe / forge / sigils 等記憶層 MCP 工具已於 2026-10-11 移除(TASK_2411),
|
|
260
|
+
呼叫會得到 Unknown tool。教訓寫入 `kenaz learn add` 或 Claude 原生記憶檔(含 triggers: frontmatter);
|
|
261
|
+
歷史知識用 Grep / 讀碼 / `kenaz learn list` 查。
|
|
295
262
|
severity: "should"
|
|
296
263
|
|
|
297
|
-
recall_triggers:
|
|
298
|
-
description: "以下情況應呼叫 synapse_recall 查詢歷史知識"
|
|
299
|
-
must_recall:
|
|
300
|
-
- trigger: "任務開始,scope_paths 涉及已有 symbol"
|
|
301
|
-
query_hint: "用 scope_paths 中的關鍵詞搜尋"
|
|
302
|
-
purpose: "確認有無已知 risk、design decision、已修復的 bug pattern"
|
|
303
|
-
- trigger: "遇到陌生或複雜的函數/模組"
|
|
304
|
-
query_hint: "用 symbol 名稱或功能描述搜尋"
|
|
305
|
-
purpose: "Agent 之前可能已留下 insight"
|
|
306
|
-
- trigger: "debug 過程中懷疑有類似歷史問題"
|
|
307
|
-
query_hint: "用錯誤特徵或受影響模組搜尋"
|
|
308
|
-
purpose: "避免重複排查已知問題"
|
|
309
|
-
skip_recall_when:
|
|
310
|
-
- "memory.db 尚無任何資料(全新系統,尚未有 agent inscribe)"
|
|
311
|
-
- "任務是全新功能,與現有 symbol 無交集"
|
|
312
|
-
- "明確知道沒有相關 rune(之前剛查過)"
|
|
313
|
-
|
|
314
|
-
inscribe_triggers:
|
|
315
|
-
description: "任務完成後,判斷是否值得留下 Rune"
|
|
316
|
-
write_rune_when:
|
|
317
|
-
- "發現 non-obvious 的 bug pattern 或 side-effect"
|
|
318
|
-
- "做出影響後續開發的架構決策"
|
|
319
|
-
- "修復了容易再次出現的問題(type=fix)"
|
|
320
|
-
- "發現模組有使用限制或已知風險(type=risk)"
|
|
321
|
-
do_not_write_when:
|
|
322
|
-
- "只是執行了標準流程,沒有新發現"
|
|
323
|
-
- "重複 docstring 或 code 中已說明的事"
|
|
324
|
-
- "confidence < 0.6(系統會拒絕)"
|
|
325
|
-
- "一般任務執行步驟(用 task log 記錄)"
|
|
326
|
-
symbol_id_format: "file_path:name:kind(例:src/synapse/memory.rs:inscribe_rune:function)"
|
|
327
|
-
related_rune_ids: |
|
|
328
|
-
SYN-012(強制):inscribe 時回溯本 session 先前 recall 過的 rune,將相關 rune_id 傳入
|
|
329
|
-
related_rune_ids 參數,閉合 recall → acted_on → confidence_boost 學習迴路。
|
|
330
|
-
|
|
331
|
-
forge_triggers:
|
|
332
|
-
description: "識別出跨 symbol 的語義抽象時呼叫 synapse_forge"
|
|
333
|
-
write_sigil_when:
|
|
334
|
-
- "多個 symbol 共同構成一個有名字的概念(如 payment_flow、auth_pipeline)"
|
|
335
|
-
- "發現一個重要的 anti_pattern 跨越多個模組"
|
|
336
|
-
note: "Sigil 是稀缺的,比 Rune 更需要謹慎。一個 Sigil 代表整個系統的一個認知單元"
|
|
337
|
-
|
|
338
|
-
conflict_resolution:
|
|
339
|
-
description: "當新發現與已有 Rune 衝突時的處理流程"
|
|
340
|
-
supersede_flow:
|
|
341
|
-
- "recall 撈出舊 rune → 發現內容過時或錯誤"
|
|
342
|
-
- "synapse_inscribe({ ..., supersedes: '<舊rune_id>' }) → 舊 rune 被標記 superseded_by,recall 自動排除"
|
|
343
|
-
- "新 rune 取代舊 rune 成為 active 知識"
|
|
344
|
-
rule: "不要留下矛盾的 rune 並存 — 用 supersedes 取代;檢查矛盾用 synapse_rune_conflicts,過時檢查用 synapse_scan_stale_runes"
|
|
345
|
-
|
|
346
264
|
# =============================================================================
|
|
347
265
|
# 快速參考
|
|
348
266
|
# =============================================================================
|
|
@@ -361,10 +279,6 @@ quick_reference:
|
|
|
361
279
|
kenaz_lsp_symbols:
|
|
362
280
|
best_for: "不讀完整檔案就了解其結構"
|
|
363
281
|
|
|
364
|
-
synapse_recall:
|
|
365
|
-
strength: "歷史 rune / sigil 召回,按 confidence × recency 排序"
|
|
366
|
-
best_for: "修改前確認有無已知 risk / decision / fix"
|
|
367
|
-
|
|
368
282
|
grep:
|
|
369
283
|
strength: "精確匹配、正則、速度快、無依賴"
|
|
370
284
|
weakness: "不理解語意、結果無排序"
|
|
@@ -43,8 +43,8 @@ rules:
|
|
|
43
43
|
description: |
|
|
44
44
|
ALL Edit/Read/Write operations MUST use the worktree path as prefix.
|
|
45
45
|
Example: if pwd returns /c/.../KenazAI/.claude/worktrees/agent-abc/,
|
|
46
|
-
then reading
|
|
47
|
-
/c/.../KenazAI/.claude/worktrees/agent-abc/
|
|
46
|
+
then reading packages/kenaz/lib/cli.js uses:
|
|
47
|
+
/c/.../KenazAI/.claude/worktrees/agent-abc/packages/kenaz/lib/cli.js
|
|
48
48
|
severity: "must"
|
|
49
49
|
|
|
50
50
|
- id: "WT-001-C"
|
|
@@ -248,15 +248,12 @@ rules:
|
|
|
248
248
|
|
|
249
249
|
=== Agent 傳遞測試指令 ===
|
|
250
250
|
post-complete.js --task=TASK_XXX \
|
|
251
|
-
--test-cmd "
|
|
252
|
-
--test-cmd "cd dashboard/pty-server && cargo test"
|
|
251
|
+
--test-cmd "node dev/scripts/rust-verify-worktree.js run <branch> <filter>"
|
|
253
252
|
|
|
254
253
|
如果 Agent 未傳 --test-cmd,腳本 fallback 到自動偵測所有可用測試套件。
|
|
255
254
|
|
|
256
255
|
=== Agent 測試判斷指引 ===
|
|
257
|
-
- 修改 dashboard/src/ (
|
|
258
|
-
- 修改 dashboard/src-tauri/ (Rust) → --test-cmd "cd dashboard/src-tauri && cargo test"
|
|
259
|
-
- 修改 dashboard/pty-server/ (Rust) → --test-cmd "cd dashboard/pty-server && cargo test"
|
|
256
|
+
- 修改 dashboard/src-tauri/ (Rust, kenaz-server) → --test-cmd "node dev/scripts/rust-verify-worktree.js run <branch> <filter>"(Dashboard 前端與 pty-server 已於 2026-10-11 移除)
|
|
260
257
|
- 修改 kenaz-cortex/ (Python) → --test-cmd "cd kenaz-cortex && pytest"
|
|
261
258
|
- 只修改 .yaml/.md/設定檔 → --skip-tests(無需測試)
|
|
262
259
|
- 修改多個子系統 → 多個 --test-cmd,分別指定
|
|
@@ -278,12 +275,12 @@ rules:
|
|
|
278
275
|
Agent 忘記傳參時,auto-detect fallback 保底。
|
|
279
276
|
防止 Agent 完成 TASK_B 時意外破壞 TASK_A 的功能。
|
|
280
277
|
examples:
|
|
281
|
-
- scenario: "修改了
|
|
278
|
+
- scenario: "修改了 kenaz-server 的 Rust 與 plugin 的 JS"
|
|
282
279
|
action: |
|
|
283
|
-
Agent 判斷:改了 dashboard/src/ 和
|
|
280
|
+
Agent 判斷:改了 dashboard/src-tauri/ 和 plugins/kenaz/scripts/
|
|
284
281
|
→ post-complete.js --task=TASK_XXX \
|
|
285
|
-
--test-cmd "
|
|
286
|
-
--test-cmd "
|
|
282
|
+
--test-cmd "node dev/scripts/rust-verify-worktree.js run <branch> peer" \
|
|
283
|
+
--test-cmd "node --test plugins/kenaz/scripts/kenaz.test.js"
|
|
287
284
|
→ 腳本依序跑 2 組測試
|
|
288
285
|
→ 全過 → 繼續 PPL-109 commit
|
|
289
286
|
- scenario: "只修改了 Python 後端 API"
|