@lamentis/naome 1.3.0 → 1.3.2

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.
Files changed (149) hide show
  1. package/Cargo.lock +2 -2
  2. package/README.md +11 -2
  3. package/bin/naome.js +62 -24
  4. package/crates/naome-cli/Cargo.toml +1 -1
  5. package/crates/naome-cli/src/context_commands.rs +47 -0
  6. package/crates/naome-cli/src/dispatcher.rs +6 -0
  7. package/crates/naome-cli/src/main.rs +43 -6
  8. package/crates/naome-cli/src/quality_commands.rs +31 -46
  9. package/crates/naome-cli/src/quality_output.rs +34 -0
  10. package/crates/naome-cli/src/quality_reconcile_command.rs +45 -0
  11. package/crates/naome-cli/src/repository_model_commands.rs +84 -0
  12. package/crates/naome-cli/src/task_commands.rs +62 -0
  13. package/crates/naome-cli/src/workflow_commands.rs +100 -3
  14. package/crates/naome-core/Cargo.toml +1 -1
  15. package/crates/naome-core/src/context/helpers.rs +75 -0
  16. package/crates/naome-core/src/context/select.rs +134 -0
  17. package/crates/naome-core/src/context/types.rs +43 -0
  18. package/crates/naome-core/src/context.rs +6 -0
  19. package/crates/naome-core/src/decision/states.rs +1 -1
  20. package/crates/naome-core/src/decision.rs +4 -1
  21. package/crates/naome-core/src/install_plan.rs +18 -0
  22. package/crates/naome-core/src/intent/resolver_catalog/active.rs +38 -0
  23. package/crates/naome-core/src/intent/resolver_catalog/baseline.rs +44 -0
  24. package/crates/naome-core/src/intent/resolver_catalog/completed.rs +56 -0
  25. package/crates/naome-core/src/intent/resolver_catalog/dirty.rs +32 -0
  26. package/crates/naome-core/src/intent/resolver_catalog/ready.rs +32 -0
  27. package/crates/naome-core/src/intent/resolver_catalog/system.rs +20 -0
  28. package/crates/naome-core/src/intent/resolver_catalog.rs +12 -166
  29. package/crates/naome-core/src/journal.rs +2 -7
  30. package/crates/naome-core/src/lib.rs +33 -10
  31. package/crates/naome-core/src/quality/adapter_ios.rs +131 -0
  32. package/crates/naome-core/src/quality/adapter_support.rs +67 -0
  33. package/crates/naome-core/src/quality/adapters.rs +81 -18
  34. package/crates/naome-core/src/quality/cache.rs +7 -9
  35. package/crates/naome-core/src/quality/checks/duplicate_blocks.rs +4 -7
  36. package/crates/naome-core/src/quality/config.rs +21 -3
  37. package/crates/naome-core/src/quality/mod.rs +138 -7
  38. package/crates/naome-core/src/quality/reconcile.rs +138 -0
  39. package/crates/naome-core/src/quality/reconcile_anchors.rs +64 -0
  40. package/crates/naome-core/src/quality/scanner/analysis.rs +20 -5
  41. package/crates/naome-core/src/quality/scanner.rs +62 -17
  42. package/crates/naome-core/src/quality/semantic/checks.rs +17 -0
  43. package/crates/naome-core/src/quality/semantic/route.rs +1 -1
  44. package/crates/naome-core/src/quality/structure/adapter_ios.rs +149 -0
  45. package/crates/naome-core/src/quality/structure/adapters.rs +60 -42
  46. package/crates/naome-core/src/quality/structure/checks/directory.rs +6 -4
  47. package/crates/naome-core/src/quality/structure/classify/roles.rs +51 -5
  48. package/crates/naome-core/src/quality/structure/config.rs +24 -3
  49. package/crates/naome-core/src/quality/structure/mod.rs +3 -0
  50. package/crates/naome-core/src/quality/types.rs +20 -1
  51. package/crates/naome-core/src/repository_model/detect.rs +188 -0
  52. package/crates/naome-core/src/repository_model/explain.rs +121 -0
  53. package/crates/naome-core/src/repository_model/path_scan.rs +67 -0
  54. package/crates/naome-core/src/repository_model/path_support.rs +59 -0
  55. package/crates/naome-core/src/repository_model/types.rs +152 -0
  56. package/crates/naome-core/src/repository_model/world.rs +48 -0
  57. package/crates/naome-core/src/repository_model/world_adapters.rs +145 -0
  58. package/crates/naome-core/src/repository_model/world_path_facts.rs +55 -0
  59. package/crates/naome-core/src/repository_model/world_paths.rs +168 -0
  60. package/crates/naome-core/src/repository_model.rs +164 -0
  61. package/crates/naome-core/src/route/builtin_checks.rs +40 -1
  62. package/crates/naome-core/src/task_ledger/import.rs +142 -0
  63. package/crates/naome-core/src/task_ledger/model.rs +13 -0
  64. package/crates/naome-core/src/task_ledger/proof_record.rs +52 -0
  65. package/crates/naome-core/src/task_ledger/read.rs +118 -0
  66. package/crates/naome-core/src/task_ledger/render.rs +55 -0
  67. package/crates/naome-core/src/task_ledger/write.rs +38 -0
  68. package/crates/naome-core/src/task_ledger.rs +48 -0
  69. package/crates/naome-core/src/task_state/api.rs +4 -2
  70. package/crates/naome-core/src/task_state/completed_refresh.rs +5 -16
  71. package/crates/naome-core/src/task_state/diff.rs +2 -2
  72. package/crates/naome-core/src/task_state/evidence.rs +8 -3
  73. package/crates/naome-core/src/task_state/mod.rs +1 -1
  74. package/crates/naome-core/src/task_state/progress.rs +13 -0
  75. package/crates/naome-core/src/task_state/proof_model.rs +8 -8
  76. package/crates/naome-core/src/task_state/repair.rs +2 -2
  77. package/crates/naome-core/src/task_state/task_diff_api.rs +9 -18
  78. package/crates/naome-core/src/task_state/types.rs +24 -0
  79. package/crates/naome-core/src/verification.rs +29 -18
  80. package/crates/naome-core/src/workflow/agent/capability.rs +194 -0
  81. package/crates/naome-core/src/workflow/agent/context_delta.rs +42 -0
  82. package/crates/naome-core/src/workflow/agent/decision.rs +32 -0
  83. package/crates/naome-core/src/workflow/agent/execution.rs +80 -0
  84. package/crates/naome-core/src/workflow/agent/proof.rs +24 -0
  85. package/crates/naome-core/src/workflow/agent/support.rs +58 -0
  86. package/crates/naome-core/src/workflow/agent/watchdog.rs +47 -0
  87. package/crates/naome-core/src/workflow/agent.rs +34 -0
  88. package/crates/naome-core/src/workflow/agent_types.rs +105 -0
  89. package/crates/naome-core/src/workflow/doctor.rs +39 -0
  90. package/crates/naome-core/src/workflow/mod.rs +11 -0
  91. package/crates/naome-core/src/workflow/output.rs +8 -2
  92. package/crates/naome-core/src/workflow/phase_inference.rs +1 -1
  93. package/crates/naome-core/tests/context.rs +99 -0
  94. package/crates/naome-core/tests/harness_health.rs +33 -40
  95. package/crates/naome-core/tests/install_plan.rs +12 -0
  96. package/crates/naome-core/tests/quality.rs +178 -2
  97. package/crates/naome-core/tests/quality_performance.rs +39 -2
  98. package/crates/naome-core/tests/quality_structure_adapters.rs +39 -0
  99. package/crates/naome-core/tests/repo_support/mod.rs +7 -1
  100. package/crates/naome-core/tests/repo_support/verification_values.rs +148 -1
  101. package/crates/naome-core/tests/repository_model.rs +281 -0
  102. package/crates/naome-core/tests/route_user_diff.rs +49 -1
  103. package/crates/naome-core/tests/semantic_legacy.rs +72 -38
  104. package/crates/naome-core/tests/task_ledger.rs +328 -0
  105. package/crates/naome-core/tests/task_state.rs +34 -14
  106. package/crates/naome-core/tests/task_state_support/mod.rs +2 -1
  107. package/crates/naome-core/tests/task_state_support/states.rs +28 -11
  108. package/crates/naome-core/tests/verification.rs +14 -39
  109. package/crates/naome-core/tests/verification_contract.rs +6 -52
  110. package/crates/naome-core/tests/workflow_agent.rs +233 -0
  111. package/crates/naome-core/tests/workflow_agent_support/mod.rs +159 -0
  112. package/crates/naome-core/tests/workflow_doctor.rs +21 -0
  113. package/crates/naome-core/tests/workflow_integrity.rs +2 -20
  114. package/crates/naome-core/tests/workflow_support/mod.rs +59 -20
  115. package/installer/codex-hooks.js +121 -0
  116. package/installer/context.js +10 -0
  117. package/installer/filesystem.js +4 -0
  118. package/installer/flows.js +8 -4
  119. package/installer/harness-files.js +6 -0
  120. package/installer/install-plan.js +4 -0
  121. package/installer/main.js +1 -1
  122. package/installer/native.js +1 -1
  123. package/native/darwin-arm64/naome +0 -0
  124. package/native/linux-x64/naome +0 -0
  125. package/package.json +1 -1
  126. package/templates/naome-root/.codex/config.toml +2 -0
  127. package/templates/naome-root/.codex/hooks.json +70 -0
  128. package/templates/naome-root/.naome/bin/check-harness-health.js +8 -6
  129. package/templates/naome-root/.naome/bin/check-task-state.js +12 -7
  130. package/templates/naome-root/.naome/bin/codex-hook-io.js +122 -0
  131. package/templates/naome-root/.naome/bin/codex-hook-policy.js +180 -0
  132. package/templates/naome-root/.naome/bin/codex-hook-runtime.js +174 -0
  133. package/templates/naome-root/.naome/bin/codex-hook.js +6 -0
  134. package/templates/naome-root/.naome/bin/naome.js +35 -4
  135. package/templates/naome-root/.naome/manifest.json +12 -6
  136. package/templates/naome-root/.naome/repository-model.json +6 -0
  137. package/templates/naome-root/.naome/repository-quality.json +3 -1
  138. package/templates/naome-root/.naome/verification.json +15 -1
  139. package/templates/naome-root/AGENTS.md +38 -83
  140. package/templates/naome-root/docs/naome/agent-workflow.md +54 -18
  141. package/templates/naome-root/docs/naome/codex-hooks.md +82 -0
  142. package/templates/naome-root/docs/naome/context-economy.md +73 -0
  143. package/templates/naome-root/docs/naome/first-run.md +25 -14
  144. package/templates/naome-root/docs/naome/index.md +18 -10
  145. package/templates/naome-root/docs/naome/repository-model.md +92 -0
  146. package/templates/naome-root/docs/naome/repository-quality.md +47 -7
  147. package/templates/naome-root/docs/naome/repository-structure.md +10 -3
  148. package/templates/naome-root/docs/naome/task-ledger.md +71 -0
  149. package/templates/naome-root/docs/naome/testing.md +16 -3
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+
3
+ const io = require("./codex-hook-io.js");
4
+ const policy = require("./codex-hook-policy.js");
5
+
6
+ function handleCodexHook() {
7
+ const payload = io.readPayload();
8
+ const event = io.eventName(payload);
9
+ try {
10
+ if (event === "UserPromptSubmit") return userPrompt(payload); if (event === "PreToolUse") return preTool(payload);
11
+ if (event === "PermissionRequest") return permission(payload); if (event === "PostToolUse") return postTool(payload);
12
+ if (event === "Stop") return stop(payload);
13
+ } catch {
14
+ return io.write({});
15
+ }
16
+ io.write({});
17
+ }
18
+
19
+ function userPrompt(payload) {
20
+ const prompt = io.promptOf(payload);
21
+ const classification = policy.classifyPrompt(prompt);
22
+ const risky = policy.riskyPromptCodes(prompt);
23
+ const status = io.parseJson(io.runNaome(["status", "--json"]).stdout);
24
+ const codes = [`prompt-${classification}`, ...risky];
25
+ if (status?.state === "dirty_unowned_diff") codes.push("repo-dirty-unowned");
26
+ if (["new_task", "ci_fix"].includes(classification)) codes.push("route-required", "context-selection-required");
27
+ io.decide("warn", "prompt-guidance", [`prompt:${classification}`, status?.state ? `repo:${status.state}` : null, risky.length ? `risk:${risky.join(",")}` : null, ["new_task", "ci_fix"].includes(classification) ? "run route and context select before feature work" : null], { classification, reasonCodes: codes });
28
+ }
29
+
30
+ function preTool(payload) {
31
+ const command = io.commandOf(payload);
32
+ const boundary = policy.forbiddenPath(payload, command);
33
+ if (boundary) return io.decide("block", boundary, [boundary], { reasonCodes: [boundary.split(":")[0]] });
34
+ if (!command) return io.write({});
35
+ const hard = policy.hardBlockedCommand(command);
36
+ if (hard) return io.decide("block", hard, [hard], { reasonCodes: [hard.split(":")[0]] });
37
+ const preflight = commitPushPreflight(command);
38
+ if (preflight) return io.decide("block", preflight, [preflight], { reasonCodes: [preflight.split(":")[0]] });
39
+ const search = validateSearch(command);
40
+ if (search) return io.decide("block", search, [search], { reasonCodes: [search.split(":")[0]] });
41
+ io.write({});
42
+ }
43
+
44
+ function permission(payload) {
45
+ const risks = policy.permissionRiskCodes(`${io.commandOf(payload) || ""} ${io.promptOf(payload)}`);
46
+ if (!risks.length) return io.write({});
47
+ io.decide("warn", "permission-risk-summary", [`permission risks: ${risks.join(",")}; approve only if this matches the current NAOME task.`], { riskCodes: risks, reasonCodes: ["permission-risk-summary"] });
48
+ }
49
+
50
+ function postTool(payload) {
51
+ const command = io.commandOf(payload);
52
+ const changedPaths = changedFiles();
53
+ if (!changedPaths.length) return io.write({});
54
+ if (!policy.looksLikeWriteTool(payload, command)) {
55
+ const cache = io.readCache();
56
+ io.writeCache({ ...cache, postToolUse: { signature: io.diffSignature(), decision: {} } });
57
+ return io.write({});
58
+ }
59
+ const checkedPaths = postToolCheckedPaths(payload, command, changedPaths);
60
+ if (!checkedPaths.length) return io.write({});
61
+ const signature = `${io.diffSignature()}:${checkedPaths.join("\0")}`;
62
+ const cache = io.readCache();
63
+ if (cache.postToolUse?.signature === signature) return io.write({});
64
+ const result = changedState(checkedPaths, { pathScoped: true });
65
+ const decision = result.codes.length ? io.decisionObject("warn", policy.primaryReason(result.codes), result.messages, { reasonCodes: result.codes, changedPaths: checkedPaths, owedProof: result.expensiveOwed, cheapGates: result.gates }) : {};
66
+ io.writeCache({ ...cache, postToolUse: { signature, decision, changedPaths, checkedPaths, cheapGateCommands: result.gateCommands } });
67
+ io.write(decision);
68
+ }
69
+
70
+ function stop(payload) {
71
+ const changedPaths = changedFiles();
72
+ const result = changedState(changedPaths);
73
+ for (const check of [io.taskCheck([]), io.taskCheck(["--progress"])]) {
74
+ const output = `${check.stdout || ""}\n${check.stderr || ""}`;
75
+ if (check.status && /outside allowedPaths|scope drift/i.test(output)) policy.pushUnique(result.codes, "scope-drift", result.messages, "scope drift blocks completion");
76
+ if (check.status && /missing proof|proofResults missing|failed proof/i.test(output)) policy.pushUnique(result.codes, "missing-proof", result.messages, "missing required proof blocks completion");
77
+ }
78
+ const prompt = io.promptOf(payload);
79
+ if (/push/i.test(prompt) && /\[ahead [1-9]/.test(io.runGit(["status", "--short", "--branch"]).stdout || "")) {
80
+ policy.pushUnique(result.codes, "unpushed-branch", result.messages, "branch has unpushed commits");
81
+ }
82
+ if (/resolve|review comment|github comment/i.test(prompt) && /CHANGES_REQUESTED/.test(io.run("gh", ["pr", "view", "--json", "reviewDecision"]).stdout || "")) {
83
+ policy.pushUnique(result.codes, "unresolved-review-comments", result.messages, "GitHub review still appears unresolved");
84
+ }
85
+ if (result.codes.length) return io.decide("block", policy.primaryReason(result.codes), result.messages, { reasonCodes: result.codes, changedPaths, cheapGates: result.gates });
86
+ io.write({});
87
+ }
88
+
89
+ function changedState(changedPaths, options = {}) {
90
+ const codes = [];
91
+ const messages = [];
92
+ const state = io.readJson(".naome/task-state.json");
93
+ const drift = policy.scopeDrift(changedPaths, state?.activeTask?.allowedPaths);
94
+ if (drift.length) policy.pushUnique(codes, "scope-drift", messages, `scope drift: ${drift.join(", ")}`);
95
+ const expensiveOwed = missingExpensiveProof(changedPaths, policy.expensiveProof(policy.owedProof(changedPaths, io.readJson(".naome/verification.json"))), state?.activeTask);
96
+ if (expensiveOwed.length) policy.pushUnique(codes, "owed-proof", messages, `owed proof: ${expensiveOwed.join(", ")}`);
97
+ if (repoStale()) policy.pushUnique(codes, "repository-model-stale", messages, "repository model is stale");
98
+ const gatePaths = options.pathScoped ? changedPaths : [];
99
+ const gates = cheapGates(gatePaths);
100
+ for (const gate of gates) policy.pushUnique(codes, gate.code, messages, gate.message);
101
+ return { codes, messages, expensiveOwed, gates, gateCommands: cheapGateCommands(gatePaths) };
102
+ }
103
+
104
+ function commitPushPreflight(command) {
105
+ if (!/\bgit\s+(commit|push)\b/.test(command.replace(/\s+/g, " "))) return null;
106
+ if (/\bgit\s+commit\b/.test(command)) return "commit-preflight: use `node .naome/bin/naome.js commit -m ...` so NAOME owns staging, proof, and commit gates.";
107
+ for (const gate of cheapGates()) return `push-preflight: ${gate.checkId} failed before git push.`;
108
+ return repoStale() ? "push-preflight: repository-model-stale failed before git push." : null;
109
+ }
110
+
111
+ function cheapGates(paths = []) {
112
+ return cheapGateChecks(paths).flatMap(([checkId, command, fn]) => fn().status ? [{ code: `${checkId}-failed`, checkId, command, message: `cheap gate failed: ${checkId}` }] : []);
113
+ }
114
+ function cheapGateCommands(paths = []) {
115
+ return cheapGateChecks(paths).map(([, command]) => command);
116
+ }
117
+ function cheapGateChecks(paths = []) {
118
+ const pathArgs = paths.flatMap((path) => ["--path", path]);
119
+ const displayPaths = paths.map(shellPath).join(" ");
120
+ const checks = [
121
+ ["diff-check", paths.length ? `git diff --check -- ${displayPaths}` : "git diff --check", () => io.runGit(paths.length ? ["diff", "--check", "--", ...paths] : ["diff", "--check"])],
122
+ ["repository-quality-check", paths.length ? `node .naome/bin/naome.js quality check ${pathArgs.join(" ")}` : "node .naome/bin/naome.js quality check --changed", () => io.runNaome(paths.length ? ["quality", "check", ...pathArgs] : ["quality", "check", "--changed"])],
123
+ ["repository-semantic-check", paths.length ? `node .naome/bin/naome.js semantic check ${pathArgs.join(" ")}` : "node .naome/bin/naome.js semantic check --changed", () => io.runNaome(paths.length ? ["semantic", "check", ...pathArgs] : ["semantic", "check", "--changed"])]
124
+ ];
125
+ if (!paths.length && hasActiveTask()) checks.push(["task-state-progress-check", "node .naome/bin/check-task-state.js --progress", () => io.taskCheck(["--progress"])]);
126
+ return checks;
127
+ }
128
+ function validateSearch(command) {
129
+ for (const segment of policy.searchSegments(command)) {
130
+ const result = io.runNaome(["workflow", "check-search", "--command", segment, "--json"]);
131
+ if (result.status === 0) continue;
132
+ const ids = io.parseJson(result.stdout)?.findings?.map((finding) => finding.id).filter(Boolean);
133
+ return ids?.length ? `${ids.join(",")}: NAOME rejected this broad search command.` : io.compact(`unsafe-search-command: ${result.stdout || result.stderr}`);
134
+ }
135
+ return null;
136
+ }
137
+ function changedFiles() {
138
+ const result = io.runGit(["status", "--porcelain=v1"]);
139
+ return result.status ? [] : result.stdout.split(/\r?\n/).filter(Boolean).map((line) => line.replace(/^..\s+/, "").split(" -> ").pop()).filter((path, index, paths) => path && paths.indexOf(path) === index);
140
+ }
141
+ function postToolCheckedPaths(payload, command, changedPaths) {
142
+ const touched = policy.touchedPaths(payload, command);
143
+ if (!touched.length) return changedPaths;
144
+ return changedPaths.filter((path) => touched.some((touch) => path === touch || path.startsWith(`${touch}/`)));
145
+ }
146
+ function shellPath(path) {
147
+ return /[^A-Za-z0-9_./:-]/.test(path) ? JSON.stringify(path) : path;
148
+ }
149
+ function repoStale() {
150
+ const result = io.runNaome(["repo", "check", "--json"]);
151
+ return result.status !== 0 && /repository model is stale|repository-model-stale/i.test(`${result.stdout}\n${result.stderr}`);
152
+ }
153
+
154
+ function hasActiveTask() {
155
+ const state = io.readJson(".naome/task-state.json"); return Boolean(state?.activeTask && state.status === "implementing");
156
+ }
157
+ function missingExpensiveProof(changedPaths, checkIds, activeTask) {
158
+ const proofPaths = changedPaths.filter((path) => !isControlStatePath(path));
159
+ return proofPaths.length ? checkIds.filter((checkId) => !proofCoversChangedPaths(activeTask, checkId, proofPaths)) : [];
160
+ }
161
+ function proofCoversChangedPaths(activeTask, checkId, changedPaths) {
162
+ const proof = (activeTask?.proofResults || []).find((entry) => entry.checkId === checkId && entry.exitCode === 0);
163
+ const evidence = Array.isArray(proof?.evidence) ? proof.evidence : [];
164
+ return changedPaths.every((changedPath) => evidence.some((path) => evidenceCoversPath(path, changedPath)));
165
+ }
166
+ function evidenceCoversPath(evidencePath, changedPath) {
167
+ const evidence = String(evidencePath);
168
+ return evidence === changedPath || (evidence.endsWith("/") && String(changedPath).startsWith(evidence)) || (evidence.endsWith("/**") && String(changedPath).startsWith(evidence.slice(0, -3)));
169
+ }
170
+ function isControlStatePath(path) {
171
+ return path === ".naome/task-state.json" || path.startsWith(".naome/tasks/") || path.startsWith(".naome/cache/");
172
+ }
173
+
174
+ module.exports = { handleCodexHook };
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ const { handleCodexHook } = require("./codex-hook-runtime.js");
5
+
6
+ handleCodexHook();
@@ -27,7 +27,7 @@ function main(argv) {
27
27
  return;
28
28
  }
29
29
 
30
- if (["status", "next", "intent", "route", "explain", "doctor", "quality", "semantic", "structure", "cleanup", "refresh-integrity", "workflow"].includes(command)) {
30
+ if (["status", "next", "intent", "route", "explain", "context", "doctor", "task", "quality", "semantic", "repo", "structure", "cleanup", "refresh-integrity", "workflow"].includes(command)) {
31
31
  runNativeDecisionCommand(command, args);
32
32
  return;
33
33
  }
@@ -143,6 +143,10 @@ function commit(args) {
143
143
  }
144
144
 
145
145
  const message = parseCommitMessage(args);
146
+ const renderResult = spawnNative(root, ["task", "render-state", "--write", "--json"]);
147
+ if (renderResult.status !== 0) {
148
+ fail(`Cannot render NAOME task-state projection: ${renderResult.stderr.trim() || renderResult.stdout.trim()}`);
149
+ }
146
150
  const taskState = readTaskState(root);
147
151
 
148
152
  if (taskState.status !== "complete") {
@@ -328,14 +332,17 @@ function gitHead(root) {
328
332
  }
329
333
 
330
334
  function findHarnessRoot(startPath) {
331
- return findAncestorWithMarker(startPath, [".naome", "task-state.json"]);
335
+ return findAncestorWithAnyMarker(startPath, [
336
+ [".naome", "task-state.json"],
337
+ [".naome", "tasks", "active.json"]
338
+ ]);
332
339
  }
333
340
 
334
- function findAncestorWithMarker(startPath, markerParts) {
341
+ function findAncestorWithAnyMarker(startPath, markers) {
335
342
  let current = resolve(startPath);
336
343
 
337
344
  while (true) {
338
- if (existsSync(join(current, ...markerParts))) {
345
+ if (markers.some((markerParts) => existsSync(join(current, ...markerParts)))) {
339
346
  return current;
340
347
  }
341
348
 
@@ -358,21 +365,32 @@ function printHelp() {
358
365
  "naome route --prompt <text> [--execute] [--json]",
359
366
  "naome explain --prompt-file <path> [--json]",
360
367
  "naome explain --prompt <text> [--json]",
368
+ "naome context select --changed [--json]",
369
+ "naome context select --prompt-file <path> [--json]",
370
+ "naome context select --prompt <text> [--json]",
361
371
  "naome doctor [--json]",
372
+ "naome task render-state [--write] [--json]",
373
+ "naome task migrate-ledger [--write] [--json]",
362
374
  "naome quality init [--baseline|--deep-baseline] [--json]",
363
375
  "naome quality check --changed [--include-scanned-paths] [--json]",
376
+ "naome quality check --path <path> [--path <path>...] [--include-scanned-paths] [--json]",
364
377
  "naome quality report [--deep] [--include-scanned-paths] [--json]",
365
378
  "naome quality cache status [--json]",
366
379
  "naome quality cache clear",
367
380
  "naome semantic report [--deep] [--json]",
368
381
  "naome semantic check --changed [--json]",
382
+ "naome semantic check --path <path> [--path <path>...] [--json]",
369
383
  "naome semantic route --finding <id> [--json]",
370
384
  "naome semantic loop [--json]",
385
+ "naome repo model [--write] [--json]",
386
+ "naome repo check [--json]",
387
+ "naome repo explain --path <path> [--json]",
371
388
  "naome structure report [--json]",
372
389
  "naome structure explain --path <path> [--json]",
373
390
  "naome cleanup plan [--json]",
374
391
  "naome cleanup route --path <path> [--json]",
375
392
  "naome refresh-integrity [--json]",
393
+ "naome workflow agent-plan|context-delta|proof-plan|capabilities|edit-watchdog|decision-gate|digest [--json]",
376
394
  "naome workflow search-profile|check-search|phases|processes|mutations [--json]",
377
395
  "naome install",
378
396
  "naome sync",
@@ -399,6 +417,19 @@ function installOrSync(command, args) {
399
417
  join(packageRoot, "bin", "naome-node.js"),
400
418
  ...args
401
419
  ], { stdio: "inherit" });
420
+ if (result.status === 0) {
421
+ const migration = spawnNative(root, ["task", "migrate-ledger", "--write", "--json"]);
422
+ if (migration.status !== 0) {
423
+ fail("task ledger migration failed after sync.");
424
+ }
425
+ const output = (migration.stdout || "").trim();
426
+ if (output) {
427
+ const parsed = JSON.parse(output);
428
+ if (parsed.updated && parsed.migration && parsed.migration.source === "task-state") {
429
+ console.log("task ledger migrated from task-state");
430
+ }
431
+ }
432
+ }
402
433
  process.exit(result.status === null ? 1 : result.status);
403
434
  }
404
435
 
@@ -3,15 +3,17 @@
3
3
  "installedAt": null,
4
4
  "integrity": {
5
5
  ".naome/bin/check-harness-health.js": "sha256:dc4de52b79c69600b9ba47b924e2c2b8de61a2cbfab6d1ccc0f1924d963db657",
6
- ".naome/bin/check-task-state.js": "sha256:43c02868072d0d13499aefba2e9a5ec9517d59539fd19ff0f11e3e4623a51b44",
7
- ".naome/bin/naome.js": "sha256:3d2edd9cf7b04ffb8845db2c55ce1b9c243bd3aba112f53af4af3c11fae5b8e1",
6
+ ".naome/bin/check-task-state.js": "sha256:df54489a22b426180266e5e0fb5f9ec381477419f688435248afbf2b9b38ea81",
7
+ ".naome/bin/naome.js": "sha256:d343f367da21bf45272331eec2ea34862a0bf056978780c62d6cae02e0f7993a",
8
8
  ".naome/package.json": "sha256:8005a3491db7d92f36ac66369861589f9c47123d3a7c71e643fc2c06168cd45a",
9
9
  ".naome/task-contract.schema.json": "sha256:1b3b62350328d0d6d660e36d1d1baaa2b88718530db774f9ab2a9e2fcba369c8",
10
- "AGENTS.md": "sha256:9192ea81f90bb19f8043513c49b5da9e9598ee694da8356f345e7ccbca0e28df",
11
- "docs/naome/agent-workflow.md": "sha256:97788255e26282ca1b7fcaaf86c9408c9040246727e3de96b4126fcb68c10b38",
10
+ "AGENTS.md": "sha256:e8b2fc786c1c72b69ba8f2b2ffce4f459e799c7453ce9ff4a9f6448a8f9e6b4f",
11
+ "docs/naome/agent-workflow.md": "sha256:78faeb4eed157b60f0b60bc43da36c713fc4a3436b93bd963ce5f3c12dc91f22",
12
+ "docs/naome/context-economy.md": "sha256:3ed5075815ecf4ada46a5e65438769310307c35759fcd46b13dc0b96e02bebd9",
12
13
  "docs/naome/execution.md": "sha256:bfc5d55838942ec8e3d790b59e3c634ff5bf6a2298265cef3dca9788a097eafb",
13
- "docs/naome/first-run.md": "sha256:a1dd0bd17ec9d71955a473cd2c4a615538e89a7d81e8f4e1015a50ab9efe3558",
14
- "docs/naome/index.md": "sha256:a674102cc801702dc77102afb59be0f5ab189dc638caf0bef358b9d6087d0742",
14
+ "docs/naome/first-run.md": "sha256:f1a2412f1b542e61c79b5ba65a3fdaa810b0f95cf79d9f734256418cdcfb19aa",
15
+ "docs/naome/index.md": "sha256:07ef776f49130319a5280bdb3ae38af22141708253f38eb983a4336fbae1b25a",
16
+ "docs/naome/task-ledger.md": "sha256:1e524085a2f88811941fd9f2f48ca826bc3e0e4816039d07e795637847714cbd",
15
17
  "docs/naome/upgrade.md": "sha256:2c60f0441bbd98bd528d109b30a7ded4b0ad55d61ffb9f52edac9e93b7999cb1"
16
18
  },
17
19
  "machineOwned": [
@@ -24,7 +26,9 @@
24
26
  "docs/naome/index.md",
25
27
  "docs/naome/first-run.md",
26
28
  "docs/naome/agent-workflow.md",
29
+ "docs/naome/context-economy.md",
27
30
  "docs/naome/execution.md",
31
+ "docs/naome/task-ledger.md",
28
32
  "docs/naome/upgrade.md"
29
33
  ],
30
34
  "name": "naome",
@@ -36,12 +40,14 @@
36
40
  ".naome/task-state.json",
37
41
  ".naome/upgrade-state.json",
38
42
  ".naome/verification.json",
43
+ ".naome/repository-model.json",
39
44
  ".naome/repository-quality.json",
40
45
  ".naome/repository-structure.json",
41
46
  ".naome/repository-quality-baseline.json",
42
47
  "docs/naome/architecture.md",
43
48
  "docs/naome/decisions.md",
44
49
  "docs/naome/repo-profile.md",
50
+ "docs/naome/repository-model.md",
45
51
  "docs/naome/repository-quality.md",
46
52
  "docs/naome/repository-structure.md",
47
53
  "docs/naome/security.md",
@@ -0,0 +1,6 @@
1
+ {
2
+ "schema": "naome.repository-model.v2",
3
+ "version": 2,
4
+ "status": "ready",
5
+ "facts": []
6
+ }
@@ -13,7 +13,9 @@
13
13
  },
14
14
  "enabledAdapters": [],
15
15
  "disabledChecks": [],
16
- "ignoredPaths": [],
16
+ "ignoredPaths": [
17
+ ".naome/tasks/**"
18
+ ],
17
19
  "generatedPaths": [
18
20
  "**/*.min.js",
19
21
  "**/*.map",
@@ -52,6 +52,19 @@
52
52
  ".naome/repository-quality-baseline.json"
53
53
  ],
54
54
  "lastVerified": null
55
+ },
56
+ {
57
+ "id": "repository-semantic-check",
58
+ "command": "node .naome/bin/naome.js semantic check --changed",
59
+ "cwd": ".",
60
+ "purpose": "Validate changed files against deterministic NAOME semantic cleanup rules.",
61
+ "cost": "fast",
62
+ "source": "NAOME built-in",
63
+ "evidence": [
64
+ ".naome/repository-quality.json",
65
+ ".naome/repository-quality-baseline.json"
66
+ ],
67
+ "lastVerified": null
55
68
  }
56
69
  ],
57
70
  "phases": [
@@ -67,7 +80,8 @@
67
80
  "id": "quality",
68
81
  "order": 20,
69
82
  "checkIds": [
70
- "repository-quality-check"
83
+ "repository-quality-check",
84
+ "repository-semantic-check"
71
85
  ]
72
86
  },
73
87
  {
@@ -4,101 +4,56 @@ This repository uses NAOME as its coding-agent harness.
4
4
 
5
5
  ## Start Here
6
6
 
7
- 1. Read `.naomeignore`.
8
- 2. Do not read any file or directory matched by `.naomeignore`.
9
- 3. If `docs/naome/index.md` or `.naome/bin/check-harness-health.js` is missing,
10
- do not begin feature work. Install the NAOME CLI with
11
- `npm install -g @lamentis/naome`, then run `naome sync --check-update`
12
- from the repository root. Then restart this list.
13
- 4. Read `docs/naome/index.md`.
14
- 5. Read `.naome/init-state.json`.
15
- 6. Read `.naome/task-state.json`.
16
- 7. Read `.naome/upgrade-state.json`.
17
- 8. Run `node .naome/bin/check-harness-health.js`.
18
- 9. If harness health fails, do not begin feature work. Repair the machine-owned
19
- harness files with `naome update` followed by `naome sync`, or ask the user
20
- for one of the listed repair decisions.
21
- 10. If upgrade status is `needs_agent_upgrade`, do not begin feature work. Run
22
- or continue `docs/naome/upgrade.md`.
23
- 11. If `initialized` is `false`, do not begin feature work. Run or continue the
24
- NAOME first-run protocol in `docs/naome/first-run.md`.
25
- 12. Before accepting feature work, run
26
- `node .naome/bin/check-task-state.js --admission`.
27
- 13. If task admission fails, follow `docs/naome/execution.md`.
28
- 14. If `initialized` is `true`, follow `docs/naome/agent-workflow.md`.
7
+ 1. Read `.naomeignore`; it is a hard read boundary.
8
+ 2. Do not read paths matched by `.naomeignore`.
9
+ 3. If `.naome/bin/check-harness-health.js` is missing, run
10
+ `naome sync --check-update` from the repository root, then restart.
11
+ 4. Read `.naome/task-state.json`.
12
+ 5. Run `node .naome/bin/check-harness-health.js`.
13
+ 6. If harness health fails, stop normal feature work and repair with
14
+ `naome update` followed by `naome sync`, or ask for the listed decision.
15
+ 7. Run `node .naome/bin/check-task-state.js --admission` before accepting new
16
+ feature work.
17
+ 8. For natural-language work, write the request to a prompt file and run
18
+ `node .naome/bin/naome.js route --prompt-file <path> --execute --json`.
19
+ 9. Run `node .naome/bin/naome.js context select --prompt-file <path> --json`
20
+ after route, or `node .naome/bin/naome.js context select --changed --json`
21
+ when continuing an existing diff.
22
+ 10. Read only `requiredContext` from context selection. Read `optionalContext`
23
+ only when blocked.
24
+ 11. If first-run or upgrade state blocks work, read only the document named by
25
+ the blocker, such as `docs/naome/first-run.md` or `docs/naome/upgrade.md`.
29
26
 
30
27
  ## Core Rules
31
28
 
32
- - Prefer discovered repository facts over assumptions.
33
- - Do not look for generic root steering files such as `ARCHITECTURE.md` or
34
- `docs/index.md` unless this repository's NAOME docs explicitly name them.
35
- NAOME's default architecture and index files are
36
- `docs/naome/architecture.md` and `docs/naome/index.md`.
37
- - Record only facts from this target repository or from the user. Do not import
38
- parent-workspace, outer-agent, chat, or unrelated repository instructions into
39
- this repository's NAOME docs.
29
+ - Prefer deterministic NAOME JSON commands over broad Markdown reading.
40
30
  - Keep changes small and task-focused.
41
- - Read only the NAOME docs relevant to the current task.
42
- - Run Harness Health before Task Admission.
43
- - For natural-language work requests, prefer
44
- `naome route --prompt-file <path> --execute --json` and follow its
45
- `userMessage`, `humanOptions`, `requiredContext`, `taskRoot`, `worktree`, and
46
- `canCreateTask` fields. If `taskRoot` differs from the current directory,
47
- continue the task in `taskRoot`; the original worktree contains unrelated user
48
- edits that must remain untouched. Pure deterministic harness refresh diffs
49
- are baselined in the current worktree before task creation; they must not
50
- create repair-loop task worktrees. Use `naome explain --prompt-file <path>
51
- --json` only for debugging policy.
52
- - If route blocks or performs no mutation, do not fall back to raw `git commit`,
53
- IDE commit, `git add`, or hook bypass commands. Only execute a commit when
54
- NAOME route/commit performs it successfully or the user takes manual Git
55
- ownership outside the agent task.
56
- - If the user explicitly asks to commit their own unowned changes, use NAOME
57
- route so the configured quality gate runs first. NAOME commits only the exact
58
- paths it evaluated, requires committed verification coverage for every path,
59
- and rechecks the final stabilized diff before creating the commit.
60
- - Repair requests may baseline deterministic harness refresh files, but they
61
- must leave unrelated user edits untouched unless the user explicitly takes
62
- manual Git ownership.
63
- - Machine-owned NAOME command shims, schemas, workflow docs, archives, and
64
- native binaries may be local-only ignored files. Missing local-only files are
65
- repaired with `naome update` followed by `naome sync`; they are not project
66
- context.
67
- - Enforce Task Admission before accepting new feature work.
68
31
  - Do not start feature work while the git diff contains setup, upgrade,
69
32
  previous-task, or other unowned changes.
70
- - Treat `.naomeignore` as a hard read boundary. Do not inspect ignored paths
71
- unless the user first removes the path from `.naomeignore`.
72
- - Use `naome workflow search-profile` or equivalent excludes for broad searches;
73
- hidden searches must exclude `.git`, `.naome/archive`, dependencies, build
33
+ - If route blocks or performs no mutation, do not fall back to raw `git commit`,
34
+ IDE commit, `git add`, or hook bypass commands.
35
+ - Use `node .naome/bin/naome.js repo explain --path <path> --json`,
36
+ `structure explain --path <path> --json`, and
37
+ `quality check --path <path>` for path-specific facts and early feedback.
38
+ - For broad searches, use `node .naome/bin/naome.js workflow search-profile`
39
+ or equivalent excludes for `.git`, `.naome/archive`, dependencies, build
74
40
  outputs, caches, and `.naomeignore` paths.
75
- - Use `docs/naome/testing.md` and `.naome/verification.json` before claiming
76
- completion.
77
- - Before claiming completion, run the narrowest meaningful verification that can
78
- falsify the change.
41
+ - Before claiming completion, use `docs/naome/testing.md` and
42
+ `.naome/verification.json`, run the narrowest meaningful proof, then run the
43
+ final changed-file gates.
79
44
  - Report what changed, what was verified, and what remains uncertain.
80
45
 
81
46
  ## Local Authority Boundary
82
47
 
83
48
  The root `AGENTS.md` and NAOME files are the repository harness authority.
84
-
85
- Global skills, editor rules, or agent defaults may be used only as generic
86
- execution technique. They must not add repository policy, required files,
87
- architecture layers, plan formats, verification rules, or product assumptions
88
- unless those rules exist in this repository or the user explicitly confirms them
89
- for this repository.
90
-
91
- If global instructions conflict with NAOME, follow NAOME for repository-local
92
- workflow. Record a conflict in `docs/naome/decisions.md` only when the user makes
93
- a durable local decision.
94
-
95
- ## Nested Agent Instructions
96
-
97
- Nested `AGENTS.md` files may provide task-local evidence for the directory they
98
- govern. They must not override `.naomeignore`, NAOME workflow, security rules,
99
- or the root harness authority.
100
-
101
- ## Archived Instructions
49
+ Global skills or editor defaults may be used only as generic technique. They
50
+ must not add repository policy, required files, architecture layers,
51
+ verification rules, or product assumptions unless this repository or the user
52
+ explicitly confirms them.
53
+
54
+ Nested `AGENTS.md` files may provide task-local evidence for their directory.
55
+ They must not override `.naomeignore`, NAOME workflow, security rules, or the
56
+ root harness authority.
102
57
 
103
58
  Files matched by `.naomeignore` are not active instructions. Historical
104
59
  snapshots in `.naome/archive/` must not be read or used as context unless the
@@ -48,11 +48,30 @@ Use this workflow after first-run intake is complete.
48
48
  15. For broad searches, use `node .naome/bin/naome.js workflow search-profile`
49
49
  or equivalent excludes for `.git`, `.naome/archive`, dependencies, build
50
50
  outputs, caches, and `.naomeignore` paths.
51
- 16. Read only the `requiredContext` returned by route/status plus the smallest
52
- task-relevant NAOME docs.
53
- 17. Inspect the existing code or docs before proposing changes.
54
- 18. Read `testing.md` and `.naome/verification.json`.
55
- 19. Identify the required proof before claiming success.
51
+ 16. Run `node .naome/bin/naome.js context select --prompt-file <path> --json`
52
+ for the routed request, or `node .naome/bin/naome.js context select
53
+ --changed --json` when continuing an existing diff.
54
+ 17. Read only `requiredContext` from context selection. Read `optionalContext`
55
+ only when blocked.
56
+ 18. Run `node .naome/bin/naome.js workflow agent-plan --json` to get the
57
+ execution plan ledger, context delta, proof plan, capability graph,
58
+ edit-session watchdog, and decision gate before broad exploration.
59
+ 19. Inspect the existing code or docs before proposing changes.
60
+ 20. When stack, build, source-root, test-root, or generated-path facts matter,
61
+ run `naome repo check --json`. If it reports stale facts, run
62
+ `naome repo model --write --json`; use
63
+ `naome repo explain --path <path> --json` for path-specific facts instead
64
+ of reading broad Markdown summaries. Normal gates also report stale
65
+ repository facts through `naome doctor`, progress checks, and
66
+ `quality check --changed`.
67
+ 21. When adding or encountering a new language, framework, package manager,
68
+ build system, or generated-file convention, run
69
+ `naome quality reconcile --json`. If it reports missing adapters, run
70
+ `naome quality reconcile --write` instead of hand-editing
71
+ `enabledAdapters`. Quality gates also report `adapter-policy-stale` when
72
+ repository signals and committed policy drift.
73
+ 22. Read `testing.md` and `.naome/verification.json`.
74
+ 23. Identify the required proof before claiming success.
56
75
 
57
76
  ## Instruction Boundaries
58
77
 
@@ -74,6 +93,14 @@ Use this workflow after first-run intake is complete.
74
93
  - Do not read or use files matched by `.naomeignore`.
75
94
  - Do not overwrite user work or existing project policy.
76
95
  - Update NAOME docs only when the change reveals durable project knowledge.
96
+ - Prefer deterministic NAOME JSON commands for repository facts; Markdown should
97
+ explain workflow or contain human-readable views, not become hidden policy.
98
+ - After writing or heavily editing a file, run
99
+ `node .naome/bin/naome.js quality check --path <path>` for early feedback.
100
+ - For a small touched set, run
101
+ `node .naome/bin/naome.js workflow edit-watchdog --path <path> --json` to
102
+ get path-scoped quality commands and scope-drift findings before the final
103
+ changed gate.
77
104
  - Use `node .naome/bin/check-task-state.js --progress` for in-flight task
78
105
  validation. Use the normal task-state check only after setting `complete`.
79
106
  Scope changes outside `allowedPaths` require human review before continuing.
@@ -83,24 +110,33 @@ Use this workflow after first-run intake is complete.
83
110
  1. Identify changed files.
84
111
  2. Match them against `.naome/verification.json`.
85
112
  3. Run the required checks when available.
86
- 4. Record proof in `.naome/task-state.json`, using compact `proofPathSets` and
87
- `proofBatches` when several checks share the same evidence or timestamp.
88
- Include every changed in-scope path reported by git in expanded proof
89
- evidence.
90
- 5. Do not list `.naome/task-state.json` as task scope or proof evidence.
91
- 6. Stop tracked long-running processes or mark them explicitly allowed in
113
+ 4. Prefer ledger-backed task updates. `naome sync` migrates active legacy
114
+ task-state automatically; if a legacy-only active task is still present, run
115
+ `node .naome/bin/naome.js task migrate-ledger --write --json` before adding
116
+ completion proof.
117
+ 5. Record proof in `.naome/tasks/<task-id>/proofs/`. If legacy compatibility
118
+ work is unavoidable, use compact `proofPathSets` and `proofBatches` in
119
+ `.naome/task-state.json` and include every changed in-scope path reported by
120
+ git in expanded proof evidence.
121
+ 6. Run `node .naome/bin/naome.js task render-state --write --json` before
122
+ external compatibility checks. Do not hand-edit the rendered projection when
123
+ `.naome/tasks/active.json` exists.
124
+ 7. Do not list `.naome/task-state.json` or `.naome/tasks/` as task scope or
125
+ proof evidence.
126
+ 8. Stop tracked long-running processes or mark them explicitly allowed in
92
127
  `.naome/processes.json`.
93
- 7. Set task state to `complete`.
94
- 8. Run `node .naome/bin/check-task-state.js`.
95
- 9. If the task-state check prints a next-task admission notice, do not repeat
128
+ 9. Set task status to `complete` in the ledger event stream or legacy task
129
+ state, then render the projection.
130
+ 10. Run `node .naome/bin/check-task-state.js`.
131
+ 11. If the task-state check prints a next-task admission notice, do not repeat
96
132
  internal baseline options in the final response. Use the machine-generated
97
133
  `userMessage` from route/status and mention `humanOptions` only when that
98
134
  array is non-empty.
99
- 10. If no rule matches or the task check fails, report the gap and ask for human
135
+ 12. If no rule matches or the task check fails, report the gap and ask for human
100
136
  review before claiming completion.
101
- 11. Report changed files, exact commands, results, and remaining risk.
102
- 12. Only ask the user for options when intent blocks, the user explicitly asks
103
- to review/revise/cancel, or automatic baselining fails.
137
+ 13. Report changed files, exact commands, results, and remaining risk.
138
+ 14. Only ask the user for options when intent blocks, the user explicitly asks
139
+ to review/revise/cancel, or automatic baselining fails.
104
140
 
105
141
  ## Commit And Push
106
142