@nimiplatform/nimi-coding 0.1.0 → 0.2.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.
- package/CHANGELOG.md +19 -0
- package/CODE_OF_CONDUCT.md +28 -0
- package/CONTRIBUTING.md +45 -0
- package/README.md +371 -344
- package/README.zh-CN.md +307 -0
- package/SECURITY.md +26 -0
- package/adapters/oh-my-codex/README.md +8 -9
- package/cli/commands/audit-sweep.mjs +10 -10
- package/cli/commands/classify-spec-tree.mjs +5 -0
- package/cli/commands/closeout.mjs +3 -0
- package/cli/commands/generate-spec-derived-docs.mjs +20 -0
- package/cli/commands/generate-spec-migration-plan.mjs +30 -0
- package/cli/commands/start.mjs +5 -1
- package/cli/commands/surface-validator-command.mjs +49 -0
- package/cli/commands/sweep-design.mjs +295 -0
- package/cli/commands/sweep.mjs +22 -0
- package/cli/commands/sync.mjs +132 -0
- package/cli/commands/topic-formatters.mjs +8 -8
- package/cli/commands/validate-ai-governance.mjs +167 -46
- package/cli/commands/validate-domain-admission.mjs +5 -0
- package/cli/commands/validate-guidance-bodies.mjs +5 -0
- package/cli/commands/validate-placement.mjs +5 -0
- package/cli/commands/validate-projection-edges.mjs +5 -0
- package/cli/commands/validate-spec-audit.mjs +5 -1
- package/cli/commands/validate-table-family.mjs +5 -0
- package/cli/commands/validate-tracked-output-admission.mjs +5 -0
- package/cli/constants.mjs +5 -49
- package/cli/help.mjs +33 -11
- package/cli/index.mjs +20 -2
- package/cli/lib/audit-sweep-runtime/admissions.mjs +38 -29
- package/cli/lib/audit-sweep-runtime/audit-validity.mjs +8 -0
- package/cli/lib/audit-sweep-runtime/chunks.mjs +11 -11
- package/cli/lib/audit-sweep-runtime/closeout.mjs +8 -8
- package/cli/lib/audit-sweep-runtime/codex-auditor-evidence.mjs +3 -3
- package/cli/lib/audit-sweep-runtime/codex-auditor.mjs +10 -10
- package/cli/lib/audit-sweep-runtime/common.mjs +7 -7
- package/cli/lib/audit-sweep-runtime/format.mjs +3 -3
- package/cli/lib/audit-sweep-runtime/ingest.mjs +8 -8
- package/cli/lib/audit-sweep-runtime/inventory-spec-chunks.mjs +24 -27
- package/cli/lib/audit-sweep-runtime/inventory.mjs +58 -18
- package/cli/lib/audit-sweep-runtime/ledger.mjs +1 -1
- package/cli/lib/audit-sweep-runtime/p0p1-profile.mjs +2 -2
- package/cli/lib/audit-sweep-runtime/remediation.mjs +6 -6
- package/cli/lib/audit-sweep-runtime/rerun.mjs +6 -6
- package/cli/lib/audit-sweep-runtime/status.mjs +1 -1
- package/cli/lib/audit-sweep-runtime/validators.mjs +2 -2
- package/cli/lib/authority-convergence.mjs +397 -2
- package/cli/lib/blueprint-audit.mjs +5 -5
- package/cli/lib/closeout.mjs +126 -3
- package/cli/lib/contracts.mjs +21 -17
- package/cli/lib/handoff.mjs +29 -11
- package/cli/lib/high-risk-admission.mjs +60 -11
- package/cli/lib/high-risk-decision.mjs +31 -2
- package/cli/lib/high-risk-ingest.mjs +5 -1
- package/cli/lib/high-risk-review.mjs +5 -1
- package/cli/lib/internal/contracts-parse.mjs +195 -24
- package/cli/lib/internal/contracts-validators.mjs +3 -2
- package/cli/lib/internal/doctor-bootstrap-surface.mjs +82 -35
- package/cli/lib/internal/doctor-delegated-surface.mjs +1 -1
- package/cli/lib/internal/doctor-finalize.mjs +12 -8
- package/cli/lib/internal/doctor-inspectors.mjs +34 -1
- package/cli/lib/internal/governance/ai/ai-context-budget-core.mjs +74 -12
- package/cli/lib/internal/governance/ai/ai-structure-budget-core.mjs +24 -6
- package/cli/lib/internal/governance/ai/check-agents-freshness.mjs +18 -23
- package/cli/lib/internal/surface-taxonomy-validators.mjs +931 -0
- package/cli/lib/internal/validators-spec.mjs +229 -20
- package/cli/lib/sweep-design-runtime/common.mjs +246 -0
- package/cli/lib/sweep-design-runtime/engine.mjs +733 -0
- package/cli/lib/sweep-design-runtime/fix-topic.mjs +414 -0
- package/cli/lib/sweep-design-runtime/lifecycle.mjs +54 -0
- package/cli/lib/sweep-design-runtime/results.mjs +324 -0
- package/cli/lib/sweep-design.mjs +8 -0
- package/cli/lib/sync.mjs +143 -0
- package/cli/lib/topic-artifacts.mjs +186 -0
- package/cli/lib/topic-authority-coverage.mjs +73 -0
- package/cli/lib/topic-closeout.mjs +560 -0
- package/cli/lib/topic-common.mjs +404 -0
- package/cli/lib/topic-decisions.mjs +332 -0
- package/cli/lib/topic-draft-packets.mjs +126 -7
- package/cli/lib/topic-execution.mjs +515 -0
- package/cli/lib/topic-goal.mjs +112 -33
- package/cli/lib/topic-ledger.mjs +281 -0
- package/cli/lib/topic-lifecycle-artifacts.mjs +173 -0
- package/cli/lib/topic-root-validation.mjs +288 -0
- package/cli/lib/topic-runner-commands.mjs +174 -0
- package/cli/lib/topic-runner-deferral.mjs +532 -0
- package/cli/lib/topic-runner-stale-gates.mjs +114 -0
- package/cli/lib/topic-runner-validation.mjs +138 -0
- package/cli/lib/topic-runner.mjs +109 -154
- package/cli/lib/topic-scaffold.mjs +252 -0
- package/cli/lib/topic-waves.mjs +403 -0
- package/cli/lib/topic.mjs +81 -93
- package/cli/lib/value-helpers.mjs +6 -1
- package/cli/seeds/bootstrap.mjs +96 -20
- package/cli/seeds/seed-policy.yaml +67 -0
- package/config/bootstrap.yaml +1 -1
- package/config/skill-manifest.yaml +4 -2
- package/config/spec-generation-inputs.yaml +41 -19
- package/contracts/audit-remediation-map.schema.yaml +1 -0
- package/contracts/audit-sweep-result.yaml +4 -0
- package/contracts/domain-admission.schema.yaml +56 -0
- package/contracts/migration-inventory.schema.yaml +80 -0
- package/contracts/negative-fixtures.yaml +91 -0
- package/contracts/placement-contract.schema.yaml +163 -0
- package/contracts/projection-edge.schema.yaml +130 -0
- package/contracts/shared-enums.yaml +68 -0
- package/contracts/spec-generation-audit.schema.yaml +19 -4
- package/contracts/spec-generation-inputs.schema.yaml +130 -29
- package/contracts/spec-reconstruction-result.yaml +9 -5
- package/contracts/surface-taxonomy.schema.yaml +201 -0
- package/contracts/sweep-design-result.yaml +349 -0
- package/contracts/table-family.schema.yaml +121 -0
- package/contracts/topic-goal.schema.yaml +10 -1
- package/contracts/tracked-output-admission.schema.yaml +70 -0
- package/contracts/workflow-consumer.schema.yaml +112 -0
- package/methodology/audit-sweep-p0p1-recall.yaml +1 -1
- package/methodology/spec-reconstruction.yaml +53 -30
- package/package.json +19 -4
- package/spec/_meta/command-gating-matrix.yaml +33 -0
- package/spec/_meta/generate-drift-migration-checklist.yaml +44 -62
- package/spec/_meta/governance-routing-cutover-checklist.yaml +3 -3
- package/spec/_meta/phase2-impacted-surface-matrix.yaml +14 -14
- package/spec/_meta/spec-authority-cutover-readiness.yaml +3 -5
- package/spec/_meta/spec-tree-model.yaml +104 -36
- package/spec/bootstrap-state.yaml +36 -36
- package/spec/product-scope.yaml +13 -10
package/cli/lib/contracts.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
loadBlueprintReference as loadBlueprintReferenceInternal,
|
|
@@ -27,6 +28,9 @@ import {
|
|
|
27
28
|
validateSpecReconstructionSummary as validateSpecReconstructionSummaryInternal,
|
|
28
29
|
} from "./internal/contracts-validators.mjs";
|
|
29
30
|
|
|
31
|
+
const PACKAGE_REF_PREFIX = "package://@nimiplatform/nimi-coding/";
|
|
32
|
+
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
33
|
+
|
|
30
34
|
export function findCommandGatingRule(commandGatingMatrix, command, skillId = null) {
|
|
31
35
|
return matchCommandGatingRule(commandGatingMatrix, command, skillId);
|
|
32
36
|
}
|
|
@@ -117,9 +121,9 @@ async function loadYamlWithFallback(projectRoot, primaryRef, fallbackRef) {
|
|
|
117
121
|
};
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
const fallbackText = await readTextIfFile(path.join(
|
|
124
|
+
const fallbackText = await readTextIfFile(path.join(PACKAGE_ROOT, fallbackRef));
|
|
121
125
|
return {
|
|
122
|
-
path: fallbackRef
|
|
126
|
+
path: `${PACKAGE_REF_PREFIX}${fallbackRef}`,
|
|
123
127
|
text: fallbackText,
|
|
124
128
|
data: parseYamlText(fallbackText),
|
|
125
129
|
};
|
|
@@ -143,21 +147,21 @@ export async function loadTopicRuntimeContracts(projectRoot) {
|
|
|
143
147
|
validationPolicy,
|
|
144
148
|
authorityConvergencePolicy,
|
|
145
149
|
] = await Promise.all([
|
|
146
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/topic.schema.yaml", "
|
|
147
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/wave.schema.yaml", "
|
|
148
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/packet.schema.yaml", "
|
|
149
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/result.schema.yaml", "
|
|
150
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/closeout.schema.yaml", "
|
|
151
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/remediation.schema.yaml", "
|
|
152
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/decision-review.schema.yaml", "
|
|
153
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/pending-note.schema.yaml", "
|
|
154
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/topic-step-decision.schema.yaml", "
|
|
155
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/topic-run-ledger.schema.yaml", "
|
|
156
|
-
loadYamlWithFallback(projectRoot, ".nimi/contracts/forbidden-shortcuts.catalog.yaml", "
|
|
157
|
-
loadYamlWithFallback(projectRoot, ".nimi/methodology/topic-lifecycle-report.yaml", "
|
|
158
|
-
loadYamlWithFallback(projectRoot, ".nimi/methodology/four-closure-policy.yaml", "
|
|
159
|
-
loadYamlWithFallback(projectRoot, ".nimi/methodology/topic-validation-policy.yaml", "
|
|
160
|
-
loadYamlWithFallback(projectRoot, ".nimi/methodology/authority-convergence-policy.yaml", "
|
|
150
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/topic.schema.yaml", "contracts/topic.schema.yaml"),
|
|
151
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/wave.schema.yaml", "contracts/wave.schema.yaml"),
|
|
152
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/packet.schema.yaml", "contracts/packet.schema.yaml"),
|
|
153
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/result.schema.yaml", "contracts/result.schema.yaml"),
|
|
154
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/closeout.schema.yaml", "contracts/closeout.schema.yaml"),
|
|
155
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/remediation.schema.yaml", "contracts/remediation.schema.yaml"),
|
|
156
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/decision-review.schema.yaml", "contracts/decision-review.schema.yaml"),
|
|
157
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/pending-note.schema.yaml", "contracts/pending-note.schema.yaml"),
|
|
158
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/topic-step-decision.schema.yaml", "contracts/topic-step-decision.schema.yaml"),
|
|
159
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/topic-run-ledger.schema.yaml", "contracts/topic-run-ledger.schema.yaml"),
|
|
160
|
+
loadYamlWithFallback(projectRoot, ".nimi/contracts/forbidden-shortcuts.catalog.yaml", "contracts/forbidden-shortcuts.catalog.yaml"),
|
|
161
|
+
loadYamlWithFallback(projectRoot, ".nimi/methodology/topic-lifecycle-report.yaml", "methodology/topic-lifecycle-report.yaml"),
|
|
162
|
+
loadYamlWithFallback(projectRoot, ".nimi/methodology/four-closure-policy.yaml", "methodology/four-closure-policy.yaml"),
|
|
163
|
+
loadYamlWithFallback(projectRoot, ".nimi/methodology/topic-validation-policy.yaml", "methodology/topic-validation-policy.yaml"),
|
|
164
|
+
loadYamlWithFallback(projectRoot, ".nimi/methodology/authority-convergence-policy.yaml", "methodology/authority-convergence-policy.yaml"),
|
|
161
165
|
]);
|
|
162
166
|
|
|
163
167
|
return {
|
package/cli/lib/handoff.mjs
CHANGED
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
HOST_ADAPTER_CONFIG_REF,
|
|
9
9
|
SKILL_RESULT_CONTRACT_REFS,
|
|
10
10
|
SPEC_GENERATION_AUDIT_CONTRACT_REF,
|
|
11
|
-
SPEC_GENERATION_AUDIT_REF,
|
|
12
11
|
SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF,
|
|
13
12
|
} from "../constants.mjs";
|
|
14
13
|
import {
|
|
@@ -79,14 +78,34 @@ function evaluateSkillReadiness(skillId, doctorResult) {
|
|
|
79
78
|
reason: "Bootstrap or handoff validation is failing; repair doctor errors before exporting handoff payloads",
|
|
80
79
|
};
|
|
81
80
|
}
|
|
82
|
-
|
|
81
|
+
const usesV2SurfaceModel = doctorResult.specGenerationInputs?.mode === "class_filtered";
|
|
82
|
+
if (usesV2SurfaceModel && (doctorResult.commandGating?.entries ?? []).length === 0) {
|
|
83
|
+
if (skillId === "spec_reconstruction") {
|
|
84
|
+
return {
|
|
85
|
+
ok: true,
|
|
86
|
+
reason: "Projects may delegate spec reconstruction to an external AI host when canonical tree work is needed",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (doctorResult.canonicalTree?.requiredFilesValid === true && doctorResult.specGenerationAudit?.ok === true) {
|
|
90
|
+
return {
|
|
91
|
+
ok: true,
|
|
92
|
+
reason: "Skill prerequisites are satisfied by the current project-local truth",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
83
95
|
return {
|
|
84
|
-
ok:
|
|
85
|
-
reason: "
|
|
96
|
+
ok: false,
|
|
97
|
+
reason: "This skill is not allowed in the current lifecycle state",
|
|
86
98
|
};
|
|
87
99
|
}
|
|
88
100
|
const rule = (doctorResult.commandGating?.entries ?? []).find((entry) => entry.command === "handoff" && entry.skill === skillId) ?? null;
|
|
89
|
-
|
|
101
|
+
const gatedReadiness = commandRuleAllowsCurrentState(rule, doctorResult);
|
|
102
|
+
if (!gatedReadiness.ok || skillId !== "spec_reconstruction") {
|
|
103
|
+
return gatedReadiness;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
ok: true,
|
|
107
|
+
reason: "Projects may delegate spec reconstruction to an external AI host when canonical tree work is needed",
|
|
108
|
+
};
|
|
90
109
|
}
|
|
91
110
|
function getSkillSpecificExpectations(
|
|
92
111
|
skillId,
|
|
@@ -108,8 +127,8 @@ function getSkillSpecificExpectations(
|
|
|
108
127
|
expectedArtifactKinds: [],
|
|
109
128
|
skillExpectedResults: [
|
|
110
129
|
"generate_canonical_tree_under_.nimi/spec",
|
|
111
|
-
"
|
|
112
|
-
"record_file_level_generation_audit_under_.nimi/
|
|
130
|
+
"establish_kernel_markdown_and_kernel_tables_before_thin_guides",
|
|
131
|
+
"record_file_level_generation_audit_under_.nimi/local/state/spec-generation/spec-generation-audit.yaml",
|
|
113
132
|
`satisfy_canonical_tree_completion_declared_in_${resultContractRef}`,
|
|
114
133
|
],
|
|
115
134
|
};
|
|
@@ -264,7 +283,7 @@ export async function buildHandoffPayload(projectRoot, skillId) {
|
|
|
264
283
|
acceptanceMode: specGenerationInputs.acceptanceMode ?? "canonical_tree_validity_without_blueprint",
|
|
265
284
|
generationOrder: specGenerationInputs.generationOrder ?? [],
|
|
266
285
|
inferenceRules: specGenerationInputs.inferenceRules ?? [],
|
|
267
|
-
auditRef:
|
|
286
|
+
auditRef: ".nimi/local/state/spec-generation/spec-generation-audit.yaml",
|
|
268
287
|
auditContractRef: SPEC_GENERATION_AUDIT_CONTRACT_REF,
|
|
269
288
|
requiredFileClasses: [
|
|
270
289
|
"INDEX.md",
|
|
@@ -272,7 +291,6 @@ export async function buildHandoffPayload(projectRoot, skillId) {
|
|
|
272
291
|
"domain kernel/tables/**",
|
|
273
292
|
],
|
|
274
293
|
optionalFileClasses: [
|
|
275
|
-
"domain kernel/generated/**",
|
|
276
294
|
"thin domain guides",
|
|
277
295
|
],
|
|
278
296
|
minimalRequiredOutputs: Array.isArray(specReconstructionDocument?.reconstruction?.target_tree_shape?.minimal_required_outputs)
|
|
@@ -586,8 +604,8 @@ export function formatHandoffPrompt(payload) {
|
|
|
586
604
|
"- 直接在 `.nimi/spec/**` 下构建 canonical tree;不要把 compact summary 当作主要输出。",
|
|
587
605
|
));
|
|
588
606
|
lines.push(localize(
|
|
589
|
-
"- Write `.nimi/
|
|
590
|
-
"-
|
|
607
|
+
"- Write `.nimi/local/state/spec-generation/spec-generation-audit.yaml` as local generation state. Every canonical file must record source refs, source basis, and unresolved gaps.",
|
|
608
|
+
"- 将 `.nimi/local/state/spec-generation/spec-generation-audit.yaml` 写作本地生成状态。每个 canonical 文件都必须记录 source refs、source basis 和未解决缺口。",
|
|
591
609
|
));
|
|
592
610
|
lines.push(localize(
|
|
593
611
|
"- When a benchmark blueprint root is declared, aim for semantic and structural parity with that benchmark rather than byte-for-byte duplication.",
|
|
@@ -26,6 +26,34 @@ import { parseYamlText } from "./yaml-helpers.mjs";
|
|
|
26
26
|
|
|
27
27
|
const ADMISSIONS_SPEC_REF = ".nimi/spec/high-risk-admissions.yaml";
|
|
28
28
|
|
|
29
|
+
async function resolveProjectContainedPath(projectRoot, inputPath, artifactLabel) {
|
|
30
|
+
const absolutePath = path.resolve(projectRoot, inputPath);
|
|
31
|
+
let resolvedProjectRoot;
|
|
32
|
+
let resolvedPath;
|
|
33
|
+
try {
|
|
34
|
+
resolvedProjectRoot = await realpath(projectRoot);
|
|
35
|
+
resolvedPath = await realpath(absolutePath);
|
|
36
|
+
} catch {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
path: absolutePath,
|
|
40
|
+
reason: `cannot read ${artifactLabel} at ${absolutePath}`,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const relative = path.relative(resolvedProjectRoot, resolvedPath);
|
|
44
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
45
|
+
return {
|
|
46
|
+
ok: false,
|
|
47
|
+
path: absolutePath,
|
|
48
|
+
reason: `${artifactLabel} must resolve inside the current project root`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
ok: true,
|
|
53
|
+
path: resolvedPath,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
29
57
|
function translateAdmissionReason(reason) {
|
|
30
58
|
const translations = new Map([
|
|
31
59
|
["imported decision payload must declare contractVersion nimicoding.high-risk-decision.v1", "导入的 decision payload 必须声明 contractVersion nimicoding.high-risk-decision.v1"],
|
|
@@ -45,15 +73,25 @@ function translateAdmissionReason(reason) {
|
|
|
45
73
|
}
|
|
46
74
|
|
|
47
75
|
async function loadImportedDecisionPayload(projectRoot, fromPath) {
|
|
48
|
-
const
|
|
49
|
-
|
|
76
|
+
const containedPath = await resolveProjectContainedPath(projectRoot, fromPath, "imported decision JSON");
|
|
77
|
+
if (!containedPath.ok) {
|
|
78
|
+
return {
|
|
79
|
+
ok: false,
|
|
80
|
+
error: `${localize(
|
|
81
|
+
`nimicoding admit-high-risk-decision refused: ${containedPath.reason}.`,
|
|
82
|
+
`nimicoding admit-high-risk-decision 已拒绝:${containedPath.reason}。`,
|
|
83
|
+
)}\n`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const rawText = await readTextIfFile(containedPath.path);
|
|
50
88
|
|
|
51
89
|
if (rawText === null) {
|
|
52
90
|
return {
|
|
53
91
|
ok: false,
|
|
54
92
|
error: `${localize(
|
|
55
|
-
`nimicoding admit-high-risk-decision refused: cannot read imported decision JSON at ${
|
|
56
|
-
`nimicoding admit-high-risk-decision 已拒绝:无法读取 ${
|
|
93
|
+
`nimicoding admit-high-risk-decision refused: cannot read imported decision JSON at ${containedPath.path}.`,
|
|
94
|
+
`nimicoding admit-high-risk-decision 已拒绝:无法读取 ${containedPath.path} 处的导入 decision JSON。`,
|
|
57
95
|
)}\n`,
|
|
58
96
|
};
|
|
59
97
|
}
|
|
@@ -65,8 +103,8 @@ async function loadImportedDecisionPayload(projectRoot, fromPath) {
|
|
|
65
103
|
return {
|
|
66
104
|
ok: false,
|
|
67
105
|
error: `${localize(
|
|
68
|
-
`nimicoding admit-high-risk-decision refused: imported decision JSON at ${
|
|
69
|
-
`nimicoding admit-high-risk-decision 已拒绝:${
|
|
106
|
+
`nimicoding admit-high-risk-decision refused: imported decision JSON at ${containedPath.path} is invalid JSON.`,
|
|
107
|
+
`nimicoding admit-high-risk-decision 已拒绝:${containedPath.path} 处的导入 decision JSON 不是合法 JSON。`,
|
|
70
108
|
)}\n`,
|
|
71
109
|
};
|
|
72
110
|
}
|
|
@@ -110,7 +148,7 @@ async function loadImportedDecisionPayload(projectRoot, fromPath) {
|
|
|
110
148
|
|
|
111
149
|
return {
|
|
112
150
|
ok: true,
|
|
113
|
-
path:
|
|
151
|
+
path: containedPath.path,
|
|
114
152
|
payload: parsed,
|
|
115
153
|
};
|
|
116
154
|
}
|
|
@@ -192,8 +230,15 @@ async function loadAdmissionsSpec(projectRoot, contract) {
|
|
|
192
230
|
}
|
|
193
231
|
|
|
194
232
|
async function loadPacketIdentity(projectRoot, packetRef) {
|
|
195
|
-
const
|
|
196
|
-
|
|
233
|
+
const containedPath = await resolveProjectContainedPath(projectRoot, packetRef, "attached packet_ref");
|
|
234
|
+
if (!containedPath.ok) {
|
|
235
|
+
return {
|
|
236
|
+
ok: false,
|
|
237
|
+
reason: containedPath.reason,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const packetValidation = await validateExecutionPacket(containedPath.path);
|
|
197
242
|
if (!packetValidation.ok) {
|
|
198
243
|
return {
|
|
199
244
|
ok: false,
|
|
@@ -202,7 +247,7 @@ async function loadPacketIdentity(projectRoot, packetRef) {
|
|
|
202
247
|
};
|
|
203
248
|
}
|
|
204
249
|
|
|
205
|
-
const text = await readTextIfFile(
|
|
250
|
+
const text = await readTextIfFile(containedPath.path);
|
|
206
251
|
const parsed = parseYamlText(text);
|
|
207
252
|
const packetId = String(parsed?.packet_id ?? "");
|
|
208
253
|
const topicId = String(parsed?.topic_id ?? "");
|
|
@@ -242,7 +287,11 @@ function evaluateAdmissionReadiness(doctorResult, admissionsSpec, packetIdentity
|
|
|
242
287
|
};
|
|
243
288
|
}
|
|
244
289
|
|
|
245
|
-
|
|
290
|
+
const v2Ready = doctorResult.specGenerationInputs?.mode === "class_filtered"
|
|
291
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
292
|
+
const legacyReady = doctorResult.lifecycleState?.treeState === "canonical_tree_ready"
|
|
293
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
294
|
+
if (!v2Ready && !legacyReady) {
|
|
246
295
|
return {
|
|
247
296
|
ok: false,
|
|
248
297
|
reason: "Canonical admission requires canonical_tree_ready with declared canonical files present",
|
|
@@ -150,8 +150,33 @@ function validateImportedReviewPayload(payload) {
|
|
|
150
150
|
return { ok: true };
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
function extractMarkdownSectionBody(text, heading) {
|
|
154
|
+
const lines = text.split(/\r?\n/);
|
|
155
|
+
let sectionLevel = null;
|
|
156
|
+
const body = [];
|
|
157
|
+
for (const line of lines) {
|
|
158
|
+
const headingMatch = line.match(/^(#{1,6})\s+(.+?)\s*#*\s*$/);
|
|
159
|
+
if (headingMatch) {
|
|
160
|
+
const level = headingMatch[1].length;
|
|
161
|
+
const title = headingMatch[2].trim();
|
|
162
|
+
if (sectionLevel !== null && level <= sectionLevel) {
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
if (title === heading) {
|
|
166
|
+
sectionLevel = level;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (sectionLevel !== null) {
|
|
171
|
+
body.push(line);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return sectionLevel === null ? "" : body.join("\n");
|
|
175
|
+
}
|
|
176
|
+
|
|
153
177
|
function extractAcceptanceDisposition(text) {
|
|
154
|
-
const
|
|
178
|
+
const dispositionSection = extractMarkdownSectionBody(text, "Current Phase Disposition");
|
|
179
|
+
const match = dispositionSection.match(/Disposition:\s*(\w+)/i);
|
|
155
180
|
return match ? match[1].toLowerCase() : null;
|
|
156
181
|
}
|
|
157
182
|
|
|
@@ -163,7 +188,11 @@ function evaluateDecisionReadiness(doctorResult, acceptanceReport) {
|
|
|
163
188
|
};
|
|
164
189
|
}
|
|
165
190
|
|
|
166
|
-
|
|
191
|
+
const v2Ready = doctorResult.specGenerationInputs?.mode === "class_filtered"
|
|
192
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
193
|
+
const legacyReady = doctorResult.lifecycleState?.treeState === "canonical_tree_ready"
|
|
194
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
195
|
+
if (!v2Ready && !legacyReady) {
|
|
167
196
|
return {
|
|
168
197
|
ok: false,
|
|
169
198
|
reason: "High-risk decision projection requires canonical_tree_ready with declared canonical files present",
|
|
@@ -149,7 +149,11 @@ function evaluateHighRiskIngestReadiness(doctorResult, validations) {
|
|
|
149
149
|
};
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
const v2Ready = doctorResult.specGenerationInputs?.mode === "class_filtered"
|
|
153
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
154
|
+
const legacyReady = doctorResult.lifecycleState?.treeState === "canonical_tree_ready"
|
|
155
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
156
|
+
if (!v2Ready && !legacyReady) {
|
|
153
157
|
return {
|
|
154
158
|
ok: false,
|
|
155
159
|
reason: "High-risk ingest requires canonical_tree_ready with declared canonical files present",
|
|
@@ -152,7 +152,11 @@ function evaluateHighRiskReviewReadiness(doctorResult) {
|
|
|
152
152
|
};
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
const v2Ready = doctorResult.specGenerationInputs?.mode === "class_filtered"
|
|
156
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
157
|
+
const legacyReady = doctorResult.lifecycleState?.treeState === "canonical_tree_ready"
|
|
158
|
+
&& doctorResult.canonicalTree?.requiredFilesValid === true;
|
|
159
|
+
if (!v2Ready && !legacyReady) {
|
|
156
160
|
return {
|
|
157
161
|
ok: false,
|
|
158
162
|
reason: "High-risk review projection requires canonical_tree_ready with declared canonical files present",
|