@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
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import {
|
|
2
|
+
runAuditorPrompt,
|
|
3
|
+
runFinalize,
|
|
4
|
+
runFixTopic,
|
|
5
|
+
runIntake,
|
|
6
|
+
runLedgerValidate,
|
|
7
|
+
runPacketBuild,
|
|
8
|
+
runPacketBuildBatch,
|
|
9
|
+
runResultIngest,
|
|
10
|
+
runWavePlan,
|
|
11
|
+
} from "../lib/sweep-design.mjs";
|
|
12
|
+
import { localize } from "../lib/ui.mjs";
|
|
13
|
+
|
|
14
|
+
function readRequiredValue(args, index, optionName, commandName) {
|
|
15
|
+
const next = args[index + 1];
|
|
16
|
+
if (!next || next.startsWith("--")) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
error: `${localize(
|
|
20
|
+
`nimicoding sweep design ${commandName} refused: ${optionName} requires a value.`,
|
|
21
|
+
`nimicoding sweep design ${commandName} 已拒绝:${optionName} 需要一个值。`,
|
|
22
|
+
)}\n`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return { ok: true, value: next };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function unknownOption(commandName, arg) {
|
|
29
|
+
return {
|
|
30
|
+
ok: false,
|
|
31
|
+
error: `${localize(
|
|
32
|
+
`nimicoding sweep design ${commandName} refused: unknown option ${arg}.`,
|
|
33
|
+
`nimicoding sweep design ${commandName} 已拒绝:未知选项 ${arg}。`,
|
|
34
|
+
)}\n`,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseOptions(args, commandName, spec) {
|
|
39
|
+
const options = Object.fromEntries(Object.entries(spec).map(([name, config]) => [name, config.default ?? null]));
|
|
40
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
41
|
+
const arg = args[index];
|
|
42
|
+
if (arg === "--json") {
|
|
43
|
+
options.json = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const entry = Object.entries(spec).find(([, config]) => config.flag === arg);
|
|
47
|
+
if (!entry) {
|
|
48
|
+
return unknownOption(commandName, arg);
|
|
49
|
+
}
|
|
50
|
+
const [name] = entry;
|
|
51
|
+
if (entry[1].type === "boolean") {
|
|
52
|
+
options[name] = true;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const value = readRequiredValue(args, index, arg, commandName);
|
|
56
|
+
if (!value.ok) return value;
|
|
57
|
+
options[name] = value.value;
|
|
58
|
+
index += 1;
|
|
59
|
+
}
|
|
60
|
+
const missing = Object.entries(spec)
|
|
61
|
+
.filter(([, config]) => config.required)
|
|
62
|
+
.filter(([name]) => !options[name])
|
|
63
|
+
.map(([, config]) => config.flag);
|
|
64
|
+
if (missing.length > 0) {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
error: `${localize(
|
|
68
|
+
`nimicoding sweep design ${commandName} refused: missing required options: ${missing.join(", ")}.`,
|
|
69
|
+
`nimicoding sweep design ${commandName} 已拒绝:缺少必填选项:${missing.join(", ")}。`,
|
|
70
|
+
)}\n`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { ok: true, options };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function parseSweepDesignOptions(args) {
|
|
77
|
+
const [phase] = args;
|
|
78
|
+
if (phase === "intake") {
|
|
79
|
+
return {
|
|
80
|
+
ok: true,
|
|
81
|
+
action: "intake",
|
|
82
|
+
parsed: parseOptions(args.slice(1), "intake", {
|
|
83
|
+
sweepId: { flag: "--sweep-id", required: true },
|
|
84
|
+
runId: { flag: "--run-id" },
|
|
85
|
+
verifiedAt: { flag: "--verified-at" },
|
|
86
|
+
json: { default: false },
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (phase === "packet-build") {
|
|
91
|
+
return {
|
|
92
|
+
ok: true,
|
|
93
|
+
action: "packet-build",
|
|
94
|
+
parsed: parseOptions(args.slice(1), "packet-build", {
|
|
95
|
+
runId: { flag: "--run-id", required: true },
|
|
96
|
+
packetId: { flag: "--packet-id", required: true },
|
|
97
|
+
findingId: { flag: "--finding-id" },
|
|
98
|
+
findingIds: { flag: "--finding-ids" },
|
|
99
|
+
explicitQuestion: { flag: "--explicit-question" },
|
|
100
|
+
explicitQuestions: { flag: "--explicit-questions" },
|
|
101
|
+
priorDesignStateRefs: { flag: "--prior-design-state-refs" },
|
|
102
|
+
priorDesignStateMarker: { flag: "--prior-design-state-marker" },
|
|
103
|
+
currentClusterRefs: { flag: "--current-cluster-refs" },
|
|
104
|
+
currentWaveRefs: { flag: "--current-wave-refs" },
|
|
105
|
+
authorityOnly: { flag: "--authority-only", type: "boolean", default: false },
|
|
106
|
+
verifiedAt: { flag: "--verified-at" },
|
|
107
|
+
json: { default: false },
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (phase === "packet-build-batch") {
|
|
112
|
+
return {
|
|
113
|
+
ok: true,
|
|
114
|
+
action: "packet-build-batch",
|
|
115
|
+
parsed: parseOptions(args.slice(1), "packet-build-batch", {
|
|
116
|
+
runId: { flag: "--run-id", required: true },
|
|
117
|
+
batchSize: { flag: "--batch-size", required: true },
|
|
118
|
+
findingIds: { flag: "--finding-ids" },
|
|
119
|
+
packetPrefix: { flag: "--packet-prefix" },
|
|
120
|
+
manifestId: { flag: "--manifest-id" },
|
|
121
|
+
explicitQuestion: { flag: "--explicit-question" },
|
|
122
|
+
explicitQuestions: { flag: "--explicit-questions" },
|
|
123
|
+
priorDesignStateRefs: { flag: "--prior-design-state-refs" },
|
|
124
|
+
priorDesignStateMarker: { flag: "--prior-design-state-marker" },
|
|
125
|
+
currentClusterRefs: { flag: "--current-cluster-refs" },
|
|
126
|
+
currentWaveRefs: { flag: "--current-wave-refs" },
|
|
127
|
+
authorityOnly: { flag: "--authority-only", type: "boolean", default: false },
|
|
128
|
+
verifiedAt: { flag: "--verified-at" },
|
|
129
|
+
json: { default: false },
|
|
130
|
+
}),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (phase === "result-ingest") {
|
|
134
|
+
return {
|
|
135
|
+
ok: true,
|
|
136
|
+
action: "result-ingest",
|
|
137
|
+
parsed: parseOptions(args.slice(1), "result-ingest", {
|
|
138
|
+
runId: { flag: "--run-id", required: true },
|
|
139
|
+
from: { flag: "--from", required: true },
|
|
140
|
+
mode: { flag: "--mode", default: "focused" },
|
|
141
|
+
allowSyntheticTrial: { flag: "--allow-synthetic-trial", type: "boolean", default: false },
|
|
142
|
+
verifiedAt: { flag: "--verified-at" },
|
|
143
|
+
json: { default: false },
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (phase === "auditor-prompt") {
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
action: "auditor-prompt",
|
|
151
|
+
parsed: parseOptions(args.slice(1), "auditor-prompt", {
|
|
152
|
+
runId: { flag: "--run-id", required: true },
|
|
153
|
+
packetId: { flag: "--packet-id", required: true },
|
|
154
|
+
verifiedAt: { flag: "--verified-at" },
|
|
155
|
+
json: { default: false },
|
|
156
|
+
}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
if (phase === "finalize") {
|
|
160
|
+
return {
|
|
161
|
+
ok: true,
|
|
162
|
+
action: "finalize",
|
|
163
|
+
parsed: parseOptions(args.slice(1), "finalize", {
|
|
164
|
+
runId: { flag: "--run-id", required: true },
|
|
165
|
+
allowSyntheticCloseout: { flag: "--allow-synthetic-closeout", type: "boolean", default: false },
|
|
166
|
+
verifiedAt: { flag: "--verified-at" },
|
|
167
|
+
json: { default: false },
|
|
168
|
+
}),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (phase === "ledger-validate") {
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
action: "ledger-validate",
|
|
175
|
+
parsed: parseOptions(args.slice(1), "ledger-validate", {
|
|
176
|
+
runId: { flag: "--run-id", required: true },
|
|
177
|
+
verifiedAt: { flag: "--verified-at" },
|
|
178
|
+
json: { default: false },
|
|
179
|
+
}),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (phase === "wave-plan") {
|
|
183
|
+
return {
|
|
184
|
+
ok: true,
|
|
185
|
+
action: "wave-plan",
|
|
186
|
+
parsed: parseOptions(args.slice(1), "wave-plan", {
|
|
187
|
+
runId: { flag: "--run-id", required: true },
|
|
188
|
+
topicId: { flag: "--topic-id", required: true },
|
|
189
|
+
allowSyntheticTrial: { flag: "--allow-synthetic-trial", type: "boolean", default: false },
|
|
190
|
+
verifiedAt: { flag: "--verified-at" },
|
|
191
|
+
json: { default: false },
|
|
192
|
+
}),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
if (phase === "fix-topic") {
|
|
196
|
+
return {
|
|
197
|
+
ok: true,
|
|
198
|
+
action: "fix-topic",
|
|
199
|
+
parsed: parseOptions(args.slice(1), "fix-topic", {
|
|
200
|
+
runId: { flag: "--run-id", required: true },
|
|
201
|
+
slug: { flag: "--slug" },
|
|
202
|
+
title: { flag: "--title" },
|
|
203
|
+
admitFirstWave: { flag: "--admit-first-wave", type: "boolean", default: false },
|
|
204
|
+
admitWaveId: { flag: "--admit-wave-id" },
|
|
205
|
+
verifiedAt: { flag: "--verified-at" },
|
|
206
|
+
json: { default: false },
|
|
207
|
+
}),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
ok: false,
|
|
212
|
+
error: `${localize(
|
|
213
|
+
"nimicoding sweep design refused: expected intake, packet-build, packet-build-batch, auditor-prompt, result-ingest, ledger-validate, finalize, wave-plan, or fix-topic.",
|
|
214
|
+
"nimicoding sweep design 已拒绝:需要 intake、packet-build、packet-build-batch、auditor-prompt、result-ingest、ledger-validate、finalize、wave-plan 或 fix-topic。",
|
|
215
|
+
)}\n`,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function emitResult(result, json) {
|
|
220
|
+
if (result.inputError) {
|
|
221
|
+
process.stderr.write(result.error);
|
|
222
|
+
return result.exitCode ?? 2;
|
|
223
|
+
}
|
|
224
|
+
if (!result.ok) {
|
|
225
|
+
process.stderr.write(result.error ?? "nimicoding sweep design failed.\n");
|
|
226
|
+
return result.exitCode ?? 1;
|
|
227
|
+
}
|
|
228
|
+
if (json) {
|
|
229
|
+
process.stdout.write(`${JSON.stringify({ command: "sweep.design", ...result }, null, 2)}\n`);
|
|
230
|
+
} else {
|
|
231
|
+
const lines = ["sweep design result"];
|
|
232
|
+
for (const [label, value] of [
|
|
233
|
+
["run", result.runId],
|
|
234
|
+
["inventory", result.inventoryRef],
|
|
235
|
+
["ledger", result.ledgerRef],
|
|
236
|
+
["packet", result.packetRef],
|
|
237
|
+
["auditor prompt", result.promptRef],
|
|
238
|
+
["auditor result", result.resultRef],
|
|
239
|
+
["decision queue", result.decisionQueueRef],
|
|
240
|
+
["final state report", result.finalStateReportRef],
|
|
241
|
+
["wave plan", result.wavePlanRef],
|
|
242
|
+
["topic", result.topicRef],
|
|
243
|
+
["sweep fix source", result.sourceRef],
|
|
244
|
+
["wave catalog", result.waveCatalogRef],
|
|
245
|
+
]) {
|
|
246
|
+
if (value !== undefined && value !== null) {
|
|
247
|
+
lines.push(`${label}: ${value}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
for (const [label, value] of [
|
|
251
|
+
["findings", result.findingCount],
|
|
252
|
+
["finding outcomes", result.findingOutcomeCount],
|
|
253
|
+
["revision entries", result.revisionEntryCount],
|
|
254
|
+
["total findings", result.totalFindingCount],
|
|
255
|
+
["final findings", result.finalFindingCount],
|
|
256
|
+
["transient findings", result.transientFindingCount],
|
|
257
|
+
["waves", result.waveCount],
|
|
258
|
+
["admitted wave", result.admittedWaveId],
|
|
259
|
+
["stop class", result.stopClass],
|
|
260
|
+
["stop reason", result.stopReason],
|
|
261
|
+
]) {
|
|
262
|
+
if (value !== undefined && value !== null) {
|
|
263
|
+
lines.push(`${label}: ${value}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
process.stdout.write(`${lines.join("\n")}\n`);
|
|
267
|
+
}
|
|
268
|
+
return result.exitCode ?? 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export async function runSweepDesign(args) {
|
|
272
|
+
const parsedAction = parseSweepDesignOptions(args);
|
|
273
|
+
if (!parsedAction.ok) {
|
|
274
|
+
process.stderr.write(parsedAction.error);
|
|
275
|
+
return 2;
|
|
276
|
+
}
|
|
277
|
+
if (!parsedAction.parsed.ok) {
|
|
278
|
+
process.stderr.write(parsedAction.parsed.error);
|
|
279
|
+
return 2;
|
|
280
|
+
}
|
|
281
|
+
const options = parsedAction.parsed.options;
|
|
282
|
+
const projectRoot = process.cwd();
|
|
283
|
+
const actions = {
|
|
284
|
+
intake: runIntake,
|
|
285
|
+
"packet-build": runPacketBuild,
|
|
286
|
+
"packet-build-batch": runPacketBuildBatch,
|
|
287
|
+
"auditor-prompt": runAuditorPrompt,
|
|
288
|
+
"result-ingest": runResultIngest,
|
|
289
|
+
"ledger-validate": runLedgerValidate,
|
|
290
|
+
finalize: runFinalize,
|
|
291
|
+
"wave-plan": runWavePlan,
|
|
292
|
+
"fix-topic": runFixTopic,
|
|
293
|
+
};
|
|
294
|
+
return emitResult(await actions[parsedAction.action](projectRoot, options), options.json);
|
|
295
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { runAuditSweep } from "./audit-sweep.mjs";
|
|
2
|
+
import { runSweepDesign } from "./sweep-design.mjs";
|
|
3
|
+
import { localize } from "../lib/ui.mjs";
|
|
4
|
+
|
|
5
|
+
export async function runSweep(args) {
|
|
6
|
+
const [command] = args;
|
|
7
|
+
const rest = args.slice(1);
|
|
8
|
+
|
|
9
|
+
if (command === "audit") {
|
|
10
|
+
return runAuditSweep(rest);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (command === "design") {
|
|
14
|
+
return runSweepDesign(rest);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
process.stderr.write(localize(
|
|
18
|
+
"nimicoding sweep refused: expected `audit` or `design`.\n",
|
|
19
|
+
"nimicoding sweep 已拒绝:需要使用 `audit` 或 `design`。\n",
|
|
20
|
+
));
|
|
21
|
+
return 2;
|
|
22
|
+
}
|
|
@@ -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) {
|