@nimiplatform/nimi-coding 0.2.8 → 0.3.1

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 (206) hide show
  1. package/CHANGELOG.md +10 -90
  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/commands/validate-spec-governance.mjs +20 -0
  8. package/cli/constants.mjs +9 -417
  9. package/cli/help.mjs +28 -145
  10. package/cli/index.mjs +5 -33
  11. package/cli/lib/blueprint-audit.mjs +5 -12
  12. package/cli/lib/bootstrap.mjs +0 -9
  13. package/cli/lib/contracts.mjs +0 -163
  14. package/cli/lib/doctor.mjs +155 -10
  15. package/cli/lib/entrypoints.mjs +63 -167
  16. package/cli/lib/internal/contracts-loaders.mjs +0 -85
  17. package/cli/lib/internal/contracts-parse.mjs +84 -520
  18. package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +13 -8
  19. package/cli/lib/internal/surface-taxonomy-validators.mjs +316 -66
  20. package/cli/lib/internal/validators-shared.mjs +0 -16
  21. package/cli/lib/internal/validators-spec-helpers.mjs +7 -140
  22. package/cli/lib/internal/validators-spec.mjs +103 -342
  23. package/cli/lib/shared.mjs +1 -42
  24. package/cli/lib/validators.mjs +0 -48
  25. package/cli/seeds/seed-policy.yaml +0 -3
  26. package/config/bootstrap.yaml +4 -4
  27. package/config/spec-generation-inputs.yaml +6 -12
  28. package/contracts/domain-admission.schema.yaml +3 -3
  29. package/contracts/migration-inventory.schema.yaml +12 -75
  30. package/contracts/negative-fixtures.yaml +19 -99
  31. package/contracts/placement-contract.schema.yaml +49 -78
  32. package/contracts/projection-edge.schema.yaml +37 -121
  33. package/contracts/shared-enums.yaml +4 -8
  34. package/contracts/spec-generation-inputs.schema.yaml +15 -112
  35. package/contracts/spec-layout.schema.yaml +32 -0
  36. package/contracts/surface-taxonomy.schema.yaml +43 -94
  37. package/contracts/table-family.schema.yaml +1 -1
  38. package/contracts/tracked-output-admission.schema.yaml +13 -66
  39. package/methodology/core.yaml +33 -25
  40. package/methodology/four-closure-policy.yaml +18 -26
  41. package/methodology/role-separation-policy.yaml +21 -27
  42. package/methodology/spec-reconstruction.yaml +17 -34
  43. package/package.json +2 -4
  44. package/spec/_meta/spec-tree-model.yaml +5 -101
  45. package/spec/product-scope.yaml +25 -57
  46. package/adapters/README.md +0 -25
  47. package/adapters/claude/README.md +0 -89
  48. package/adapters/claude/profile.yaml +0 -70
  49. package/adapters/codex/README.md +0 -53
  50. package/adapters/codex/profile.yaml +0 -78
  51. package/adapters/oh-my-codex/README.md +0 -184
  52. package/adapters/oh-my-codex/profile.yaml +0 -46
  53. package/cli/commands/admit-high-risk-decision.mjs +0 -108
  54. package/cli/commands/audit-sweep.mjs +0 -364
  55. package/cli/commands/closeout.mjs +0 -186
  56. package/cli/commands/decide-high-risk-execution.mjs +0 -124
  57. package/cli/commands/handoff.mjs +0 -123
  58. package/cli/commands/ingest-high-risk-execution.mjs +0 -95
  59. package/cli/commands/review-high-risk-execution.mjs +0 -95
  60. package/cli/commands/sweep-design.mjs +0 -295
  61. package/cli/commands/sweep.mjs +0 -22
  62. package/cli/commands/topic-formatters.mjs +0 -382
  63. package/cli/commands/topic-goal.mjs +0 -33
  64. package/cli/commands/topic-options-shared.mjs +0 -27
  65. package/cli/commands/topic-options-workflow.mjs +0 -767
  66. package/cli/commands/topic-options.mjs +0 -626
  67. package/cli/commands/topic-runner.mjs +0 -169
  68. package/cli/commands/topic.mjs +0 -795
  69. package/cli/commands/validate-acceptance.mjs +0 -5
  70. package/cli/commands/validate-execution-packet.mjs +0 -5
  71. package/cli/commands/validate-orchestration-state.mjs +0 -5
  72. package/cli/commands/validate-prompt.mjs +0 -5
  73. package/cli/commands/validate-worker-output.mjs +0 -5
  74. package/cli/lib/adapter-profiles.mjs +0 -403
  75. package/cli/lib/audit-execution.mjs +0 -52
  76. package/cli/lib/audit-sweep-runtime/admissions.mjs +0 -508
  77. package/cli/lib/audit-sweep-runtime/audit-validity.mjs +0 -356
  78. package/cli/lib/audit-sweep-runtime/chunks.mjs +0 -697
  79. package/cli/lib/audit-sweep-runtime/claude-auditor.mjs +0 -658
  80. package/cli/lib/audit-sweep-runtime/closeout.mjs +0 -144
  81. package/cli/lib/audit-sweep-runtime/codex-auditor-evidence.mjs +0 -654
  82. package/cli/lib/audit-sweep-runtime/codex-auditor.mjs +0 -527
  83. package/cli/lib/audit-sweep-runtime/common.mjs +0 -341
  84. package/cli/lib/audit-sweep-runtime/coverage-quality.mjs +0 -172
  85. package/cli/lib/audit-sweep-runtime/evidence-assignment.mjs +0 -155
  86. package/cli/lib/audit-sweep-runtime/format.mjs +0 -57
  87. package/cli/lib/audit-sweep-runtime/ingest.mjs +0 -486
  88. package/cli/lib/audit-sweep-runtime/inventory-spec-chunks.mjs +0 -425
  89. package/cli/lib/audit-sweep-runtime/inventory.mjs +0 -798
  90. package/cli/lib/audit-sweep-runtime/ledger.mjs +0 -315
  91. package/cli/lib/audit-sweep-runtime/p0p1-profile.mjs +0 -101
  92. package/cli/lib/audit-sweep-runtime/remediation.mjs +0 -349
  93. package/cli/lib/audit-sweep-runtime/rerun.mjs +0 -129
  94. package/cli/lib/audit-sweep-runtime/risk-budget.mjs +0 -300
  95. package/cli/lib/audit-sweep-runtime/status.mjs +0 -62
  96. package/cli/lib/audit-sweep-runtime/validators-ledger.mjs +0 -215
  97. package/cli/lib/audit-sweep-runtime/validators.mjs +0 -797
  98. package/cli/lib/audit-sweep.mjs +0 -19
  99. package/cli/lib/authority-convergence.mjs +0 -720
  100. package/cli/lib/closeout.mjs +0 -732
  101. package/cli/lib/codex-sdk-runner.mjs +0 -76
  102. package/cli/lib/external-execution.mjs +0 -101
  103. package/cli/lib/handoff.mjs +0 -812
  104. package/cli/lib/high-risk-admission.mjs +0 -512
  105. package/cli/lib/high-risk-decision.mjs +0 -353
  106. package/cli/lib/high-risk-ingest.mjs +0 -321
  107. package/cli/lib/high-risk-review.mjs +0 -267
  108. package/cli/lib/internal/contracts-parse-high-risk.mjs +0 -131
  109. package/cli/lib/internal/contracts-validators.mjs +0 -399
  110. package/cli/lib/internal/doctor-bootstrap-surface.mjs +0 -406
  111. package/cli/lib/internal/doctor-delegated-surface.mjs +0 -256
  112. package/cli/lib/internal/doctor-finalize.mjs +0 -383
  113. package/cli/lib/internal/doctor-format.mjs +0 -286
  114. package/cli/lib/internal/doctor-inspectors.mjs +0 -327
  115. package/cli/lib/internal/doctor-state.mjs +0 -205
  116. package/cli/lib/internal/validators-artifacts.mjs +0 -515
  117. package/cli/lib/sweep-design-runtime/common.mjs +0 -246
  118. package/cli/lib/sweep-design-runtime/engine.mjs +0 -733
  119. package/cli/lib/sweep-design-runtime/fix-topic.mjs +0 -414
  120. package/cli/lib/sweep-design-runtime/lifecycle.mjs +0 -54
  121. package/cli/lib/sweep-design-runtime/results.mjs +0 -324
  122. package/cli/lib/sweep-design.mjs +0 -8
  123. package/cli/lib/topic-artifacts.mjs +0 -186
  124. package/cli/lib/topic-authority-coverage.mjs +0 -73
  125. package/cli/lib/topic-closeout.mjs +0 -560
  126. package/cli/lib/topic-common.mjs +0 -404
  127. package/cli/lib/topic-decisions.mjs +0 -332
  128. package/cli/lib/topic-draft-packets.mjs +0 -167
  129. package/cli/lib/topic-execution.mjs +0 -533
  130. package/cli/lib/topic-goal.mjs +0 -440
  131. package/cli/lib/topic-ledger.mjs +0 -281
  132. package/cli/lib/topic-lifecycle-artifacts.mjs +0 -173
  133. package/cli/lib/topic-root-validation.mjs +0 -288
  134. package/cli/lib/topic-runner-commands.mjs +0 -174
  135. package/cli/lib/topic-runner-deferral.mjs +0 -532
  136. package/cli/lib/topic-runner-stale-gates.mjs +0 -114
  137. package/cli/lib/topic-runner-validation.mjs +0 -138
  138. package/cli/lib/topic-runner.mjs +0 -727
  139. package/cli/lib/topic-scaffold.mjs +0 -252
  140. package/cli/lib/topic-waves.mjs +0 -403
  141. package/cli/lib/topic.mjs +0 -81
  142. package/config/audit-execution-artifacts.yaml +0 -20
  143. package/config/external-execution-artifacts.yaml +0 -16
  144. package/config/host-adapter.yaml +0 -30
  145. package/config/host-profile.yaml +0 -29
  146. package/config/installer-evidence.yaml +0 -31
  147. package/config/skill-installer.yaml +0 -23
  148. package/config/skill-manifest.yaml +0 -48
  149. package/config/skills.yaml +0 -30
  150. package/contracts/acceptance.schema.yaml +0 -16
  151. package/contracts/admission-checklist.schema.yaml +0 -15
  152. package/contracts/audit-chunk.schema.yaml +0 -123
  153. package/contracts/audit-closeout.schema.yaml +0 -51
  154. package/contracts/audit-finding.schema.yaml +0 -61
  155. package/contracts/audit-ledger.schema.yaml +0 -138
  156. package/contracts/audit-plan.schema.yaml +0 -138
  157. package/contracts/audit-remediation-map.schema.yaml +0 -52
  158. package/contracts/audit-rerun.schema.yaml +0 -31
  159. package/contracts/audit-sweep-result.yaml +0 -53
  160. package/contracts/authority-convergence-audit.schema.yaml +0 -19
  161. package/contracts/closeout.schema.yaml +0 -25
  162. package/contracts/decision-review.schema.yaml +0 -16
  163. package/contracts/doc-spec-audit-result.yaml +0 -19
  164. package/contracts/execution-packet.schema.yaml +0 -49
  165. package/contracts/external-host-compatibility.yaml +0 -22
  166. package/contracts/forbidden-shortcuts.catalog.yaml +0 -23
  167. package/contracts/high-risk-admission.schema.yaml +0 -23
  168. package/contracts/high-risk-execution-result.yaml +0 -20
  169. package/contracts/orchestration-state.schema.yaml +0 -41
  170. package/contracts/overflow-continuation.schema.yaml +0 -12
  171. package/contracts/packet.schema.yaml +0 -30
  172. package/contracts/pending-note.schema.yaml +0 -17
  173. package/contracts/prompt.schema.yaml +0 -12
  174. package/contracts/remediation.schema.yaml +0 -16
  175. package/contracts/result.schema.yaml +0 -24
  176. package/contracts/spec-reconstruction-result.yaml +0 -41
  177. package/contracts/sweep-design-result.yaml +0 -349
  178. package/contracts/topic-goal.schema.yaml +0 -87
  179. package/contracts/topic-run-ledger.schema.yaml +0 -72
  180. package/contracts/topic-step-decision.schema.yaml +0 -45
  181. package/contracts/topic.schema.yaml +0 -65
  182. package/contracts/true-close.schema.yaml +0 -15
  183. package/contracts/wave.schema.yaml +0 -29
  184. package/contracts/worker-output.schema.yaml +0 -15
  185. package/contracts/workflow-consumer.schema.yaml +0 -110
  186. package/methodology/audit-sweep-p0p1-recall.yaml +0 -45
  187. package/methodology/authority-convergence-policy.yaml +0 -42
  188. package/methodology/overflow-continuation-policy.yaml +0 -14
  189. package/methodology/skill-exchange-projection.yaml +0 -114
  190. package/methodology/skill-handoff.yaml +0 -34
  191. package/methodology/skill-installer-result.yaml +0 -27
  192. package/methodology/skill-installer-summary-projection.yaml +0 -181
  193. package/methodology/skill-runtime.yaml +0 -23
  194. package/methodology/spec-target-truth-profile.yaml +0 -46
  195. package/methodology/topic-lifecycle-report.yaml +0 -144
  196. package/methodology/topic-lifecycle.yaml +0 -37
  197. package/methodology/topic-naming-ontology.yaml +0 -21
  198. package/methodology/topic-ontology.yaml +0 -38
  199. package/methodology/topic-validation-policy.yaml +0 -9
  200. package/methodology/wave-dag-policy.yaml +0 -14
  201. package/spec/_meta/command-gating-matrix.yaml +0 -143
  202. package/spec/_meta/generate-drift-migration-checklist.yaml +0 -137
  203. package/spec/_meta/governance-routing-cutover-checklist.yaml +0 -35
  204. package/spec/_meta/phase2-impacted-surface-matrix.yaml +0 -44
  205. package/spec/_meta/spec-authority-cutover-readiness.yaml +0 -102
  206. 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
- }