@nimiplatform/nimi-coding 0.2.7 → 0.3.0

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 (207) hide show
  1. package/CHANGELOG.md +8 -80
  2. package/CONTRIBUTING.md +5 -34
  3. package/README.md +47 -350
  4. package/README.zh-CN.md +33 -287
  5. package/cli/commands/start.mjs +48 -688
  6. package/cli/commands/validate-spec-audit.mjs +1 -5
  7. package/cli/constants.mjs +9 -417
  8. package/cli/dev/run-cli-smoke.mjs +24 -0
  9. package/cli/dev/run-suite.mjs +17 -0
  10. package/cli/help.mjs +28 -145
  11. package/cli/index.mjs +5 -33
  12. package/cli/lib/blueprint-audit.mjs +5 -12
  13. package/cli/lib/bootstrap.mjs +0 -9
  14. package/cli/lib/contracts.mjs +0 -163
  15. package/cli/lib/doctor.mjs +155 -10
  16. package/cli/lib/entrypoints.mjs +63 -167
  17. package/cli/lib/internal/contracts-loaders.mjs +0 -85
  18. package/cli/lib/internal/contracts-parse.mjs +84 -520
  19. package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +13 -8
  20. package/cli/lib/internal/surface-taxonomy-validators.mjs +316 -66
  21. package/cli/lib/internal/validators-shared.mjs +0 -16
  22. package/cli/lib/internal/validators-spec-helpers.mjs +7 -140
  23. package/cli/lib/internal/validators-spec.mjs +103 -342
  24. package/cli/lib/shared.mjs +1 -42
  25. package/cli/lib/validators.mjs +0 -48
  26. package/cli/seeds/seed-policy.yaml +0 -3
  27. package/config/bootstrap.yaml +4 -4
  28. package/config/spec-generation-inputs.yaml +6 -12
  29. package/contracts/domain-admission.schema.yaml +3 -3
  30. package/contracts/migration-inventory.schema.yaml +12 -75
  31. package/contracts/negative-fixtures.yaml +19 -99
  32. package/contracts/placement-contract.schema.yaml +49 -78
  33. package/contracts/projection-edge.schema.yaml +37 -121
  34. package/contracts/shared-enums.yaml +4 -8
  35. package/contracts/spec-generation-inputs.schema.yaml +15 -112
  36. package/contracts/spec-layout.schema.yaml +32 -0
  37. package/contracts/surface-taxonomy.schema.yaml +43 -94
  38. package/contracts/table-family.schema.yaml +1 -1
  39. package/contracts/tracked-output-admission.schema.yaml +13 -66
  40. package/methodology/core.yaml +33 -25
  41. package/methodology/four-closure-policy.yaml +18 -26
  42. package/methodology/role-separation-policy.yaml +21 -27
  43. package/methodology/spec-reconstruction.yaml +17 -34
  44. package/package.json +4 -6
  45. package/spec/_meta/spec-tree-model.yaml +5 -101
  46. package/spec/product-scope.yaml +25 -57
  47. package/adapters/README.md +0 -25
  48. package/adapters/claude/README.md +0 -89
  49. package/adapters/claude/profile.yaml +0 -70
  50. package/adapters/codex/README.md +0 -53
  51. package/adapters/codex/profile.yaml +0 -78
  52. package/adapters/oh-my-codex/README.md +0 -184
  53. package/adapters/oh-my-codex/profile.yaml +0 -46
  54. package/cli/commands/admit-high-risk-decision.mjs +0 -108
  55. package/cli/commands/audit-sweep.mjs +0 -364
  56. package/cli/commands/closeout.mjs +0 -186
  57. package/cli/commands/decide-high-risk-execution.mjs +0 -124
  58. package/cli/commands/handoff.mjs +0 -123
  59. package/cli/commands/ingest-high-risk-execution.mjs +0 -95
  60. package/cli/commands/review-high-risk-execution.mjs +0 -95
  61. package/cli/commands/sweep-design.mjs +0 -295
  62. package/cli/commands/sweep.mjs +0 -22
  63. package/cli/commands/topic-formatters.mjs +0 -382
  64. package/cli/commands/topic-goal.mjs +0 -33
  65. package/cli/commands/topic-options-shared.mjs +0 -27
  66. package/cli/commands/topic-options-workflow.mjs +0 -767
  67. package/cli/commands/topic-options.mjs +0 -626
  68. package/cli/commands/topic-runner.mjs +0 -169
  69. package/cli/commands/topic.mjs +0 -795
  70. package/cli/commands/validate-acceptance.mjs +0 -5
  71. package/cli/commands/validate-execution-packet.mjs +0 -5
  72. package/cli/commands/validate-orchestration-state.mjs +0 -5
  73. package/cli/commands/validate-prompt.mjs +0 -5
  74. package/cli/commands/validate-worker-output.mjs +0 -5
  75. package/cli/lib/adapter-profiles.mjs +0 -403
  76. package/cli/lib/audit-execution.mjs +0 -52
  77. package/cli/lib/audit-sweep-runtime/admissions.mjs +0 -508
  78. package/cli/lib/audit-sweep-runtime/audit-validity.mjs +0 -356
  79. package/cli/lib/audit-sweep-runtime/chunks.mjs +0 -697
  80. package/cli/lib/audit-sweep-runtime/claude-auditor.mjs +0 -647
  81. package/cli/lib/audit-sweep-runtime/closeout.mjs +0 -144
  82. package/cli/lib/audit-sweep-runtime/codex-auditor-evidence.mjs +0 -654
  83. package/cli/lib/audit-sweep-runtime/codex-auditor.mjs +0 -516
  84. package/cli/lib/audit-sweep-runtime/common.mjs +0 -341
  85. package/cli/lib/audit-sweep-runtime/coverage-quality.mjs +0 -172
  86. package/cli/lib/audit-sweep-runtime/evidence-assignment.mjs +0 -155
  87. package/cli/lib/audit-sweep-runtime/format.mjs +0 -57
  88. package/cli/lib/audit-sweep-runtime/ingest.mjs +0 -486
  89. package/cli/lib/audit-sweep-runtime/inventory-spec-chunks.mjs +0 -425
  90. package/cli/lib/audit-sweep-runtime/inventory.mjs +0 -798
  91. package/cli/lib/audit-sweep-runtime/ledger.mjs +0 -315
  92. package/cli/lib/audit-sweep-runtime/p0p1-profile.mjs +0 -101
  93. package/cli/lib/audit-sweep-runtime/remediation.mjs +0 -349
  94. package/cli/lib/audit-sweep-runtime/rerun.mjs +0 -129
  95. package/cli/lib/audit-sweep-runtime/risk-budget.mjs +0 -300
  96. package/cli/lib/audit-sweep-runtime/status.mjs +0 -62
  97. package/cli/lib/audit-sweep-runtime/validators-ledger.mjs +0 -215
  98. package/cli/lib/audit-sweep-runtime/validators.mjs +0 -797
  99. package/cli/lib/audit-sweep.mjs +0 -19
  100. package/cli/lib/authority-convergence.mjs +0 -704
  101. package/cli/lib/closeout.mjs +0 -732
  102. package/cli/lib/codex-sdk-runner.mjs +0 -76
  103. package/cli/lib/external-execution.mjs +0 -101
  104. package/cli/lib/handoff.mjs +0 -812
  105. package/cli/lib/high-risk-admission.mjs +0 -512
  106. package/cli/lib/high-risk-decision.mjs +0 -353
  107. package/cli/lib/high-risk-ingest.mjs +0 -321
  108. package/cli/lib/high-risk-review.mjs +0 -267
  109. package/cli/lib/internal/contracts-parse-high-risk.mjs +0 -131
  110. package/cli/lib/internal/contracts-validators.mjs +0 -399
  111. package/cli/lib/internal/doctor-bootstrap-surface.mjs +0 -406
  112. package/cli/lib/internal/doctor-delegated-surface.mjs +0 -256
  113. package/cli/lib/internal/doctor-finalize.mjs +0 -383
  114. package/cli/lib/internal/doctor-format.mjs +0 -286
  115. package/cli/lib/internal/doctor-inspectors.mjs +0 -327
  116. package/cli/lib/internal/doctor-state.mjs +0 -205
  117. package/cli/lib/internal/validators-artifacts.mjs +0 -515
  118. package/cli/lib/sweep-design-runtime/common.mjs +0 -246
  119. package/cli/lib/sweep-design-runtime/engine.mjs +0 -733
  120. package/cli/lib/sweep-design-runtime/fix-topic.mjs +0 -414
  121. package/cli/lib/sweep-design-runtime/lifecycle.mjs +0 -54
  122. package/cli/lib/sweep-design-runtime/results.mjs +0 -324
  123. package/cli/lib/sweep-design.mjs +0 -8
  124. package/cli/lib/topic-artifacts.mjs +0 -186
  125. package/cli/lib/topic-authority-coverage.mjs +0 -73
  126. package/cli/lib/topic-closeout.mjs +0 -560
  127. package/cli/lib/topic-common.mjs +0 -404
  128. package/cli/lib/topic-decisions.mjs +0 -332
  129. package/cli/lib/topic-draft-packets.mjs +0 -167
  130. package/cli/lib/topic-execution.mjs +0 -515
  131. package/cli/lib/topic-goal.mjs +0 -440
  132. package/cli/lib/topic-ledger.mjs +0 -281
  133. package/cli/lib/topic-lifecycle-artifacts.mjs +0 -173
  134. package/cli/lib/topic-root-validation.mjs +0 -288
  135. package/cli/lib/topic-runner-commands.mjs +0 -174
  136. package/cli/lib/topic-runner-deferral.mjs +0 -532
  137. package/cli/lib/topic-runner-stale-gates.mjs +0 -114
  138. package/cli/lib/topic-runner-validation.mjs +0 -138
  139. package/cli/lib/topic-runner.mjs +0 -727
  140. package/cli/lib/topic-scaffold.mjs +0 -252
  141. package/cli/lib/topic-waves.mjs +0 -403
  142. package/cli/lib/topic.mjs +0 -81
  143. package/config/audit-execution-artifacts.yaml +0 -20
  144. package/config/external-execution-artifacts.yaml +0 -16
  145. package/config/host-adapter.yaml +0 -30
  146. package/config/host-profile.yaml +0 -29
  147. package/config/installer-evidence.yaml +0 -31
  148. package/config/skill-installer.yaml +0 -23
  149. package/config/skill-manifest.yaml +0 -48
  150. package/config/skills.yaml +0 -30
  151. package/contracts/acceptance.schema.yaml +0 -16
  152. package/contracts/admission-checklist.schema.yaml +0 -15
  153. package/contracts/audit-chunk.schema.yaml +0 -123
  154. package/contracts/audit-closeout.schema.yaml +0 -51
  155. package/contracts/audit-finding.schema.yaml +0 -61
  156. package/contracts/audit-ledger.schema.yaml +0 -138
  157. package/contracts/audit-plan.schema.yaml +0 -138
  158. package/contracts/audit-remediation-map.schema.yaml +0 -52
  159. package/contracts/audit-rerun.schema.yaml +0 -31
  160. package/contracts/audit-sweep-result.yaml +0 -53
  161. package/contracts/authority-convergence-audit.schema.yaml +0 -19
  162. package/contracts/closeout.schema.yaml +0 -25
  163. package/contracts/decision-review.schema.yaml +0 -16
  164. package/contracts/doc-spec-audit-result.yaml +0 -19
  165. package/contracts/execution-packet.schema.yaml +0 -49
  166. package/contracts/external-host-compatibility.yaml +0 -22
  167. package/contracts/forbidden-shortcuts.catalog.yaml +0 -23
  168. package/contracts/high-risk-admission.schema.yaml +0 -23
  169. package/contracts/high-risk-execution-result.yaml +0 -20
  170. package/contracts/orchestration-state.schema.yaml +0 -41
  171. package/contracts/overflow-continuation.schema.yaml +0 -12
  172. package/contracts/packet.schema.yaml +0 -30
  173. package/contracts/pending-note.schema.yaml +0 -17
  174. package/contracts/prompt.schema.yaml +0 -12
  175. package/contracts/remediation.schema.yaml +0 -16
  176. package/contracts/result.schema.yaml +0 -24
  177. package/contracts/spec-reconstruction-result.yaml +0 -41
  178. package/contracts/sweep-design-result.yaml +0 -349
  179. package/contracts/topic-goal.schema.yaml +0 -87
  180. package/contracts/topic-run-ledger.schema.yaml +0 -72
  181. package/contracts/topic-step-decision.schema.yaml +0 -45
  182. package/contracts/topic.schema.yaml +0 -65
  183. package/contracts/true-close.schema.yaml +0 -15
  184. package/contracts/wave.schema.yaml +0 -29
  185. package/contracts/worker-output.schema.yaml +0 -15
  186. package/contracts/workflow-consumer.schema.yaml +0 -110
  187. package/methodology/audit-sweep-p0p1-recall.yaml +0 -45
  188. package/methodology/authority-convergence-policy.yaml +0 -42
  189. package/methodology/overflow-continuation-policy.yaml +0 -14
  190. package/methodology/skill-exchange-projection.yaml +0 -114
  191. package/methodology/skill-handoff.yaml +0 -34
  192. package/methodology/skill-installer-result.yaml +0 -27
  193. package/methodology/skill-installer-summary-projection.yaml +0 -181
  194. package/methodology/skill-runtime.yaml +0 -23
  195. package/methodology/spec-target-truth-profile.yaml +0 -46
  196. package/methodology/topic-lifecycle-report.yaml +0 -144
  197. package/methodology/topic-lifecycle.yaml +0 -37
  198. package/methodology/topic-naming-ontology.yaml +0 -21
  199. package/methodology/topic-ontology.yaml +0 -38
  200. package/methodology/topic-validation-policy.yaml +0 -9
  201. package/methodology/wave-dag-policy.yaml +0 -14
  202. package/spec/_meta/command-gating-matrix.yaml +0 -143
  203. package/spec/_meta/generate-drift-migration-checklist.yaml +0 -137
  204. package/spec/_meta/governance-routing-cutover-checklist.yaml +0 -35
  205. package/spec/_meta/phase2-impacted-surface-matrix.yaml +0 -44
  206. package/spec/_meta/spec-authority-cutover-readiness.yaml +0 -102
  207. package/spec/bootstrap-state.yaml +0 -99
