@nimiplatform/nimi-coding 0.1.0 → 0.2.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.
- package/README.md +19 -20
- 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 +114 -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 +5 -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
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { runSeedSync, SYNC_MODE, SYNC_RESULT_STATUS } from "../lib/sync.mjs";
|
|
2
|
+
import { localize } from "../lib/ui.mjs";
|
|
3
|
+
|
|
4
|
+
function parseSyncOptions(args) {
|
|
5
|
+
const options = {
|
|
6
|
+
mode: SYNC_MODE.DRY_RUN,
|
|
7
|
+
json: false,
|
|
8
|
+
};
|
|
9
|
+
let modeSet = false;
|
|
10
|
+
|
|
11
|
+
for (const arg of args) {
|
|
12
|
+
if (arg === "--apply") {
|
|
13
|
+
if (modeSet) {
|
|
14
|
+
return {
|
|
15
|
+
ok: false,
|
|
16
|
+
error: localize(
|
|
17
|
+
"nimicoding sync refused: --apply, --check, and --dry-run are mutually exclusive.\n",
|
|
18
|
+
"nimicoding sync 拒绝执行:--apply、--check、--dry-run 互斥。\n",
|
|
19
|
+
),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
options.mode = SYNC_MODE.APPLY;
|
|
23
|
+
modeSet = true;
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (arg === "--check") {
|
|
27
|
+
if (modeSet) {
|
|
28
|
+
return {
|
|
29
|
+
ok: false,
|
|
30
|
+
error: localize(
|
|
31
|
+
"nimicoding sync refused: --apply, --check, and --dry-run are mutually exclusive.\n",
|
|
32
|
+
"nimicoding sync 拒绝执行:--apply、--check、--dry-run 互斥。\n",
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
options.mode = SYNC_MODE.CHECK;
|
|
37
|
+
modeSet = true;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (arg === "--dry-run") {
|
|
41
|
+
if (modeSet) {
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
error: localize(
|
|
45
|
+
"nimicoding sync refused: --apply, --check, and --dry-run are mutually exclusive.\n",
|
|
46
|
+
"nimicoding sync 拒绝执行:--apply、--check、--dry-run 互斥。\n",
|
|
47
|
+
),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
options.mode = SYNC_MODE.DRY_RUN;
|
|
51
|
+
modeSet = true;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (arg === "--json") {
|
|
55
|
+
options.json = true;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: localize(
|
|
61
|
+
`nimicoding sync refused: unknown option ${arg}.\n`,
|
|
62
|
+
`nimicoding sync 拒绝执行:未知选项 ${arg}。\n`,
|
|
63
|
+
),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return { ok: true, options };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function formatHumanReport(result) {
|
|
71
|
+
const lines = [];
|
|
72
|
+
lines.push(localize(
|
|
73
|
+
`nimicoding sync (${result.mode})`,
|
|
74
|
+
`nimicoding sync (${result.mode})`,
|
|
75
|
+
));
|
|
76
|
+
lines.push("");
|
|
77
|
+
lines.push(localize("Summary:", "概览:"));
|
|
78
|
+
lines.push(` total: ${result.summary.total}`);
|
|
79
|
+
lines.push(` in_sync: ${result.summary.in_sync}`);
|
|
80
|
+
if (result.mode === SYNC_MODE.APPLY) {
|
|
81
|
+
lines.push(` created: ${result.summary.created}`);
|
|
82
|
+
lines.push(` updated: ${result.summary.updated}`);
|
|
83
|
+
} else {
|
|
84
|
+
lines.push(` would_create: ${result.summary.would_create}`);
|
|
85
|
+
lines.push(` would_update: ${result.summary.would_update}`);
|
|
86
|
+
}
|
|
87
|
+
lines.push(` drifted_preserved (host-owned seed): ${result.summary.drifted_preserved}`);
|
|
88
|
+
if (result.mode === SYNC_MODE.CHECK) {
|
|
89
|
+
lines.push(` missing_package_canonical: ${result.summary.missing_package_canonical}`);
|
|
90
|
+
lines.push(` missing_host_state_seed: ${result.summary.missing_host_state_seed}`);
|
|
91
|
+
lines.push(` drifted_package_canonical: ${result.summary.drifted_package_canonical}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const noteworthy = result.results.filter((entry) => entry.status !== SYNC_RESULT_STATUS.IN_SYNC);
|
|
95
|
+
if (noteworthy.length > 0) {
|
|
96
|
+
lines.push("");
|
|
97
|
+
lines.push(localize("Per-file status:", "逐文件状态:"));
|
|
98
|
+
for (const entry of noteworthy) {
|
|
99
|
+
lines.push(` [${entry.status}] (${entry.ownership}) ${entry.outputRelativePath}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (result.mode === SYNC_MODE.CHECK && !result.ok) {
|
|
104
|
+
lines.push("");
|
|
105
|
+
lines.push(localize(
|
|
106
|
+
"FAIL: package_canonical drift or missing seed detected; run `nimicoding sync --apply` to refresh.",
|
|
107
|
+
"FAIL:检测到 package_canonical drift 或缺失 seed;执行 `nimicoding sync --apply` 以刷新。",
|
|
108
|
+
));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return `${lines.join("\n")}\n`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function runSync(args) {
|
|
115
|
+
const parsed = parseSyncOptions(args);
|
|
116
|
+
if (!parsed.ok) {
|
|
117
|
+
process.stderr.write(parsed.error);
|
|
118
|
+
return 2;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const result = await runSeedSync(process.cwd(), parsed.options.mode);
|
|
122
|
+
|
|
123
|
+
if (parsed.options.json) {
|
|
124
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
125
|
+
} else {
|
|
126
|
+
process.stdout.write(formatHumanReport(result));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result.ok ? 0 : 1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export { parseSyncOptions };
|
|
@@ -62,16 +62,16 @@ export function formatTopicStatus(report) {
|
|
|
62
62
|
...Object.entries(report.featureFlags).map(([key, value]) => `- ${key}: ${value ? "true" : "false"}`),
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
|
-
if (Array.isArray(report.
|
|
65
|
+
if (Array.isArray(report.observedWaves) && report.observedWaves.length > 0) {
|
|
66
66
|
lines.push(
|
|
67
67
|
"",
|
|
68
68
|
styleLabel(localize("Observed Waves", "Observed Waves")),
|
|
69
|
-
...report.
|
|
69
|
+
...report.observedWaves.slice(0, 8).map((entry) => (
|
|
70
70
|
`- ${entry.wave_id}: ${entry.observed_lineage} packets=${entry.packets} results=${entry.results} closeouts=${entry.closeouts} exec_packs=${entry.exec_packs}`
|
|
71
71
|
)),
|
|
72
72
|
);
|
|
73
|
-
if (report.
|
|
74
|
-
lines.push(styleMuted(`- ... ${report.
|
|
73
|
+
if (report.observedWaves.length > 8) {
|
|
74
|
+
lines.push(styleMuted(`- ... ${report.observedWaves.length - 8} more wave observations`));
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
if (report.warnings.length > 0) {
|
|
@@ -119,16 +119,16 @@ export function formatTopicValidate(report) {
|
|
|
119
119
|
...Object.entries(report.featureFlags).map(([key, value]) => `- ${key}: ${value ? "true" : "false"}`),
|
|
120
120
|
);
|
|
121
121
|
}
|
|
122
|
-
if (Array.isArray(report.
|
|
122
|
+
if (Array.isArray(report.observedWaves) && report.observedWaves.length > 0) {
|
|
123
123
|
lines.push(
|
|
124
124
|
"",
|
|
125
125
|
styleLabel(localize("Observed Waves", "Observed Waves")),
|
|
126
|
-
...report.
|
|
126
|
+
...report.observedWaves.slice(0, 8).map((entry) => (
|
|
127
127
|
`- ${entry.wave_id}: ${entry.observed_lineage} packets=${entry.packets} results=${entry.results} closeouts=${entry.closeouts} exec_packs=${entry.exec_packs}`
|
|
128
128
|
)),
|
|
129
129
|
);
|
|
130
|
-
if (report.
|
|
131
|
-
lines.push(styleMuted(`- ... ${report.
|
|
130
|
+
if (report.observedWaves.length > 8) {
|
|
131
|
+
lines.push(styleMuted(`- ... ${report.observedWaves.length - 8} more wave observations`));
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
if (report.warnings.length > 0) {
|
|
@@ -3,7 +3,10 @@ import { loadGovernanceConfig, requireProfile } from "../lib/internal/governance
|
|
|
3
3
|
import { evaluateAiContextBudget, formatBytes } from "../lib/internal/governance/ai/ai-context-budget-core.mjs";
|
|
4
4
|
import { evaluateAiStructureBudget } from "../lib/internal/governance/ai/ai-structure-budget-core.mjs";
|
|
5
5
|
import { evaluateHighRiskDocMetadata } from "../lib/internal/governance/ai/check-high-risk-doc-metadata-core.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
evaluateAgentsFreshnessCheck,
|
|
8
|
+
runAgentsFreshnessCheck,
|
|
9
|
+
} from "../lib/internal/governance/ai/check-agents-freshness.mjs";
|
|
7
10
|
|
|
8
11
|
const SCOPES = new Set([
|
|
9
12
|
"agents-freshness",
|
|
@@ -16,6 +19,7 @@ function parseOptions(args) {
|
|
|
16
19
|
const options = {
|
|
17
20
|
profile: null,
|
|
18
21
|
scope: "all",
|
|
22
|
+
json: false,
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -41,6 +45,11 @@ function parseOptions(args) {
|
|
|
41
45
|
continue;
|
|
42
46
|
}
|
|
43
47
|
|
|
48
|
+
if (arg === "--json") {
|
|
49
|
+
options.json = true;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
44
53
|
return {
|
|
45
54
|
ok: false,
|
|
46
55
|
error: `nimicoding validate-ai-governance refused: unknown option ${arg}.\n`,
|
|
@@ -57,6 +66,63 @@ function parseOptions(args) {
|
|
|
57
66
|
return { ok: true, options };
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
function writeJson(payload) {
|
|
70
|
+
process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function buildContextBudgetReport(governanceConfig) {
|
|
74
|
+
const report = evaluateAiContextBudget({
|
|
75
|
+
cwd: process.cwd(),
|
|
76
|
+
config: governanceConfig.aiGovernance.contextBudget,
|
|
77
|
+
configPathLabel: ".nimi/config/governance.yaml#ai_governance.context_budget",
|
|
78
|
+
});
|
|
79
|
+
const exitCode = report.invalidWaivers.length > 0 || report.expiredWaivers.length > 0 || report.errors.length > 0
|
|
80
|
+
? 1
|
|
81
|
+
: 0;
|
|
82
|
+
return { exitCode, report };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function buildStructureBudgetReport(governanceConfig) {
|
|
86
|
+
const report = evaluateAiStructureBudget({
|
|
87
|
+
cwd: process.cwd(),
|
|
88
|
+
config: governanceConfig.aiGovernance.structureBudget,
|
|
89
|
+
configPathLabel: ".nimi/config/governance.yaml#ai_governance.structure_budget",
|
|
90
|
+
});
|
|
91
|
+
const exitCode = report.errors.length > 0 || report.expiredWaivers.length > 0 ? 1 : 0;
|
|
92
|
+
return { exitCode, report };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function buildHighRiskDocMetadataReport(governanceConfig) {
|
|
96
|
+
const config = governanceConfig.aiGovernance.highRiskDocMetadata;
|
|
97
|
+
const report = evaluateHighRiskDocMetadata({
|
|
98
|
+
repoRoot: process.cwd(),
|
|
99
|
+
docRoots: Array.isArray(config.doc_roots) ? config.doc_roots : [".local"],
|
|
100
|
+
exemptPaths: Array.isArray(config.exempt_paths) ? config.exempt_paths : [],
|
|
101
|
+
namePatterns: Array.isArray(config.name_patterns) ? config.name_patterns : [],
|
|
102
|
+
requiredMetadataKeys: Array.isArray(config.required_metadata_keys)
|
|
103
|
+
? config.required_metadata_keys
|
|
104
|
+
: [],
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
exitCode: report.failures.length > 0 ? 1 : 0,
|
|
108
|
+
report: {
|
|
109
|
+
...report,
|
|
110
|
+
exemptPaths: [...report.exemptPaths],
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildAgentsFreshnessReport(governanceConfig) {
|
|
116
|
+
const report = evaluateAgentsFreshnessCheck({
|
|
117
|
+
projectRoot: process.cwd(),
|
|
118
|
+
config: governanceConfig.aiGovernance.agentsFreshness,
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
exitCode: report.failures.length > 0 ? 1 : 0,
|
|
122
|
+
report,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
60
126
|
function formatStructureRow(row) {
|
|
61
127
|
if (row.check === "depth") {
|
|
62
128
|
return `${row.file} [rule=${row.ruleId}] depth=${row.depth} base=${row.depthBase} subject=${row.depthSubject} (threshold warn>=${row.warningDepth} error>=${row.errorDepth})`;
|
|
@@ -64,42 +130,37 @@ function formatStructureRow(row) {
|
|
|
64
130
|
return `${row.file} [rule=${row.ruleId}] basename=${row.basename} (forwarding shell outside allowed basename set)`;
|
|
65
131
|
}
|
|
66
132
|
|
|
133
|
+
function formatContextBudgetRow(row, thresholdPrefix) {
|
|
134
|
+
return `${row.file} [${row.profile}] lines=${row.lines} bytes=${formatBytes(row.bytes)} max-line=${formatBytes(row.maxLineBytes)} avg-line=${formatBytes(Math.round(row.averageLineBytes))} `
|
|
135
|
+
+ `(${thresholdPrefix} lines>=${row[`${thresholdPrefix}Lines`] ?? "-"} bytes>=${row[`${thresholdPrefix}Bytes`] ?? "-"} max-line>=${row[`${thresholdPrefix}MaxLineBytes`] ?? "-"} avg-line>=${row[`${thresholdPrefix}AverageLineBytes`] ?? "-"})`;
|
|
136
|
+
}
|
|
137
|
+
|
|
67
138
|
async function runContextBudget(governanceConfig) {
|
|
68
|
-
const report =
|
|
69
|
-
cwd: process.cwd(),
|
|
70
|
-
config: governanceConfig.aiGovernance.contextBudget,
|
|
71
|
-
configPathLabel: ".nimi/config/governance.yaml#ai_governance.context_budget",
|
|
72
|
-
});
|
|
139
|
+
const { exitCode, report } = buildContextBudgetReport(governanceConfig);
|
|
73
140
|
|
|
74
141
|
process.stdout.write(`ai-context-budget: config=${report.configPath}\n`);
|
|
75
142
|
process.stdout.write(`ai-context-budget: tracked=${report.totalTrackedFiles}, analyzed=${report.analyzedFiles}\n`);
|
|
76
143
|
|
|
77
144
|
for (const row of report.warnings) {
|
|
78
|
-
process.stderr.write(
|
|
79
|
-
`WARN: ${row.file} [${row.profile}] lines=${row.lines} bytes=${formatBytes(row.bytes)} (threshold warn lines>=${row.warningLines ?? "-"} bytes>=${row.warningBytes ?? "-"})\n`,
|
|
80
|
-
);
|
|
145
|
+
process.stderr.write(`WARN: ${formatContextBudgetRow(row, "warning")}\n`);
|
|
81
146
|
}
|
|
82
147
|
for (const row of report.waivedErrors) {
|
|
83
148
|
const until = row.waiver?.until ? row.waiver.until.toISOString().slice(0, 10) : "n/a";
|
|
84
149
|
const reason = row.waiver?.reason || "no reason";
|
|
85
|
-
process.stderr.write(
|
|
86
|
-
`WARN: WAIVED error for ${row.file} [${row.profile}] lines=${row.lines} bytes=${formatBytes(row.bytes)} until=${until} reason=${reason}\n`,
|
|
87
|
-
);
|
|
150
|
+
process.stderr.write(`WARN: WAIVED error for ${formatContextBudgetRow(row, "error")} until=${until} reason=${reason}\n`);
|
|
88
151
|
}
|
|
89
152
|
for (const row of report.expiredWaivers) {
|
|
90
|
-
process.stderr.write(`ERROR: waiver expired for ${
|
|
153
|
+
process.stderr.write(`ERROR: waiver expired for ${formatContextBudgetRow(row, "error")}\n`);
|
|
91
154
|
}
|
|
92
155
|
for (const row of report.invalidWaivers) {
|
|
93
156
|
process.stderr.write(`ERROR: invalid waiver for ${row.file}: ${row.detail}\n`);
|
|
94
157
|
}
|
|
95
158
|
for (const row of report.errors) {
|
|
96
|
-
process.stderr.write(
|
|
97
|
-
`ERROR: ${row.file} [${row.profile}] lines=${row.lines} bytes=${formatBytes(row.bytes)} (threshold error lines>=${row.errorLines ?? "-"} bytes>=${row.errorBytes ?? "-"})\n`,
|
|
98
|
-
);
|
|
159
|
+
process.stderr.write(`ERROR: ${formatContextBudgetRow(row, "error")}\n`);
|
|
99
160
|
}
|
|
100
161
|
|
|
101
|
-
if (
|
|
102
|
-
return
|
|
162
|
+
if (exitCode !== 0) {
|
|
163
|
+
return exitCode;
|
|
103
164
|
}
|
|
104
165
|
|
|
105
166
|
process.stdout.write("ai-context-budget: OK\n");
|
|
@@ -107,11 +168,7 @@ async function runContextBudget(governanceConfig) {
|
|
|
107
168
|
}
|
|
108
169
|
|
|
109
170
|
async function runStructureBudget(governanceConfig) {
|
|
110
|
-
const report =
|
|
111
|
-
cwd: process.cwd(),
|
|
112
|
-
config: governanceConfig.aiGovernance.structureBudget,
|
|
113
|
-
configPathLabel: ".nimi/config/governance.yaml#ai_governance.structure_budget",
|
|
114
|
-
});
|
|
171
|
+
const { exitCode, report } = buildStructureBudgetReport(governanceConfig);
|
|
115
172
|
|
|
116
173
|
process.stdout.write(`ai-structure-budget: config=${report.configPath}\n`);
|
|
117
174
|
process.stdout.write(`ai-structure-budget: tracked=${report.totalTrackedFiles}, analyzed=${report.analyzedFiles}\n`);
|
|
@@ -129,8 +186,8 @@ async function runStructureBudget(governanceConfig) {
|
|
|
129
186
|
for (const row of report.errors) {
|
|
130
187
|
process.stderr.write(`ERROR: ${formatStructureRow(row)}\n`);
|
|
131
188
|
}
|
|
132
|
-
if (
|
|
133
|
-
return
|
|
189
|
+
if (exitCode !== 0) {
|
|
190
|
+
return exitCode;
|
|
134
191
|
}
|
|
135
192
|
|
|
136
193
|
process.stdout.write("ai-structure-budget: OK\n");
|
|
@@ -138,51 +195,90 @@ async function runStructureBudget(governanceConfig) {
|
|
|
138
195
|
}
|
|
139
196
|
|
|
140
197
|
async function runHighRiskDocMetadata(governanceConfig) {
|
|
141
|
-
const
|
|
142
|
-
const report = evaluateHighRiskDocMetadata({
|
|
143
|
-
repoRoot: process.cwd(),
|
|
144
|
-
docRoots: Array.isArray(config.doc_roots) ? config.doc_roots : [".local"],
|
|
145
|
-
exemptPaths: Array.isArray(config.exempt_paths) ? config.exempt_paths : [],
|
|
146
|
-
namePatterns: Array.isArray(config.name_patterns) ? config.name_patterns : [],
|
|
147
|
-
requiredMetadataKeys: Array.isArray(config.required_metadata_keys)
|
|
148
|
-
? config.required_metadata_keys
|
|
149
|
-
: [],
|
|
150
|
-
});
|
|
198
|
+
const { exitCode, report } = buildHighRiskDocMetadataReport(governanceConfig);
|
|
151
199
|
|
|
152
|
-
if (
|
|
200
|
+
if (exitCode !== 0) {
|
|
153
201
|
process.stderr.write("high-risk doc metadata check failed:\n");
|
|
154
202
|
for (const failure of report.failures) {
|
|
155
203
|
process.stderr.write(`- ${failure}\n`);
|
|
156
204
|
}
|
|
157
|
-
return
|
|
205
|
+
return exitCode;
|
|
158
206
|
}
|
|
159
207
|
|
|
160
208
|
process.stdout.write(`high-risk doc metadata check passed (${report.scanned.length} file(s) scanned)\n`);
|
|
161
209
|
return 0;
|
|
162
210
|
}
|
|
163
211
|
|
|
212
|
+
function runJsonScope(governanceConfig, scope) {
|
|
213
|
+
if (scope === "agents-freshness") {
|
|
214
|
+
return buildAgentsFreshnessReport(governanceConfig);
|
|
215
|
+
}
|
|
216
|
+
if (scope === "context-budget") {
|
|
217
|
+
return buildContextBudgetReport(governanceConfig);
|
|
218
|
+
}
|
|
219
|
+
if (scope === "structure-budget") {
|
|
220
|
+
return buildStructureBudgetReport(governanceConfig);
|
|
221
|
+
}
|
|
222
|
+
if (scope === "high-risk-doc-metadata") {
|
|
223
|
+
return buildHighRiskDocMetadataReport(governanceConfig);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
exitCode: 2,
|
|
227
|
+
report: { error: `unsupported scope: ${scope}` },
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
164
231
|
export async function runValidateAiGovernance(args) {
|
|
232
|
+
const wantsJson = args.includes("--json");
|
|
165
233
|
const parsed = parseOptions(args);
|
|
166
234
|
if (!parsed.ok) {
|
|
167
|
-
|
|
235
|
+
if (wantsJson) {
|
|
236
|
+
writeJson({
|
|
237
|
+
ok: false,
|
|
238
|
+
command: "validate-ai-governance",
|
|
239
|
+
error: parsed.error.trim(),
|
|
240
|
+
});
|
|
241
|
+
} else {
|
|
242
|
+
process.stderr.write(localize(parsed.error, parsed.error));
|
|
243
|
+
}
|
|
168
244
|
return 2;
|
|
169
245
|
}
|
|
170
246
|
|
|
171
247
|
const governance = await loadGovernanceConfig(process.cwd());
|
|
172
248
|
if (!governance.ok) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
249
|
+
const error = `nimicoding validate-ai-governance refused: ${governance.reason} at ${governance.path}.`;
|
|
250
|
+
if (parsed.options.json) {
|
|
251
|
+
writeJson({
|
|
252
|
+
ok: false,
|
|
253
|
+
command: "validate-ai-governance",
|
|
254
|
+
error,
|
|
255
|
+
governancePath: governance.path,
|
|
256
|
+
});
|
|
257
|
+
} else {
|
|
258
|
+
process.stderr.write(localize(
|
|
259
|
+
`${error}\n`,
|
|
260
|
+
`nimicoding validate-ai-governance 已拒绝:${governance.path} 的治理配置不可用。\n`,
|
|
261
|
+
));
|
|
262
|
+
}
|
|
177
263
|
return 2;
|
|
178
264
|
}
|
|
179
265
|
|
|
180
266
|
const profileCheck = requireProfile(governance.config, parsed.options.profile);
|
|
181
267
|
if (!profileCheck.ok) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
268
|
+
const error = `nimicoding validate-ai-governance refused: ${profileCheck.error}.`;
|
|
269
|
+
if (parsed.options.json) {
|
|
270
|
+
writeJson({
|
|
271
|
+
ok: false,
|
|
272
|
+
command: "validate-ai-governance",
|
|
273
|
+
error,
|
|
274
|
+
profile: profileCheck.profile,
|
|
275
|
+
});
|
|
276
|
+
} else {
|
|
277
|
+
process.stderr.write(localize(
|
|
278
|
+
`${error}\n`,
|
|
279
|
+
`nimicoding validate-ai-governance 已拒绝:${profileCheck.error}。\n`,
|
|
280
|
+
));
|
|
281
|
+
}
|
|
186
282
|
return 2;
|
|
187
283
|
}
|
|
188
284
|
|
|
@@ -190,6 +286,31 @@ export async function runValidateAiGovernance(args) {
|
|
|
190
286
|
? ["agents-freshness", "context-budget", "structure-budget", "high-risk-doc-metadata"]
|
|
191
287
|
: [parsed.options.scope];
|
|
192
288
|
|
|
289
|
+
if (parsed.options.json) {
|
|
290
|
+
const results = [];
|
|
291
|
+
let exitCode = 0;
|
|
292
|
+
for (const scope of scopes) {
|
|
293
|
+
const result = runJsonScope(governance.config, scope);
|
|
294
|
+
if (exitCode === 0 && result.exitCode !== 0) {
|
|
295
|
+
exitCode = result.exitCode;
|
|
296
|
+
}
|
|
297
|
+
results.push({
|
|
298
|
+
scope,
|
|
299
|
+
ok: result.exitCode === 0,
|
|
300
|
+
exitCode: result.exitCode,
|
|
301
|
+
report: result.report,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
writeJson({
|
|
305
|
+
ok: exitCode === 0,
|
|
306
|
+
command: "validate-ai-governance",
|
|
307
|
+
profile: profileCheck.profile,
|
|
308
|
+
scope: parsed.options.scope,
|
|
309
|
+
scopes: results,
|
|
310
|
+
});
|
|
311
|
+
return exitCode;
|
|
312
|
+
}
|
|
313
|
+
|
|
193
314
|
for (const scope of scopes) {
|
|
194
315
|
let exitCode = 0;
|
|
195
316
|
if (scope === "agents-freshness") {
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
3
|
import { validateSpecAudit, buildValidatorCliReport } from "../lib/validators.mjs";
|
|
4
|
+
import { loadSpecGenerationInputsConfig } from "../lib/contracts.mjs";
|
|
4
5
|
import { localize } from "../lib/ui.mjs";
|
|
5
6
|
|
|
6
7
|
export async function runValidateSpecAudit(args) {
|
|
7
8
|
const normalized = args[0] === "--" ? args.slice(1) : args;
|
|
8
|
-
|
|
9
|
+
const generationInputs = await loadSpecGenerationInputsConfig(process.cwd());
|
|
10
|
+
let targetPath = generationInputs.ok && generationInputs.mode === "class_filtered"
|
|
11
|
+
? ".nimi/local/state/spec-generation/spec-generation-audit.yaml"
|
|
12
|
+
: ".nimi/spec/_meta/spec-generation-audit.yaml";
|
|
9
13
|
|
|
10
14
|
if (normalized.length > 1) {
|
|
11
15
|
process.stderr.write(localize(
|
package/cli/constants.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const VERSION = "0.
|
|
1
|
+
export const VERSION = "0.2.0";
|
|
2
2
|
export const PACKAGE_NAME = "@nimiplatform/nimi-coding";
|
|
3
3
|
export const BOOTSTRAP_CONTRACT_ID = "nimicoding.bootstrap";
|
|
4
4
|
export const BOOTSTRAP_CONTRACT_VERSION = 1;
|
|
@@ -18,6 +18,8 @@ export const STANDALONE_COMPLETED_SURFACES = [
|
|
|
18
18
|
"bootstrap",
|
|
19
19
|
"doctor",
|
|
20
20
|
"handoff",
|
|
21
|
+
"sweep_audit",
|
|
22
|
+
"sweep_design",
|
|
21
23
|
"validators",
|
|
22
24
|
"topic_lifecycle_report_methodology",
|
|
23
25
|
"closeout",
|
|
@@ -51,6 +53,7 @@ export const CLAUDE_END = "<!-- nimicoding:managed:claude:end -->";
|
|
|
51
53
|
export const SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF = ".nimi/contracts/spec-reconstruction-result.yaml";
|
|
52
54
|
export const DOC_SPEC_AUDIT_RESULT_CONTRACT_REF = ".nimi/contracts/doc-spec-audit-result.yaml";
|
|
53
55
|
export const AUDIT_SWEEP_RESULT_CONTRACT_REF = ".nimi/contracts/audit-sweep-result.yaml";
|
|
56
|
+
export const SWEEP_DESIGN_RESULT_CONTRACT_REF = ".nimi/contracts/sweep-design-result.yaml";
|
|
54
57
|
export const AUDIT_PLAN_SCHEMA_REF = ".nimi/contracts/audit-plan.schema.yaml";
|
|
55
58
|
export const AUDIT_CHUNK_SCHEMA_REF = ".nimi/contracts/audit-chunk.schema.yaml";
|
|
56
59
|
export const AUDIT_FINDING_SCHEMA_REF = ".nimi/contracts/audit-finding.schema.yaml";
|
|
@@ -260,7 +263,7 @@ export const DOC_SPEC_AUDIT_DEFAULT_COMPARED_PATHS = [
|
|
|
260
263
|
];
|
|
261
264
|
|
|
262
265
|
export const SPEC_TREE_MODEL_REF = ".nimi/spec/_meta/spec-tree-model.yaml";
|
|
263
|
-
export const BLUEPRINT_REFERENCE_REF = ".nimi/spec/
|
|
266
|
+
export const BLUEPRINT_REFERENCE_REF = ".nimi/local/state/spec-generation/blueprint-reference.yaml";
|
|
264
267
|
export const COMMAND_GATING_MATRIX_REF = ".nimi/spec/_meta/command-gating-matrix.yaml";
|
|
265
268
|
export const GENERATE_DRIFT_MIGRATION_CHECKLIST_REF = ".nimi/spec/_meta/generate-drift-migration-checklist.yaml";
|
|
266
269
|
export const GOVERNANCE_ROUTING_CUTOVER_CHECKLIST_REF = ".nimi/spec/_meta/governance-routing-cutover-checklist.yaml";
|
|
@@ -277,53 +280,6 @@ export const SKILL_RESULT_CONTRACT_REFS = {
|
|
|
277
280
|
high_risk_execution: HIGH_RISK_EXECUTION_RESULT_CONTRACT_REF,
|
|
278
281
|
};
|
|
279
282
|
|
|
280
|
-
export const REQUIRED_BOOTSTRAP_FILES = [
|
|
281
|
-
".nimi/methodology/core.yaml",
|
|
282
|
-
".nimi/methodology/spec-reconstruction.yaml",
|
|
283
|
-
".nimi/methodology/skill-runtime.yaml",
|
|
284
|
-
".nimi/methodology/skill-installer-result.yaml",
|
|
285
|
-
".nimi/methodology/skill-installer-summary-projection.yaml",
|
|
286
|
-
".nimi/methodology/skill-exchange-projection.yaml",
|
|
287
|
-
".nimi/methodology/skill-handoff.yaml",
|
|
288
|
-
SPEC_TREE_MODEL_REF,
|
|
289
|
-
COMMAND_GATING_MATRIX_REF,
|
|
290
|
-
GENERATE_DRIFT_MIGRATION_CHECKLIST_REF,
|
|
291
|
-
GOVERNANCE_ROUTING_CUTOVER_CHECKLIST_REF,
|
|
292
|
-
PHASE2_IMPACTED_SURFACE_MATRIX_REF,
|
|
293
|
-
".nimi/spec/product-scope.yaml",
|
|
294
|
-
".nimi/spec/bootstrap-state.yaml",
|
|
295
|
-
".nimi/config/bootstrap.yaml",
|
|
296
|
-
".nimi/config/skills.yaml",
|
|
297
|
-
".nimi/config/skill-manifest.yaml",
|
|
298
|
-
SPEC_GENERATION_INPUTS_REF,
|
|
299
|
-
".nimi/config/host-profile.yaml",
|
|
300
|
-
HOST_ADAPTER_CONFIG_REF,
|
|
301
|
-
EXTERNAL_EXECUTION_ARTIFACTS_CONFIG_REF,
|
|
302
|
-
AUDIT_EXECUTION_ARTIFACTS_CONFIG_REF,
|
|
303
|
-
".nimi/config/skill-installer.yaml",
|
|
304
|
-
".nimi/config/installer-evidence.yaml",
|
|
305
|
-
SPEC_RECONSTRUCTION_RESULT_CONTRACT_REF,
|
|
306
|
-
DOC_SPEC_AUDIT_RESULT_CONTRACT_REF,
|
|
307
|
-
AUDIT_SWEEP_RESULT_CONTRACT_REF,
|
|
308
|
-
AUDIT_PLAN_SCHEMA_REF,
|
|
309
|
-
AUDIT_CHUNK_SCHEMA_REF,
|
|
310
|
-
AUDIT_FINDING_SCHEMA_REF,
|
|
311
|
-
AUDIT_LEDGER_SCHEMA_REF,
|
|
312
|
-
AUDIT_REMEDIATION_MAP_SCHEMA_REF,
|
|
313
|
-
AUDIT_RERUN_SCHEMA_REF,
|
|
314
|
-
AUDIT_CLOSEOUT_SCHEMA_REF,
|
|
315
|
-
HIGH_RISK_EXECUTION_RESULT_CONTRACT_REF,
|
|
316
|
-
HIGH_RISK_ADMISSION_CONTRACT_REF,
|
|
317
|
-
SPEC_GENERATION_INPUTS_CONTRACT_REF,
|
|
318
|
-
SPEC_GENERATION_AUDIT_CONTRACT_REF,
|
|
319
|
-
EXTERNAL_HOST_COMPATIBILITY_CONTRACT_REF,
|
|
320
|
-
EXECUTION_PACKET_SCHEMA_REF,
|
|
321
|
-
ORCHESTRATION_STATE_SCHEMA_REF,
|
|
322
|
-
PROMPT_SCHEMA_REF,
|
|
323
|
-
WORKER_OUTPUT_SCHEMA_REF,
|
|
324
|
-
ACCEPTANCE_SCHEMA_REF,
|
|
325
|
-
];
|
|
326
|
-
|
|
327
283
|
export const REQUIRED_LOCAL_DIRS = [".nimi/local", ".nimi/cache"];
|
|
328
284
|
|
|
329
285
|
export const REQUIRED_BOOTSTRAP_DIRS = [
|