@@ -1,18 +1,163 @@
1
- import { inspectDoctorBootstrapSurface } from "./internal/doctor-bootstrap-surface.mjs";
2
- import { inspectDoctorDelegatedSurface } from "./internal/doctor-delegated-surface.mjs";
3
- import { finalizeDoctorState } from "./internal/doctor-finalize.mjs";
4
- import { formatDoctorResult as formatDoctorResultInternal } from "./internal/doctor-format.mjs";
1
+ import { readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+
4
+ import { SPEC_GENERATION_AUDIT_REF } from "../constants.mjs";
5
+ import { getBootstrapSeedEntries } from "../seeds/bootstrap.mjs";
6
+ import { inspectBootstrapCompatibility } from "./bootstrap.mjs";
7
+ import { loadSpecGenerationInputsConfig } from "./contracts.mjs";
8
+ import { pathExists, readTextIfFile } from "./fs-helpers.mjs";
9
+ import { runSeedSync, SYNC_MODE } from "./sync.mjs";
10
+ import { localize, styleHeading, styleLabel, styleStatus } from "./ui.mjs";
11
+
12
+ function check(id, ok, severity, detail) {
13
+ return { id, ok, severity: ok ? "ok" : severity, detail };
14
+ }
15
+
16
+ async function directoryHasFiles(root) {
17
+ const info = await pathExists(root);
18
+ if (!info || !info.isDirectory()) return false;
19
+ const entries = await readdir(root, { withFileTypes: true });
20
+ return entries.length > 0;
21
+ }
22
+
23
+ async function managedEntrypoints(projectRoot) {
24
+ const refs = [];
25
+ for (const ref of ["AGENTS.md", "CLAUDE.md"]) {
26
+ const text = await readTextIfFile(path.join(projectRoot, ref));
27
+ if (text?.includes("nimicoding:managed:")) refs.push(ref);
28
+ }
29
+ return refs;
30
+ }
5
31
 
6
32
  export async function inspectDoctorState(projectRoot) {
7
- const bootstrapSurface = await inspectDoctorBootstrapSurface(projectRoot);
8
- if (bootstrapSurface.done) {
9
- return bootstrapSurface.result;
33
+ const checks = [];
34
+ const bootstrap = await inspectBootstrapCompatibility(projectRoot);
35
+ checks.push(check(
36
+ "bootstrap_contract",
37
+ bootstrap.status === "supported",
38
+ "error",
39
+ bootstrap.status === "supported"
40
+ ? "bootstrap contract is supported"
41
+ : "bootstrap contract is missing or unsupported",
42
+ ));
43
+
44
+ let seedSync = null;
45
+ if (bootstrap.status === "supported") {
46
+ seedSync = await runSeedSync(projectRoot, SYNC_MODE.CHECK);
47
+ checks.push(check(
48
+ "managed_projection",
49
+ seedSync.ok,
50
+ "error",
51
+ seedSync.ok
52
+ ? `all ${seedSync.summary.total} package-managed files are aligned`
53
+ : `${seedSync.checkFailures.length} package-managed files are missing or drifted`,
54
+ ));
10
55
  }
11
56
 
12
- const delegatedSurface = await inspectDoctorDelegatedSurface(projectRoot, bootstrapSurface);
13
- return finalizeDoctorState(projectRoot, bootstrapSurface, delegatedSurface);
57
+ const generationInputs = await loadSpecGenerationInputsConfig(projectRoot);
58
+ checks.push(check(
59
+ "spec_generation_inputs",
60
+ generationInputs.ok && generationInputs.mode === "class_filtered",
61
+ "error",
62
+ generationInputs.ok && generationInputs.mode === "class_filtered"
63
+ ? "spec generation inputs use class-filtered authority"
64
+ : "spec generation inputs are missing or invalid",
65
+ ));
66
+
67
+ const specRoot = path.join(projectRoot, ".nimi", "spec");
68
+ const specPresent = await directoryHasFiles(specRoot);
69
+ checks.push(check(
70
+ "spec_tree",
71
+ true,
72
+ "info",
73
+ specPresent
74
+ ? "canonical spec tree is present; conformance is checked by validate-spec-tree or project-specific validators"
75
+ : "canonical spec tree has not been constructed yet",
76
+ ));
77
+
78
+ const auditPath = path.join(projectRoot, SPEC_GENERATION_AUDIT_REF);
79
+ const auditPresent = Boolean(await pathExists(auditPath));
80
+ checks.push(check(
81
+ "spec_generation_audit",
82
+ true,
83
+ "info",
84
+ auditPresent
85
+ ? "spec generation audit is present; conformance is checked by validate-spec-audit"
86
+ : "spec generation audit is not present",
87
+ ));
88
+
89
+ const entrypoints = await managedEntrypoints(projectRoot);
90
+ checks.push(check(
91
+ "entrypoint_integration",
92
+ true,
93
+ "info",
94
+ entrypoints.length > 0
95
+ ? `managed methodology guidance is present in ${entrypoints.join(", ")}`
96
+ : "managed methodology guidance is not installed",
97
+ ));
98
+
99
+ const seedEntries = await getBootstrapSeedEntries();
100
+ const ok = checks.every((entry) => entry.severity !== "error");
101
+
102
+ return {
103
+ ok,
104
+ projectRoot,
105
+ bootstrap,
106
+ managedProjection: seedSync,
107
+ generationInputs: {
108
+ ok: generationInputs.ok,
109
+ mode: generationInputs.mode ?? null,
110
+ canonicalTargetRoot: generationInputs.canonicalTargetRoot ?? null,
111
+ },
112
+ spec: {
113
+ present: specPresent,
114
+ ok: null,
115
+ summary: null,
116
+ },
117
+ generationAudit: {
118
+ present: auditPresent,
119
+ ok: null,
120
+ summary: null,
121
+ },
122
+ entrypoints,
123
+ managedFileCount: seedEntries.length,
124
+ checks,
125
+ };
14
126
  }
15
127
 
16
128
  export function formatDoctorResult(result, options = {}) {
17
- return formatDoctorResultInternal(result, options);
129
+ const lines = [
130
+ styleHeading(`nimicoding doctor: ${result.projectRoot}`),
131
+ "",
132
+ styleLabel(localize("Summary:", "摘要:")),
133
+ ` - ${localize("status", "状态")}: ${styleStatus(result.ok ? "ok" : "needs_attention")}`,
134
+ ` - bootstrap: ${result.bootstrap.status}`,
135
+ ` - managed_projection: ${result.managedProjection?.ok === true ? "aligned" : "invalid"}`,
136
+ ` - spec: ${!result.spec.present ? "not_constructed" : "present_not_validated"}`,
137
+ ` - generation_audit: ${!result.generationAudit.present ? "not_present" : "present_not_validated"}`,
138
+ "",
139
+ styleLabel(localize("Checks:", "检查项:")),
140
+ ];
141
+
142
+ const visibleChecks = options.verbose
143
+ ? result.checks
144
+ : result.checks.filter((entry) => entry.severity !== "ok" || !entry.ok);
145
+ if (visibleChecks.length === 0) {
146
+ lines.push(` - ${localize("No blocking issues found.", "没有发现阻塞问题。")}`);
147
+ } else {
148
+ for (const entry of visibleChecks) {
149
+ const marker = entry.ok ? "info" : entry.severity;
150
+ lines.push(` - [${marker}] ${entry.detail}`);
151
+ }
152
+ }
153
+
154
+ if (!result.spec.present) {
155
+ lines.push(
156
+ "",
157
+ styleLabel(localize("Next:", "下一步:")),
158
+ " - Build canonical product authority under .nimi/spec, then run nimicoding validate-spec-tree.",
159
+ );
160
+ }
161
+
162
+ return `${lines.join("\n")}\n`;
18
163
  }
@@ -10,85 +10,66 @@ import {
10
10
  import { pathExists } from "./fs-helpers.mjs";
11
11
 
12
12
  function managedAgentsBlock() {
13
- return `${AGENTS_BEGIN}
14
- # Nimi Coding Managed Block
15
-
16
- - Read .nimi/methodology, .nimi/spec, and .nimi/contracts before high-risk changes.
17
- - Treat .nimi as the primary AI truth surface for this project.
18
- - Treat \`/.nimi/spec/**\` as the current repo-wide product authority for this project, and use Git history for retired pre-cutover authority evidence.
19
- - If .nimi/spec remains bootstrap-only, use .nimi/methodology/spec-reconstruction.yaml and .nimi/config/skills.yaml to drive AI-side truth reconstruction.
20
- - Treat .nimi/methodology/spec-target-truth-profile.yaml as repo-local support guidance for future governance slices, not as the canonical reconstruction completion target or a guaranteed fresh-bootstrap seed.
21
- - Treat .nimi/contracts/spec-reconstruction-result.yaml, .nimi/contracts/doc-spec-audit-result.yaml, .nimi/contracts/high-risk-execution-result.yaml, and .nimi/contracts/high-risk-admission.schema.yaml as machine contracts for reconstruction, audit, local-only high-risk closeout summaries, and local-only high-risk admission evidence.
22
- - Treat .nimi/config/skill-manifest.yaml, .nimi/config/host-profile.yaml, .nimi/config/host-adapter.yaml, .nimi/config/external-execution-artifacts.yaml, .nimi/config/skill-installer.yaml, .nimi/methodology/skill-runtime.yaml, .nimi/methodology/skill-installer-result.yaml, .nimi/methodology/skill-handoff.yaml, and admitted package-owned adapter profiles under adapters/**/profile.yaml as the canonical bridge to any external AI/skill execution.
23
- - Treat standalone nimicoding as boundary-complete for bootstrap, handoff, validation, projection, and explicit admission only; do not assume packaged run-kernel, provider, scheduler, notification, or automation ownership.
24
- - Treat .nimi/config/installer-evidence.yaml and .nimi/methodology/skill-installer-summary-projection.yaml as the operational-to-semantic installer projection boundary; do not promote concrete evidence artifacts into semantic truth.
25
- - Treat high-risk external execution closeout, decision, ingest, and review payloads under .nimi/local/** as local-only operational projections; they do not promote semantic truth automatically, even when manager-owned.
26
- - Use high-risk packetized execution only when authority, ownership, or cross-layer risk justifies it.
27
- - Keep inline manager-worker as the default methodology posture; do not assume a separate worker runtime is mandatory.
28
- - Keep code changes AI-context-efficient: favor bounded, cohesive files and split by responsibility during implementation instead of first concentrating unrelated logic into one file.
29
- - Keep the methodology continuity-agnostic; do not assume daemon, heartbeat, or persistent manager ownership.
30
- - Treat cutover readiness as preflight evidence only; the authority flip must come from an admitted cutover batch, not from readiness green by itself.
31
- - Do not treat this managed block as a replacement for project-specific rules outside .nimi.
32
- ${AGENTS_END}`;
13
+ return [
14
+ AGENTS_BEGIN,
15
+ "# Nimi Coding Managed Block",
16
+ "",
17
+ "- Product and repository authority lives under `/.nimi/spec/**`.",
18
+ "- Read `/.nimi/spec/INDEX.md` first, then the affected kernel contracts and tables.",
19
+ "- Read `/.nimi/methodology/**` for reasoning principles and `/.nimi/contracts/**` for spec construction and validation contracts.",
20
+ "- Treat `/.nimi/{config,contracts,methodology}/**` as package-managed governance support, never as product authority.",
21
+ "- Keep generation evidence under `/.nimi/local/state/spec-generation/**`; it must not become product truth.",
22
+ "- Do not treat this managed block as a replacement for project-specific rules.",
23
+ AGENTS_END,
24
+ ].join("\n");
33
25
  }
34
-
35
26
  function managedClaudeBlock() {
36
- return `${CLAUDE_BEGIN}
37
- # Nimi Coding Managed Block
38
-
39
- Use the project's .nimi layer as the primary AI truth surface.
40
-
41
- Priority:
42
- 1. .nimi/methodology
43
- 2. .nimi/spec
44
- 3. .nimi/contracts
45
- 4. .nimi/config
46
- 5. repository-local AI entrypoint files
47
-
48
- If the project still exposes only bootstrap seed files, use the reconstruction guidance, result contracts, manifest, host-profile, host-adapter, admitted package-owned adapter profiles, installer, runtime contract, installer result contract, collapsed installer summary projection lifecycle contract, operational evidence guidance, and handoff truth under .nimi rather than assuming skills are already installed.
27
+ return [
28
+ CLAUDE_BEGIN,
29
+ "# Nimi Coding Managed Block",
30
+ "",
31
+ "Authority order:",
32
+ "1. `/.nimi/spec/**`",
33
+ "2. `/.nimi/methodology/**`",
34
+ "3. `/.nimi/contracts/**`",
35
+ "4. `/.nimi/config/**`",
36
+ "5. repository-local AI entry files",
37
+ "",
38
+ "Nimi Coding owns methodology, canonical spec construction, and deterministic validation only.",
39
+ "Keep local generation evidence outside product authority.",
40
+ CLAUDE_END,
41
+ ].join("\n");
42
+ }
49
43
 
50
- Default posture:
51
- - use risk-shaped methodology only for authority-bearing or high-risk work
52
- - prefer inline manager-worker unless a later admitted packet expands runtime ownership
53
- - keep code changes AI-context-efficient: prefer bounded cohesive files and split by responsibility during implementation instead of first concentrating unrelated logic into one file
54
- - keep continuity-agnostic semantics; do not assume persistent automation or self-hosting
55
- - treat handoff --json as the authoritative machine contract and handoff --prompt as a human-readable projection only
56
- - treat \`/.nimi/spec/**\` as today's repo-wide authority, treat pre-cutover authority history as Git-only, and treat cutover readiness as historical preflight evidence rather than the authority source
57
- ${CLAUDE_END}`;
44
+ function escapeRegExp(value) {
45
+ return value.replace(/[.*+?^$()|[\]{}\\]/g, "\\$&");
58
46
  }
59
47
 
60
- function upsertManagedBlock(existing, begin, end, block) {
61
- const pattern = new RegExp(
62
- `${begin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${end.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`,
48
+ function blockPattern(begin, end, leading = false) {
49
+ return new RegExp(
50
+ `${leading ? "(?:\\n\\n)?" : ""}${escapeRegExp(begin)}[\\s\\S]*?${escapeRegExp(end)}${leading ? "(?:\\n)?" : ""}`,
63
51
  );
52
+ }
64
53
 
54
+ function upsertManagedBlock(existing, begin, end, block) {
55
+ const pattern = blockPattern(begin, end);
65
56
  if (pattern.test(existing)) {
66
57
  return existing.replace(pattern, block);
67
58
  }
68
-
69
59
  const prefix = existing.length === 0 ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
70
60
  return `${existing}${prefix}${block}\n`;
71
61
  }
72
62
 
73
63
  function removeManagedBlock(existing, begin, end) {
74
- const pattern = new RegExp(
75
- `(?:\\n\\n)?${begin.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[\\s\\S]*?${end.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?:\\n)?`,
76
- );
77
-
64
+ const pattern = blockPattern(begin, end, true);
78
65
  if (!pattern.test(existing)) {
79
- return {
80
- changed: false,
81
- next: existing,
82
- deleteFile: false,
83
- };
66
+ return { changed: false, next: existing, deleteFile: false };
84
67
  }
85
-
86
68
  const next = existing
87
69
  .replace(pattern, "\n")
88
70
  .replace(/\n{3,}/g, "\n\n")
89
71
  .replace(/^\n+/, "")
90
72
  .trimEnd();
91
-
92
73
  return {
93
74
  changed: true,
94
75
  next: next.length === 0 ? "" : `${next}\n`,
@@ -99,59 +80,32 @@ function removeManagedBlock(existing, begin, end) {
99
80
  function computeTextFileUpdate(existing, block, begin, end, header) {
100
81
  const base = existing ?? header;
101
82
  const next = upsertManagedBlock(base, begin, end, block);
102
- return {
103
- changed: next !== base,
104
- next,
105
- };
83
+ return { changed: next !== base, next };
106
84
  }
107
85
 
108
86
  async function upsertTextFile(filePath, block, begin, end, header) {
109
87
  const existing = (await pathExists(filePath)) ? await readFile(filePath, "utf8") : header;
110
88
  const computed = computeTextFileUpdate(existing, block, begin, end, header);
111
-
112
- if (!computed.changed) {
113
- return false;
114
- }
115
-
89
+ if (!computed.changed) return false;
116
90
  await writeFile(filePath, computed.next, "utf8");
117
91
  return true;
118
92
  }
119
93
 
120
94
  async function removeManagedTextFile(filePath, begin, end, emptyFallbackHeader = null) {
121
95
  const existing = (await pathExists(filePath)) ? await readFile(filePath, "utf8") : null;
122
- if (existing === null) {
123
- return {
124
- changed: false,
125
- removedFile: false,
126
- };
127
- }
128
-
96
+ if (existing === null) return { changed: false, removedFile: false };
129
97
  const computed = removeManagedBlock(existing, begin, end);
130
- if (!computed.changed) {
131
- return {
132
- changed: false,
133
- removedFile: false,
134
- };
135
- }
136
-
98
+ if (!computed.changed) return { changed: false, removedFile: false };
137
99
  if (computed.deleteFile || (emptyFallbackHeader && computed.next.trim() === emptyFallbackHeader.trim())) {
138
100
  await rm(filePath, { force: true });
139
- return {
140
- changed: true,
141
- removedFile: true,
142
- };
101
+ return { changed: true, removedFile: true };
143
102
  }
144
-
145
103
  await writeFile(filePath, computed.next, "utf8");
146
- return {
147
- changed: true,
148
- removedFile: false,
149
- };
104
+ return { changed: true, removedFile: false };
150
105
  }
151
106
 
152
- export async function previewEntrypointIntegration(projectRoot) {
153
- const updates = [];
154
- const files = [
107
+ function entrypointDefinitions(projectRoot) {
108
+ return [
155
109
  {
156
110
  path: path.join(projectRoot, "AGENTS.md"),
157
111
  block: managedAgentsBlock(),
@@ -169,106 +123,48 @@ export async function previewEntrypointIntegration(projectRoot) {
169
123
  relativePath: "CLAUDE.md",
170
124
  },
171
125
  ];
126
+ }
172
127
 
173
- for (const file of files) {
128
+ export async function previewEntrypointIntegration(projectRoot) {
129
+ const updates = [];
130
+ for (const file of entrypointDefinitions(projectRoot)) {
174
131
  const existing = (await pathExists(file.path)) ? await readFile(file.path, "utf8") : null;
175
- const computed = computeTextFileUpdate(existing, file.block, file.begin, file.end, file.header);
176
- if (computed.changed) {
132
+ if (computeTextFileUpdate(existing, file.block, file.begin, file.end, file.header).changed) {
177
133
  updates.push(file.relativePath);
178
134
  }
179
135
  }
180
-
181
136
  return updates;
182
137
  }
183
138
 
184
139
  export async function integrateEntrypoints(projectRoot) {
185
140
  const updated = [];
186
-
187
- if (
188
- await upsertTextFile(
189
- path.join(projectRoot, "AGENTS.md"),
190
- managedAgentsBlock(),
191
- AGENTS_BEGIN,
192
- AGENTS_END,
193
- "# AGENTS.md\n",
194
- )
195
- ) {
196
- updated.push("AGENTS.md");
197
- }
198
-
199
- if (
200
- await upsertTextFile(
201
- path.join(projectRoot, "CLAUDE.md"),
202
- managedClaudeBlock(),
203
- CLAUDE_BEGIN,
204
- CLAUDE_END,
205
- "# CLAUDE.md\n",
206
- )
207
- ) {
208
- updated.push("CLAUDE.md");
141
+ for (const file of entrypointDefinitions(projectRoot)) {
142
+ if (await upsertTextFile(file.path, file.block, file.begin, file.end, file.header)) {
143
+ updated.push(file.relativePath);
144
+ }
209
145
  }
210
-
211
146
  return updated;
212
147
  }
213
148
 
214
149
  export async function previewEntrypointRemoval(projectRoot) {
215
150
  const updates = [];
216
- const files = [
217
- {
218
- path: path.join(projectRoot, "AGENTS.md"),
219
- begin: AGENTS_BEGIN,
220
- end: AGENTS_END,
221
- relativePath: "AGENTS.md",
222
- },
223
- {
224
- path: path.join(projectRoot, "CLAUDE.md"),
225
- begin: CLAUDE_BEGIN,
226
- end: CLAUDE_END,
227
- relativePath: "CLAUDE.md",
228
- },
229
- ];
230
-
231
- for (const file of files) {
151
+ for (const file of entrypointDefinitions(projectRoot)) {
232
152
  const existing = (await pathExists(file.path)) ? await readFile(file.path, "utf8") : null;
233
- if (existing === null) {
234
- continue;
235
- }
236
-
237
- const computed = removeManagedBlock(existing, file.begin, file.end);
238
- if (computed.changed) {
153
+ if (existing !== null && removeManagedBlock(existing, file.begin, file.end).changed) {
239
154
  updates.push(file.relativePath);
240
155
  }
241
156
  }
242
-
243
157
  return updates;
244
158
  }
245
159
 
246
160
  export async function removeManagedEntrypoints(projectRoot) {
247
161
  const updatedFiles = [];
248
162
  const removedFiles = [];
249
-
250
- const agentsResult = await removeManagedTextFile(
251
- path.join(projectRoot, "AGENTS.md"),
252
- AGENTS_BEGIN,
253
- AGENTS_END,
254
- "# AGENTS.md",
255
- );
256
- if (agentsResult.changed) {
257
- (agentsResult.removedFile ? removedFiles : updatedFiles).push("AGENTS.md");
258
- }
259
-
260
- const claudeResult = await removeManagedTextFile(
261
- path.join(projectRoot, "CLAUDE.md"),
262
- CLAUDE_BEGIN,
263
- CLAUDE_END,
264
- "# CLAUDE.md",
265
- );
266
- if (claudeResult.changed) {
267
- (claudeResult.removedFile ? removedFiles : updatedFiles).push("CLAUDE.md");
163
+ for (const file of entrypointDefinitions(projectRoot)) {
164
+ const result = await removeManagedTextFile(file.path, file.begin, file.end, file.header.trim());
165
+ if (result.changed) {
166
+ (result.removedFile ? removedFiles : updatedFiles).push(file.relativePath);
167
+ }
268
168
  }
269
-
270
- return {
271
- updatedFiles,
272
- removedFiles,
273
- };
169
+ return { updatedFiles, removedFiles };
274
170
  }
@@ -1,39 +1,17 @@
1
1
  import path from "node:path";
2
2
 
3
3
  import {
4
- AUDIT_SWEEP_RESULT_CONTRACT_REF,
5
- ACCEPTANCE_SCHEMA_REF,
6
4
  BLUEPRINT_REFERENCE_REF,
7
- COMMAND_GATING_MATRIX_REF,
8
- DOC_SPEC_AUDIT_RESULT_CONTRACT_REF,
9
- EXTERNAL_HOST_COMPATIBILITY_CONTRACT_REF,
10
- EXECUTION_PACKET_SCHEMA_REF,
11
- HIGH_RISK_ADMISSION_CONTRACT_REF,
12
- HIGH_RISK_EXECUTION_RESULT_CONTRACT_REF,
13
- ORCHESTRATION_STATE_SCHEMA_REF,
14
- PROMPT_SCHEMA_REF,
15
5
  SPEC_GENERATION_AUDIT_CONTRACT_REF,
16
6
  SPEC_GENERATION_INPUTS_CONTRACT_REF,
17
7
  SPEC_GENERATION_INPUTS_REF,
18
- SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF,
19
- SPEC_TREE_MODEL_REF,
20
- WORKER_OUTPUT_SCHEMA_REF,
21
8
  } from "../../constants.mjs";
22
9
  import { readTextIfFile } from "../fs-helpers.mjs";
23
10
  import {
24
11
  parseBlueprintReference,
25
- parseCommandGatingMatrix,
26
- parseAuditSweepContract,
27
- parseDocSpecAuditContract,
28
- parseExternalHostCompatibilityContract,
29
- parseHighRiskAdmissionContract,
30
- parseHighRiskExecutionContract,
31
- parseHighRiskSchemaContract,
32
12
  parseSpecGenerationAuditContract,
33
13
  parseSpecGenerationInputsConfig,
34
14
  parseSpecGenerationInputsContract,
35
- parseSpecReconstructionContract,
36
- parseSpecTreeModel,
37
15
  } from "./contracts-parse.mjs";
38
16
 
39
17
  async function loadParsedYaml(projectRoot, relativePath, parse) {
@@ -44,19 +22,6 @@ async function loadParsedYaml(projectRoot, relativePath, parse) {
44
22
  ...parse(text),
45
23
  };
46
24
  }
47
-
48
- export function loadSpecReconstructionContract(projectRoot) {
49
- return loadParsedYaml(
50
- projectRoot,
51
- SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF,
52
- parseSpecReconstructionContract,
53
- );
54
- }
55
-
56
- export function loadSpecTreeModelContract(projectRoot) {
57
- return loadParsedYaml(projectRoot, SPEC_TREE_MODEL_REF, parseSpecTreeModel);
58
- }
59
-
60
25
  export function loadSpecGenerationInputsContract(projectRoot) {
61
26
  return loadParsedYaml(
62
27
  projectRoot,
@@ -77,56 +42,6 @@ export function loadSpecGenerationInputsConfig(projectRoot) {
77
42
  return loadParsedYaml(projectRoot, SPEC_GENERATION_INPUTS_REF, parseSpecGenerationInputsConfig);
78
43
  }
79
44
 
80
- export function loadCommandGatingMatrix(projectRoot) {
81
- return loadParsedYaml(projectRoot, COMMAND_GATING_MATRIX_REF, parseCommandGatingMatrix);
82
- }
83
-
84
45
  export function loadBlueprintReference(projectRoot) {
85
46
  return loadParsedYaml(projectRoot, BLUEPRINT_REFERENCE_REF, parseBlueprintReference);
86
47
  }
87
-
88
- export function loadDocSpecAuditContract(projectRoot) {
89
- return loadParsedYaml(projectRoot, DOC_SPEC_AUDIT_RESULT_CONTRACT_REF, parseDocSpecAuditContract);
90
- }
91
-
92
- export function loadAuditSweepContract(projectRoot) {
93
- return loadParsedYaml(projectRoot, AUDIT_SWEEP_RESULT_CONTRACT_REF, parseAuditSweepContract);
94
- }
95
-
96
- export function loadHighRiskExecutionContract(projectRoot) {
97
- return loadParsedYaml(projectRoot, HIGH_RISK_EXECUTION_RESULT_CONTRACT_REF, parseHighRiskExecutionContract);
98
- }
99
-
100
- export function loadHighRiskAdmissionContract(projectRoot) {
101
- return loadParsedYaml(projectRoot, HIGH_RISK_ADMISSION_CONTRACT_REF, parseHighRiskAdmissionContract);
102
- }
103
-
104
- export function loadExternalHostCompatibilityContract(projectRoot) {
105
- return loadParsedYaml(
106
- projectRoot,
107
- EXTERNAL_HOST_COMPATIBILITY_CONTRACT_REF,
108
- parseExternalHostCompatibilityContract,
109
- );
110
- }
111
-
112
- export async function loadHighRiskSchemaContracts(projectRoot) {
113
- const contractRefs = [
114
- EXECUTION_PACKET_SCHEMA_REF,
115
- ORCHESTRATION_STATE_SCHEMA_REF,
116
- PROMPT_SCHEMA_REF,
117
- WORKER_OUTPUT_SCHEMA_REF,
118
- ACCEPTANCE_SCHEMA_REF,
119
- ];
120
-
121
- const results = [];
122
- for (const schemaRef of contractRefs) {
123
- const text = await readTextIfFile(path.join(projectRoot, schemaRef));
124
- results.push({
125
- path: schemaRef,
126
- text,
127
- ...parseHighRiskSchemaContract(text, schemaRef),
128
- });
129
- }
130
-
131
- return results;
132
- }