perttool 0.8.1 → 0.9.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 +37 -1
- package/README.md +100 -38
- package/dist/application/cli-facade.d.ts +12 -7
- package/dist/application/cli-facade.d.ts.map +1 -1
- package/dist/application/cli-facade.js +16 -7
- package/dist/application/cli-facade.js.map +1 -1
- package/dist/application/contract8-milestone-acceptance.d.ts +74 -0
- package/dist/application/contract8-milestone-acceptance.d.ts.map +1 -0
- package/dist/application/contract8-milestone-acceptance.js +185 -0
- package/dist/application/contract8-milestone-acceptance.js.map +1 -0
- package/dist/application/editor-milestone-acceptance.d.ts +75 -0
- package/dist/application/editor-milestone-acceptance.d.ts.map +1 -0
- package/dist/application/editor-milestone-acceptance.js +161 -0
- package/dist/application/editor-milestone-acceptance.js.map +1 -0
- package/dist/application/target-governance-init.d.ts +1 -1
- package/dist/application/target-governance-init.d.ts.map +1 -1
- package/dist/application/target-governance-init.js +3 -5
- package/dist/application/target-governance-init.js.map +1 -1
- package/dist/application/target-governance-project.d.ts +2 -2
- package/dist/application/target-governance-project.d.ts.map +1 -1
- package/dist/application/target-historical-graph.d.ts +3 -1
- package/dist/application/target-historical-graph.d.ts.map +1 -1
- package/dist/application/target-historical-graph.js +85 -2
- package/dist/application/target-historical-graph.js.map +1 -1
- package/dist/application/target-project-history.d.ts +10 -0
- package/dist/application/target-project-history.d.ts.map +1 -1
- package/dist/application/target-project-history.js +54 -0
- package/dist/application/target-project-history.js.map +1 -1
- package/dist/application/target-velocity-observation.d.ts +6 -1
- package/dist/application/target-velocity-observation.d.ts.map +1 -1
- package/dist/application/target-velocity-observation.js +72 -4
- package/dist/application/target-velocity-observation.js.map +1 -1
- package/dist/cli.js +377 -37
- package/dist/cli.js.map +1 -1
- package/dist/command/assurance-discovery.d.ts +4 -3
- package/dist/command/assurance-discovery.d.ts.map +1 -1
- package/dist/command/assurance-discovery.js +96 -9
- package/dist/command/assurance-discovery.js.map +1 -1
- package/dist/command/assurance-usage.js +2 -2
- package/dist/command/assurance-usage.js.map +1 -1
- package/dist/command/discovery.js +4 -4
- package/dist/command/discovery.js.map +1 -1
- package/dist/command/registry.d.ts +1 -1
- package/dist/command/registry.d.ts.map +1 -1
- package/dist/command/registry.js +2 -2
- package/dist/command/registry.js.map +1 -1
- package/dist/command/usage.d.ts.map +1 -1
- package/dist/command/usage.js +12 -4
- package/dist/command/usage.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/help/assurance-guide.d.ts +1 -1
- package/dist/help/assurance-guide.d.ts.map +1 -1
- package/dist/help/assurance-guide.js +46 -19
- package/dist/help/assurance-guide.js.map +1 -1
- package/dist/help/guide.d.ts +1 -1
- package/dist/help/guide.d.ts.map +1 -1
- package/dist/help/registry.js +5 -5
- package/dist/help/registry.js.map +1 -1
- package/dist/history/historical-graph.d.ts +2 -0
- package/dist/history/historical-graph.d.ts.map +1 -1
- package/dist/history/historical-graph.js +98 -24
- package/dist/history/historical-graph.js.map +1 -1
- package/dist/history/milestone-acceptance-history.d.ts +59 -0
- package/dist/history/milestone-acceptance-history.d.ts.map +1 -0
- package/dist/history/milestone-acceptance-history.js +332 -0
- package/dist/history/milestone-acceptance-history.js.map +1 -0
- package/dist/index.d.ts +10 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/index.js.map +1 -1
- package/dist/migration/grammar-boundary.d.ts +1 -1
- package/dist/migration/grammar-boundary.d.ts.map +1 -1
- package/dist/migration/grammar-boundary.js +7 -3
- package/dist/migration/grammar-boundary.js.map +1 -1
- package/dist/milestone-acceptance/advance.d.ts +39 -0
- package/dist/milestone-acceptance/advance.d.ts.map +1 -0
- package/dist/milestone-acceptance/advance.js +112 -0
- package/dist/milestone-acceptance/advance.js.map +1 -0
- package/dist/milestone-acceptance/evaluate.d.ts +51 -0
- package/dist/milestone-acceptance/evaluate.d.ts.map +1 -0
- package/dist/milestone-acceptance/evaluate.js +114 -0
- package/dist/milestone-acceptance/evaluate.js.map +1 -0
- package/dist/milestone-acceptance/migration.d.ts +25 -0
- package/dist/milestone-acceptance/migration.d.ts.map +1 -0
- package/dist/milestone-acceptance/migration.js +76 -0
- package/dist/milestone-acceptance/migration.js.map +1 -0
- package/dist/milestone-acceptance/mutation.d.ts +49 -0
- package/dist/milestone-acceptance/mutation.d.ts.map +1 -0
- package/dist/milestone-acceptance/mutation.js +136 -0
- package/dist/milestone-acceptance/mutation.js.map +1 -0
- package/dist/milestone-acceptance/source.d.ts +83 -0
- package/dist/milestone-acceptance/source.d.ts.map +1 -0
- package/dist/milestone-acceptance/source.js +301 -0
- package/dist/milestone-acceptance/source.js.map +1 -0
- package/dist/mutation/advance-deletion.d.ts.map +1 -1
- package/dist/mutation/advance-deletion.js +6 -1
- package/dist/mutation/advance-deletion.js.map +1 -1
- package/dist/perttool-vscode-private-0.0.0-d1578b9.vsix +0 -0
- package/dist/recommendation/override-types.d.ts +2 -2
- package/dist/recommendation/override.d.ts +1 -1
- package/dist/recommendation/override.js +2 -2
- package/dist/schema/registry.d.ts +1 -1
- package/dist/schema/registry.d.ts.map +1 -1
- package/dist/schema/registry.js +8 -6
- package/dist/schema/registry.js.map +1 -1
- package/dist/semantic/validator.d.ts.map +1 -1
- package/dist/semantic/validator.js +14 -3
- package/dist/semantic/validator.js.map +1 -1
- package/dist/session/document-session.d.ts +5 -0
- package/dist/session/document-session.d.ts.map +1 -1
- package/dist/session/document-session.js +25 -2
- package/dist/session/document-session.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/schemas/{Perttool.AdvanceResult.v2.schema.json → Perttool.AdvanceResult.v3.schema.json} +36 -5
- package/schemas/Perttool.AgentGuidanceResult.v1.schema.json +1 -1
- package/schemas/{Perttool.AnalysisResult.v5.schema.json → Perttool.AnalysisResult.v6.schema.json} +12 -5
- package/schemas/{Perttool.CheckResult.v4.schema.json → Perttool.CheckResult.v5.schema.json} +12 -5
- package/schemas/Perttool.CliError.v1.schema.json +1 -1
- package/schemas/Perttool.CommandHelpResult.v1.schema.json +3 -3
- package/schemas/Perttool.ExportResult.v1.schema.json +1 -1
- package/schemas/Perttool.FormatResult.v1.schema.json +1 -1
- package/schemas/Perttool.GuideResult.v1.schema.json +1 -1
- package/schemas/Perttool.HistoricalGraphResult.v1.schema.json +100 -2
- package/schemas/Perttool.ImportResult.v1.schema.json +1 -1
- package/schemas/Perttool.InitResult.v1.schema.json +1 -1
- package/schemas/Perttool.MilestoneAcceptanceMigrationResult.v1.schema.json +24 -0
- package/schemas/Perttool.MilestoneAcceptanceResult.v1.schema.json +79 -0
- package/schemas/{Perttool.MutationResult.v4.schema.json → Perttool.MutationResult.v5.schema.json} +4 -4
- package/schemas/{Perttool.NextResult.v6.schema.json → Perttool.NextResult.v7.schema.json} +12 -5
- package/schemas/Perttool.OverrideDecision.v1.schema.json +1 -1
- package/schemas/Perttool.PlanAssuranceResult.v1.schema.json +1 -1
- package/schemas/Perttool.ProjectHistoryResult.v1.schema.json +1 -1
- package/schemas/Perttool.ProjectResult.v4.schema.json +2 -2
- package/schemas/Perttool.SchemaResult.v1.schema.json +1 -1
- package/schemas/Perttool.UnitMigrationResult.v3.schema.json +5 -3
- package/schemas/Perttool.VelocityObservationResult.v1.schema.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -19,11 +19,29 @@ import { formatDecimal } from "./model/rational.js";
|
|
|
19
19
|
import { convertWithVelocity, durationSuffix } from "./model/units.js";
|
|
20
20
|
import { recommendationInvariantExitCode } from "./recommendation/failure.js";
|
|
21
21
|
import { recommendationAnalysisToJson } from "./recommendation/json.js";
|
|
22
|
+
import { applyTextEdits, normalizeTextEdits } from "./mutation/text-edits.js";
|
|
23
|
+
import { createUnifiedDiff } from "./editing/unified-diff.js";
|
|
24
|
+
import { sha256DigestUtf8 } from "./model/sha256.js";
|
|
22
25
|
import { TARGET_GRAMMAR_6_CAPABILITY, } from "./parser/document-parser.js";
|
|
23
26
|
import { exportPlanAssuranceMermaid, importPlanAssuranceMermaid, } from "./assurance/mermaid.js";
|
|
24
27
|
import { getJsonSchemaResult, renderJsonSchemaResult, serializeJsonSchemaResult, } from "./schema/registry.js";
|
|
25
28
|
import { TOOL_VERSION } from "./version.js";
|
|
26
|
-
|
|
29
|
+
import { analyzeDocument as analyzeContract8Document, checkDocument as checkContract8Document, selectNextTasks as selectContract8NextTasks, } from "./application/contract8-milestone-acceptance.js";
|
|
30
|
+
import { persistMilestoneAcceptanceMutation, planAcceptanceReceiptMutation, planCriterionSetReplacement, showMilestoneAcceptance, } from "./milestone-acceptance/mutation.js";
|
|
31
|
+
import { planMilestoneAcceptanceMigration, recheckCommittedMigrationProof, } from "./milestone-acceptance/migration.js";
|
|
32
|
+
import { MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY, milestoneAcceptanceBaseText, parseMilestoneAcceptanceSource } from "./milestone-acceptance/source.js";
|
|
33
|
+
import { planMilestoneAcceptanceAdvance } from "./milestone-acceptance/advance.js";
|
|
34
|
+
const { analyzeDocument: _analyzeContract7Document, checkDocument: _checkContract7Document, selectNextTasks: _selectContract7NextTasks, planFormat, planProjectInit, projectInitResultToJson, renderProjectInitResult, withProjectInitOutput, planUnitMigration, withUnitMigrationWrite, getProjectMetadata, contract7ProjectResultToJson, renderContract7ProjectText, planAdvance, planBatchMutation, planFinishActuals, planLifecycle, planMutation, planAssuranceMutation, renderTargetGovernanceDecision, contract7InspectionResultToJson, contract7MutationResultToJson, contract7SnakeJson, contract6WorkEventToJson, renderAdvanceHistoryGuard, prepareTargetPlanAssuranceAdvanceHistory, prepareAdvanceHistory, withAdvanceHistoryRace, withTargetPlanAssuranceAdvanceHistoryRace, persistTargetPlanAssuranceResult, inspectTargetPlanAssurance, inspectTargetCurrentProjectActuals, inspectTargetProjectHistoryFile, renderTargetProjectHistoryText, targetProjectHistoryResultToJson, observeTargetProjectVelocity, renderTargetVelocityObservationText, targetVelocityObservationResultToJson, getAgentHelp, documentContentFromBytes, readDocumentContent, readBytes, recheckAdvanceHistoryBaseline, captureAdvanceHistoryBaseline, createArtifactFile, createValidatedDocumentFile, createTargetGrammar6DocumentFile, replaceTargetGrammar6DocumentFile, replaceValidatedDocumentFile, inspectTargetHistoricalGraphFile, renderTargetHistoricalGraphText, targetHistoricalGraphResultToJson, } = createCliApplicationFacade(createNodeHost(), createHistoricalGraphGitEvidenceHost());
|
|
35
|
+
const analyzeDocument = analyzeContract8Document;
|
|
36
|
+
const checkDocument = checkContract8Document;
|
|
37
|
+
const selectNextTasks = selectContract8NextTasks;
|
|
38
|
+
function contract8MutationResultToJson(result, ...args) {
|
|
39
|
+
return Object.freeze({
|
|
40
|
+
...contract7MutationResultToJson(result, ...args),
|
|
41
|
+
schema_version: "Perttool.MutationResult.v5",
|
|
42
|
+
cli_contract_version: 8,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
27
45
|
class UsageError extends Error {
|
|
28
46
|
code = "PTCLI-001";
|
|
29
47
|
}
|
|
@@ -195,7 +213,11 @@ async function readStdin() {
|
|
|
195
213
|
return Buffer.concat(chunks);
|
|
196
214
|
}
|
|
197
215
|
function writeJson(value) {
|
|
198
|
-
|
|
216
|
+
const contract8Value = typeof value === "object" && value !== null && !Array.isArray(value) &&
|
|
217
|
+
"cli_contract_version" in value
|
|
218
|
+
? { ...value, cli_contract_version: 8 }
|
|
219
|
+
: value;
|
|
220
|
+
process.stdout.write(`${JSON.stringify(contract8Value)}\n`);
|
|
199
221
|
}
|
|
200
222
|
function snakeJson(value) {
|
|
201
223
|
if (typeof value === "bigint")
|
|
@@ -232,7 +254,7 @@ function cliError(error, exitCode, operation, json) {
|
|
|
232
254
|
if (json) {
|
|
233
255
|
writeJson({
|
|
234
256
|
schema_version: "Perttool.CliError.v1",
|
|
235
|
-
cli_contract_version:
|
|
257
|
+
cli_contract_version: 8,
|
|
236
258
|
tool_version: TOOL_VERSION,
|
|
237
259
|
operation,
|
|
238
260
|
ok: false,
|
|
@@ -268,7 +290,7 @@ async function runCheck(args) {
|
|
|
268
290
|
if (format === "json") {
|
|
269
291
|
writeJson({
|
|
270
292
|
schema_version: result.schemaVersion,
|
|
271
|
-
cli_contract_version:
|
|
293
|
+
cli_contract_version: 8,
|
|
272
294
|
tool_version: TOOL_VERSION,
|
|
273
295
|
operation: "document.check",
|
|
274
296
|
ok,
|
|
@@ -288,6 +310,7 @@ async function runCheck(args) {
|
|
|
288
310
|
},
|
|
289
311
|
assurance: contract7SnakeJson(result.assurance),
|
|
290
312
|
assurance_state_counts: contract7SnakeJson(result.assuranceStateCounts),
|
|
313
|
+
acceptance: snakeJson(result.acceptance),
|
|
291
314
|
});
|
|
292
315
|
}
|
|
293
316
|
else {
|
|
@@ -345,7 +368,7 @@ async function runProjectInit(args) {
|
|
|
345
368
|
const parsed = parseCommandOptions("project.init", args);
|
|
346
369
|
const format = outputFormat(parsed.values.get("format"));
|
|
347
370
|
const color = colorMode(parsed.values.get("color"), format);
|
|
348
|
-
const durationUnit = enumOption(
|
|
371
|
+
const durationUnit = enumOption(parsed.values.get("duration-unit") ?? "point", "duration-unit", new Set(["day", "hour", "point"]));
|
|
349
372
|
const version = optionalInteger(parsed, "version", 0, 2_147_483_647);
|
|
350
373
|
let result = planProjectInit({
|
|
351
374
|
projectId: parsed.positionals[0],
|
|
@@ -518,6 +541,28 @@ async function persistGovernedResult(result, request, sourceOperand) {
|
|
|
518
541
|
target: request.target,
|
|
519
542
|
});
|
|
520
543
|
}
|
|
544
|
+
async function persistContract8CandidateResult(result, request) {
|
|
545
|
+
if (request.mode === "preview" || !result.changed) {
|
|
546
|
+
return Object.freeze({ mode: request.mode, target: request.target, written: false });
|
|
547
|
+
}
|
|
548
|
+
if (!result.ok || !result.governance?.writeAuthorized || result.updatedText === null) {
|
|
549
|
+
throw new TypeError("authorized Contract 8 result does not contain a digest-bound candidate");
|
|
550
|
+
}
|
|
551
|
+
const validator = (candidate) => {
|
|
552
|
+
const parsed = parseMilestoneAcceptanceSource(candidate, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
|
|
553
|
+
return { ok: parsed.ok, diagnostics: [] };
|
|
554
|
+
};
|
|
555
|
+
if (request.mode === "in_place") {
|
|
556
|
+
await replaceValidatedDocumentFile(request.target, result.updatedText, {
|
|
557
|
+
initialDigest: result.originalDigest,
|
|
558
|
+
...(request.expectedDigest === undefined ? {} : { expectedDigest: request.expectedDigest }),
|
|
559
|
+
}, validator);
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
await createValidatedDocumentFile(request.target, result.updatedText, validator);
|
|
563
|
+
}
|
|
564
|
+
return Object.freeze({ mode: request.mode, target: request.target, written: true });
|
|
565
|
+
}
|
|
521
566
|
function assertExpectedDigest(request, initialDigest) {
|
|
522
567
|
if (request.mode === "in_place" &&
|
|
523
568
|
request.expectedDigest !== undefined &&
|
|
@@ -529,6 +574,21 @@ async function commitCandidate(request, candidateText, initialDigest) {
|
|
|
529
574
|
if (candidateText === null) {
|
|
530
575
|
throw new SafeWriteVerificationError("invalid_candidate", "successful editing result has no candidate text");
|
|
531
576
|
}
|
|
577
|
+
const acceptanceSource = parseMilestoneAcceptanceSource(candidateText, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
|
|
578
|
+
if (acceptanceSource.grammarVersion === 7) {
|
|
579
|
+
const validator = (candidate) => {
|
|
580
|
+
const parsed = parseMilestoneAcceptanceSource(candidate, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
|
|
581
|
+
return { ok: parsed.ok, diagnostics: [] };
|
|
582
|
+
};
|
|
583
|
+
return request.mode === "in_place"
|
|
584
|
+
? replaceValidatedDocumentFile(request.target, candidateText, {
|
|
585
|
+
initialDigest,
|
|
586
|
+
...(request.expectedDigest === undefined
|
|
587
|
+
? {}
|
|
588
|
+
: { expectedDigest: request.expectedDigest }),
|
|
589
|
+
}, validator)
|
|
590
|
+
: createValidatedDocumentFile(request.target, candidateText, validator);
|
|
591
|
+
}
|
|
532
592
|
return request.mode === "in_place"
|
|
533
593
|
? replaceTargetGrammar6DocumentFile(request.target, candidateText, TARGET_GRAMMAR_6_CAPABILITY, {
|
|
534
594
|
initialDigest,
|
|
@@ -596,7 +656,7 @@ async function runFormat(args) {
|
|
|
596
656
|
if (format === "json") {
|
|
597
657
|
writeJson({
|
|
598
658
|
schema_version: "Perttool.FormatResult.v1",
|
|
599
|
-
cli_contract_version:
|
|
659
|
+
cli_contract_version: 8,
|
|
600
660
|
tool_version: TOOL_VERSION,
|
|
601
661
|
operation: "document.format",
|
|
602
662
|
ok,
|
|
@@ -1197,7 +1257,7 @@ async function runMutation(resource, action, args) {
|
|
|
1197
1257
|
if (result.ok) {
|
|
1198
1258
|
try {
|
|
1199
1259
|
if (ok && writeRequest.mode !== "preview") {
|
|
1200
|
-
writeResult = await
|
|
1260
|
+
writeResult = await persistContract8CandidateResult(result, writeRequest);
|
|
1201
1261
|
}
|
|
1202
1262
|
}
|
|
1203
1263
|
catch (error) {
|
|
@@ -1205,7 +1265,7 @@ async function runMutation(resource, action, args) {
|
|
|
1205
1265
|
}
|
|
1206
1266
|
}
|
|
1207
1267
|
if (format === "json") {
|
|
1208
|
-
writeJson(
|
|
1268
|
+
writeJson(contract8MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
|
|
1209
1269
|
}
|
|
1210
1270
|
else {
|
|
1211
1271
|
if (ok) {
|
|
@@ -1281,14 +1341,14 @@ async function runLifecycleMutation(action, args) {
|
|
|
1281
1341
|
});
|
|
1282
1342
|
if (result.ok && ok && writeRequest.mode !== "preview") {
|
|
1283
1343
|
try {
|
|
1284
|
-
writeResult = await
|
|
1344
|
+
writeResult = await persistContract8CandidateResult(result, writeRequest);
|
|
1285
1345
|
}
|
|
1286
1346
|
catch (error) {
|
|
1287
1347
|
return writeFailureExit(error, operation, format === "json");
|
|
1288
1348
|
}
|
|
1289
1349
|
}
|
|
1290
1350
|
if (format === "json") {
|
|
1291
|
-
writeJson(
|
|
1351
|
+
writeJson(contract8MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
|
|
1292
1352
|
}
|
|
1293
1353
|
else {
|
|
1294
1354
|
if (ok) {
|
|
@@ -1327,7 +1387,7 @@ function unitMigrationJson(result, source, sourceDigest, ok) {
|
|
|
1327
1387
|
});
|
|
1328
1388
|
return {
|
|
1329
1389
|
schema_version: result.schemaVersion,
|
|
1330
|
-
cli_contract_version:
|
|
1390
|
+
cli_contract_version: 8,
|
|
1331
1391
|
tool_version: TOOL_VERSION,
|
|
1332
1392
|
operation: "project.migrate-unit",
|
|
1333
1393
|
ok,
|
|
@@ -1455,7 +1515,7 @@ async function runUnitMigration(args) {
|
|
|
1455
1515
|
}
|
|
1456
1516
|
return ok ? 0 : 1;
|
|
1457
1517
|
}
|
|
1458
|
-
async function readHistoryForCommand(operation, parsed, format) {
|
|
1518
|
+
async function readHistoryForCommand(operation, parsed, format, expectedSourceDigest) {
|
|
1459
1519
|
if (parsed.positionals.length !== 1) {
|
|
1460
1520
|
throw new UsageError(`${operation.replace(".", " ")} requires exactly one <file>`);
|
|
1461
1521
|
}
|
|
@@ -1472,6 +1532,9 @@ async function readHistoryForCommand(operation, parsed, format) {
|
|
|
1472
1532
|
...(parsed.repeatedValues.get("task") === undefined
|
|
1473
1533
|
? {}
|
|
1474
1534
|
: { taskIds: parsed.repeatedValues.get("task") }),
|
|
1535
|
+
...(expectedSourceDigest === undefined
|
|
1536
|
+
? {}
|
|
1537
|
+
: { expectedSourceDigest }),
|
|
1475
1538
|
}, TARGET_GRAMMAR_6_CAPABILITY);
|
|
1476
1539
|
}
|
|
1477
1540
|
catch (error) {
|
|
@@ -1559,20 +1622,37 @@ async function runProjectVelocityObservation(args) {
|
|
|
1559
1622
|
const parsed = parseCommandOptions("project.observe-velocity", args);
|
|
1560
1623
|
const format = outputFormat(parsed.values.get("format"));
|
|
1561
1624
|
const color = colorMode(parsed.values.get("color"), format);
|
|
1562
|
-
const history = await readHistoryForCommand("project.observe-velocity", parsed, format);
|
|
1563
|
-
if (history instanceof Error) {
|
|
1564
|
-
return cliError(history, 3, "project.observe-velocity", format === "json");
|
|
1565
|
-
}
|
|
1566
1625
|
const evidenceValue = parsed.values.get("evidence") ?? "declared";
|
|
1567
1626
|
const evidence = evidenceValue === "git-recorded"
|
|
1568
1627
|
? "git_recorded"
|
|
1569
1628
|
: evidenceValue;
|
|
1629
|
+
const source = parsed.positionals[0];
|
|
1630
|
+
let current = null;
|
|
1631
|
+
if (evidence !== "git_recorded" && source !== undefined && source !== "-") {
|
|
1632
|
+
try {
|
|
1633
|
+
current = await readDocumentContent(source);
|
|
1634
|
+
}
|
|
1635
|
+
catch (error) {
|
|
1636
|
+
return cliError(error instanceof Error ? error : new Error(String(error)), 3, "project.observe-velocity", format === "json");
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
const history = await readHistoryForCommand("project.observe-velocity", parsed, format, current?.digest);
|
|
1640
|
+
if (history instanceof Error) {
|
|
1641
|
+
return cliError(history, 3, "project.observe-velocity", format === "json");
|
|
1642
|
+
}
|
|
1643
|
+
const taskIds = parsed.repeatedValues.get("task");
|
|
1644
|
+
const currentActuals = current === null
|
|
1645
|
+
? null
|
|
1646
|
+
: inspectTargetCurrentProjectActuals({ bytes: current.bytes, digest: current.digest }, taskIds === undefined ? {} : { taskIds }, TARGET_GRAMMAR_6_CAPABILITY);
|
|
1570
1647
|
const result = observeTargetProjectVelocity(history, {
|
|
1571
|
-
...(
|
|
1572
|
-
? {}
|
|
1573
|
-
: { taskIds: parsed.repeatedValues.get("task") }),
|
|
1648
|
+
...(taskIds === undefined ? {} : { taskIds }),
|
|
1574
1649
|
evidence,
|
|
1575
|
-
}
|
|
1650
|
+
}, currentActuals === null || current === null
|
|
1651
|
+
? {}
|
|
1652
|
+
: {
|
|
1653
|
+
currentActuals,
|
|
1654
|
+
currentSourceDigest: current.digest,
|
|
1655
|
+
});
|
|
1576
1656
|
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1577
1657
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
|
|
1578
1658
|
const ok = result.ok && !warningFailure;
|
|
@@ -1628,16 +1708,94 @@ async function runAdvance(args) {
|
|
|
1628
1708
|
catch (error) {
|
|
1629
1709
|
return cliError(error instanceof Error ? error : new Error(String(error)), 3, "dag.advance", format === "json");
|
|
1630
1710
|
}
|
|
1631
|
-
const
|
|
1711
|
+
const acceptancePlan = planMilestoneAcceptanceAdvance(input.text, {
|
|
1712
|
+
maxDiagnostics,
|
|
1713
|
+
originalLabel: source,
|
|
1714
|
+
updatedLabel: "candidate",
|
|
1715
|
+
provisionalPlanner: (baseText) => planAdvance(baseText, {
|
|
1716
|
+
maxDiagnostics,
|
|
1717
|
+
originalLabel: source,
|
|
1718
|
+
updatedLabel: "candidate",
|
|
1719
|
+
}),
|
|
1720
|
+
});
|
|
1721
|
+
if (!acceptancePlan.ok) {
|
|
1722
|
+
if (format === "json")
|
|
1723
|
+
writeJson({
|
|
1724
|
+
schema_version: "Perttool.AdvanceResult.v3",
|
|
1725
|
+
cli_contract_version: 8,
|
|
1726
|
+
tool_version: TOOL_VERSION,
|
|
1727
|
+
operation: "dag.advance",
|
|
1728
|
+
ok: false,
|
|
1729
|
+
document_id: /^project ([A-Za-z][A-Za-z0-9_-]*):$/mu.exec(input.text)?.[1] ?? null,
|
|
1730
|
+
source,
|
|
1731
|
+
source_digest: input.digest,
|
|
1732
|
+
diagnostics: acceptancePlan.diagnostics.map(jsonDiagnostic),
|
|
1733
|
+
diagnostics_truncated: false,
|
|
1734
|
+
changed: acceptancePlan.provisional !== null,
|
|
1735
|
+
original_digest: acceptancePlan.originalDigest,
|
|
1736
|
+
updated_digest: acceptancePlan.provisional?.updatedDigest ?? null,
|
|
1737
|
+
updated_text: acceptancePlan.provisional?.updatedText ?? null,
|
|
1738
|
+
diff: acceptancePlan.provisional?.diff ?? null,
|
|
1739
|
+
edits: snakeJson(acceptancePlan.provisional?.edits ?? []),
|
|
1740
|
+
write: { mode: writeRequest.mode, target: writeRequest.target, written: false },
|
|
1741
|
+
governance: null,
|
|
1742
|
+
lifecycle: null,
|
|
1743
|
+
advance: acceptancePlan.provisional === null ? null : snakeJson({
|
|
1744
|
+
...acceptancePlan.provisional.advance,
|
|
1745
|
+
removedWorkEventIds: [],
|
|
1746
|
+
removedAssuranceRecordIds: [],
|
|
1747
|
+
updatedAssuranceReceiptIds: [],
|
|
1748
|
+
}),
|
|
1749
|
+
history_guard: null,
|
|
1750
|
+
assurance_guard: null,
|
|
1751
|
+
acceptance_guard: snakeJson(acceptancePlan.acceptanceGuard),
|
|
1752
|
+
});
|
|
1753
|
+
else {
|
|
1754
|
+
if (acceptancePlan.provisional !== null)
|
|
1755
|
+
process.stdout.write(parsed.flags.has("diff") ? acceptancePlan.provisional.diff : acceptancePlan.provisional.updatedText);
|
|
1756
|
+
for (const diagnostic of acceptancePlan.diagnostics)
|
|
1757
|
+
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
1758
|
+
}
|
|
1759
|
+
return 1;
|
|
1760
|
+
}
|
|
1761
|
+
const contract7BaseText = milestoneAcceptanceBaseText(input.text);
|
|
1762
|
+
const contract7Planned = planAdvance(contract7BaseText, {
|
|
1632
1763
|
maxDiagnostics,
|
|
1633
1764
|
originalLabel: source,
|
|
1634
1765
|
updatedLabel: "candidate",
|
|
1635
1766
|
governance: governanceRequest(parsed, writeRequest),
|
|
1636
1767
|
});
|
|
1768
|
+
const combinedEdits = contract7Planned.updatedText === null
|
|
1769
|
+
? contract7Planned.edits
|
|
1770
|
+
: normalizeTextEdits(input.text, [...contract7Planned.edits, ...acceptancePlan.provisional.edits].filter((edit, index, values) => values.findIndex((candidate) => candidate.startOffset === edit.startOffset &&
|
|
1771
|
+
candidate.endOffset === edit.endOffset &&
|
|
1772
|
+
candidate.replacement === edit.replacement) === index), "Contract 8 acceptance-aware advance");
|
|
1773
|
+
const combinedText = contract7Planned.updatedText === null
|
|
1774
|
+
? null
|
|
1775
|
+
: applyTextEdits(input.text, combinedEdits);
|
|
1776
|
+
const combinedSource = combinedText === null
|
|
1777
|
+
? null
|
|
1778
|
+
: parseMilestoneAcceptanceSource(combinedText, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
|
|
1779
|
+
if (combinedSource !== null && !combinedSource.ok) {
|
|
1780
|
+
throw new Error("acceptance-aware assurance advance lost Grammar 7 validation");
|
|
1781
|
+
}
|
|
1782
|
+
const planned = Object.freeze({
|
|
1783
|
+
...contract7Planned,
|
|
1784
|
+
schemaVersion: "Perttool.AdvanceResult.v3",
|
|
1785
|
+
originalDigest: input.digest,
|
|
1786
|
+
updatedText: combinedText,
|
|
1787
|
+
updatedDigest: combinedText === null ? null : sha256DigestUtf8(combinedText),
|
|
1788
|
+
diff: combinedText === null ? null : createUnifiedDiff(input.text, combinedText, {
|
|
1789
|
+
originalLabel: source,
|
|
1790
|
+
updatedLabel: "candidate",
|
|
1791
|
+
}),
|
|
1792
|
+
edits: combinedEdits,
|
|
1793
|
+
acceptanceGuard: acceptancePlan.acceptanceGuard,
|
|
1794
|
+
});
|
|
1637
1795
|
const initialWarningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1638
1796
|
(planned.diagnosticsTruncated ||
|
|
1639
1797
|
planned.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
1640
|
-
const
|
|
1798
|
+
const preparedBase = await prepareAdvanceHistory(input.text, planned, {
|
|
1641
1799
|
mode: writeRequest.mode === "out"
|
|
1642
1800
|
? "out"
|
|
1643
1801
|
: writeRequest.mode,
|
|
@@ -1649,6 +1807,28 @@ async function runAdvance(args) {
|
|
|
1649
1807
|
forceRequested,
|
|
1650
1808
|
warningDenied: initialWarningFailure,
|
|
1651
1809
|
maxDiagnostics,
|
|
1810
|
+
documentValidator: (candidateText, candidateMaxDiagnostics) => {
|
|
1811
|
+
const acceptanceSource = parseMilestoneAcceptanceSource(candidateText, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
|
|
1812
|
+
const checked = checkContract8Document(candidateText, { maxDiagnostics: candidateMaxDiagnostics });
|
|
1813
|
+
return {
|
|
1814
|
+
ok: checked.ok && acceptanceSource.ok,
|
|
1815
|
+
document: checked.document,
|
|
1816
|
+
documentId: checked.documentId,
|
|
1817
|
+
diagnostics: checked.diagnostics,
|
|
1818
|
+
diagnosticsTruncated: checked.diagnosticsTruncated,
|
|
1819
|
+
};
|
|
1820
|
+
},
|
|
1821
|
+
});
|
|
1822
|
+
const prepared = Object.freeze({
|
|
1823
|
+
...preparedBase,
|
|
1824
|
+
result: Object.freeze({
|
|
1825
|
+
...preparedBase.result,
|
|
1826
|
+
schemaVersion: "Perttool.AdvanceResult.v3",
|
|
1827
|
+
governance: planned.governance,
|
|
1828
|
+
assuranceGuard: planned.assuranceGuard,
|
|
1829
|
+
acceptanceGuard: acceptancePlan.acceptanceGuard,
|
|
1830
|
+
advance: planned.advance,
|
|
1831
|
+
}),
|
|
1652
1832
|
});
|
|
1653
1833
|
let result = prepared.result;
|
|
1654
1834
|
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
@@ -1671,13 +1851,20 @@ async function runAdvance(args) {
|
|
|
1671
1851
|
result.historyGuard?.status === "forced")) {
|
|
1672
1852
|
const recheck = await recheckAdvanceHistoryBaseline(prepared.baseline, sourceOperand);
|
|
1673
1853
|
if (!recheck.ok) {
|
|
1674
|
-
result =
|
|
1854
|
+
result = Object.freeze({
|
|
1855
|
+
...withAdvanceHistoryRace(result, recheck, maxDiagnostics),
|
|
1856
|
+
schemaVersion: "Perttool.AdvanceResult.v3",
|
|
1857
|
+
governance: result.governance,
|
|
1858
|
+
assuranceGuard: result.assuranceGuard,
|
|
1859
|
+
acceptanceGuard: result.acceptanceGuard,
|
|
1860
|
+
advance: result.advance,
|
|
1861
|
+
});
|
|
1675
1862
|
ok = false;
|
|
1676
1863
|
historyRace = true;
|
|
1677
1864
|
}
|
|
1678
1865
|
}
|
|
1679
1866
|
if (ok && writeRequest.mode !== "preview") {
|
|
1680
|
-
writeResult = await
|
|
1867
|
+
writeResult = await persistContract8CandidateResult(result, writeRequest);
|
|
1681
1868
|
}
|
|
1682
1869
|
}
|
|
1683
1870
|
catch (error) {
|
|
@@ -1685,7 +1872,12 @@ async function runAdvance(args) {
|
|
|
1685
1872
|
}
|
|
1686
1873
|
}
|
|
1687
1874
|
if (format === "json") {
|
|
1688
|
-
writeJson(
|
|
1875
|
+
writeJson({
|
|
1876
|
+
...contract7MutationResultToJson((ok ? result : Object.freeze({ ...result, ok: false })), "dag.advance", source, writeResult),
|
|
1877
|
+
schema_version: "Perttool.AdvanceResult.v3",
|
|
1878
|
+
cli_contract_version: 8,
|
|
1879
|
+
acceptance_guard: snakeJson(result.acceptanceGuard),
|
|
1880
|
+
});
|
|
1689
1881
|
}
|
|
1690
1882
|
else {
|
|
1691
1883
|
if (result.advance !== null) {
|
|
@@ -2046,7 +2238,7 @@ async function runAnalyze(args) {
|
|
|
2046
2238
|
if (format === "json") {
|
|
2047
2239
|
writeJson({
|
|
2048
2240
|
schema_version: result.schemaVersion,
|
|
2049
|
-
cli_contract_version:
|
|
2241
|
+
cli_contract_version: 8,
|
|
2050
2242
|
tool_version: TOOL_VERSION,
|
|
2051
2243
|
operation: "dag.analyze",
|
|
2052
2244
|
ok,
|
|
@@ -2079,6 +2271,7 @@ async function runAnalyze(args) {
|
|
|
2079
2271
|
: resourceJson(result.resource, result.durationUnit, result.precision),
|
|
2080
2272
|
temporal: snakeJson(result.temporal),
|
|
2081
2273
|
assurance: contract7SnakeJson(result.assurance),
|
|
2274
|
+
acceptance: snakeJson(result.acceptance),
|
|
2082
2275
|
});
|
|
2083
2276
|
}
|
|
2084
2277
|
else {
|
|
@@ -2193,7 +2386,7 @@ async function runRender(args) {
|
|
|
2193
2386
|
if (format === "json") {
|
|
2194
2387
|
writeJson({
|
|
2195
2388
|
schema_version: "Perttool.ExportResult.v1",
|
|
2196
|
-
cli_contract_version:
|
|
2389
|
+
cli_contract_version: 8,
|
|
2197
2390
|
tool_version: TOOL_VERSION,
|
|
2198
2391
|
operation: "dag.render",
|
|
2199
2392
|
ok,
|
|
@@ -2306,7 +2499,7 @@ async function runImport(args) {
|
|
|
2306
2499
|
if (format === "json") {
|
|
2307
2500
|
writeJson({
|
|
2308
2501
|
schema_version: "Perttool.ImportResult.v1",
|
|
2309
|
-
cli_contract_version:
|
|
2502
|
+
cli_contract_version: 8,
|
|
2310
2503
|
tool_version: TOOL_VERSION,
|
|
2311
2504
|
operation: "dag.import",
|
|
2312
2505
|
ok,
|
|
@@ -2615,7 +2808,7 @@ async function runNext(args) {
|
|
|
2615
2808
|
if (format === "json") {
|
|
2616
2809
|
writeJson({
|
|
2617
2810
|
schema_version: "Perttool.CliError.v1",
|
|
2618
|
-
cli_contract_version:
|
|
2811
|
+
cli_contract_version: 8,
|
|
2619
2812
|
tool_version: TOOL_VERSION,
|
|
2620
2813
|
operation: "dag.next",
|
|
2621
2814
|
ok: false,
|
|
@@ -2636,7 +2829,7 @@ async function runNext(args) {
|
|
|
2636
2829
|
if (format === "json") {
|
|
2637
2830
|
writeJson({
|
|
2638
2831
|
schema_version: result.schemaVersion,
|
|
2639
|
-
cli_contract_version:
|
|
2832
|
+
cli_contract_version: 8,
|
|
2640
2833
|
recommendation_interface_version: 1,
|
|
2641
2834
|
tool_version: TOOL_VERSION,
|
|
2642
2835
|
operation: "dag.next",
|
|
@@ -2650,6 +2843,7 @@ async function runNext(args) {
|
|
|
2650
2843
|
...(result.durationUnit === null ? {} : nextJson(result)),
|
|
2651
2844
|
temporal: snakeJson(result.temporal),
|
|
2652
2845
|
assurance: contract7SnakeJson(result.assurance),
|
|
2846
|
+
acceptance: snakeJson(result.acceptance),
|
|
2653
2847
|
});
|
|
2654
2848
|
}
|
|
2655
2849
|
else {
|
|
@@ -2664,6 +2858,142 @@ async function runNext(args) {
|
|
|
2664
2858
|
}
|
|
2665
2859
|
return ok ? 0 : 1;
|
|
2666
2860
|
}
|
|
2861
|
+
async function runMilestoneAcceptance(action, args) {
|
|
2862
|
+
const operation = `milestone-acceptance.${action}`;
|
|
2863
|
+
const parsed = parseCommandOptions(operation, args);
|
|
2864
|
+
const format = outputFormat(parsed.values.get("format"));
|
|
2865
|
+
const sourceOperand = parsed.positionals[0];
|
|
2866
|
+
if (sourceOperand === undefined)
|
|
2867
|
+
throw new UsageError(`${operation} requires <file>`);
|
|
2868
|
+
const input = await readDocument(sourceOperand);
|
|
2869
|
+
if (action === "show") {
|
|
2870
|
+
if (parsed.positionals.length !== 1)
|
|
2871
|
+
throw new UsageError("milestone acceptance show requires exactly one <file>");
|
|
2872
|
+
const result = checkDocument(input.text).acceptance ?? showMilestoneAcceptance(input.text, []);
|
|
2873
|
+
if (format === "json")
|
|
2874
|
+
writeJson({ schema_version: "Perttool.MilestoneAcceptanceResult.v1", cli_contract_version: 8, tool_version: TOOL_VERSION, operation, ok: result.ok, milestones: snakeJson(result.milestones), diagnostics: snakeJson(result.diagnostics) });
|
|
2875
|
+
else
|
|
2876
|
+
process.stdout.write(`${result.milestones.map(({ milestoneId, closure, acceptance }) => `${milestoneId} closure=${closure} acceptance=${acceptance}`).join("\n")}\n`);
|
|
2877
|
+
return result.ok ? 0 : 1;
|
|
2878
|
+
}
|
|
2879
|
+
if (parsed.positionals.length !== 4)
|
|
2880
|
+
throw new UsageError(`${operation} requires four operands`);
|
|
2881
|
+
const request = editingWriteRequest(parsed, sourceOperand);
|
|
2882
|
+
if (request.mode === "out")
|
|
2883
|
+
throw new UsageError(`${operation} does not support --out in Contract 8`);
|
|
2884
|
+
const governance = governanceRequest(parsed, request);
|
|
2885
|
+
let result;
|
|
2886
|
+
if (action === "replace") {
|
|
2887
|
+
const criteria = (parsed.repeatedValues.get("criterion") ?? []).map((value) => {
|
|
2888
|
+
const [criterionId, requiredText, evidenceKind, ...description] = value.split(":");
|
|
2889
|
+
if (criterionId === undefined || !["required", "optional"].includes(requiredText ?? "") || !["test", "command", "artifact", "observation", "owner"].includes(evidenceKind ?? "") || description.length === 0)
|
|
2890
|
+
throw new UsageError("--criterion must be ID:required|optional:kind:description");
|
|
2891
|
+
return { criterionId, required: requiredText === "required", evidenceKind: evidenceKind, description: description.join(":") };
|
|
2892
|
+
});
|
|
2893
|
+
result = planCriterionSetReplacement(input.text, { milestoneId: parsed.positionals[1], setId: parsed.positionals[2], revisionId: parsed.positionals[3], criteria }, { governance });
|
|
2894
|
+
}
|
|
2895
|
+
else {
|
|
2896
|
+
result = planAcceptanceReceiptMutation(input.text, {
|
|
2897
|
+
setId: parsed.positionals[1], criterionId: parsed.positionals[2], receiptId: parsed.positionals[3], action: action,
|
|
2898
|
+
...(parsed.values.get("evidence-kind") === undefined ? {} : { evidenceKind: parsed.values.get("evidence-kind") }),
|
|
2899
|
+
...(parsed.values.get("evidence-reference") === undefined ? {} : { evidenceReference: parsed.values.get("evidence-reference") }),
|
|
2900
|
+
...(parsed.values.get("evidence-revision") === undefined ? {} : { evidenceRevision: parsed.values.get("evidence-revision") }),
|
|
2901
|
+
...(parsed.values.get("verifier") === undefined ? {} : { verifier: parsed.values.get("verifier") }),
|
|
2902
|
+
...(parsed.values.get("occurred-at") === undefined ? {} : { occurredAt: parsed.values.get("occurred-at") }),
|
|
2903
|
+
...(parsed.values.get("reason") === undefined ? {} : { reason: parsed.values.get("reason") }),
|
|
2904
|
+
...(parsed.values.get("revokes") === undefined ? {} : { revokes: parsed.values.get("revokes") }),
|
|
2905
|
+
}, { governance });
|
|
2906
|
+
}
|
|
2907
|
+
let written = false;
|
|
2908
|
+
if (result.ok && request.mode === "in_place" && result.changed) {
|
|
2909
|
+
await persistMilestoneAcceptanceMutation(sourceOperand, result, request.expectedDigest);
|
|
2910
|
+
written = true;
|
|
2911
|
+
}
|
|
2912
|
+
if (format === "json")
|
|
2913
|
+
writeJson({
|
|
2914
|
+
schema_version: "Perttool.MutationResult.v5",
|
|
2915
|
+
cli_contract_version: 8,
|
|
2916
|
+
tool_version: TOOL_VERSION,
|
|
2917
|
+
operation,
|
|
2918
|
+
ok: result.ok,
|
|
2919
|
+
document_id: /^project ([A-Za-z][A-Za-z0-9_-]*):$/mu.exec(input.text)?.[1] ?? null,
|
|
2920
|
+
source: sourceOperand,
|
|
2921
|
+
source_digest: input.digest,
|
|
2922
|
+
diagnostics: result.diagnostics.map((code) => jsonDiagnostic({
|
|
2923
|
+
code,
|
|
2924
|
+
severity: code === "PTGOV-103" || code === "PTGOV-104" ? "warning" : "error",
|
|
2925
|
+
message: code,
|
|
2926
|
+
helpTopic: "editing",
|
|
2927
|
+
})),
|
|
2928
|
+
diagnostics_truncated: false,
|
|
2929
|
+
changed: result.changed,
|
|
2930
|
+
original_digest: result.originalDigest,
|
|
2931
|
+
updated_digest: result.updatedDigest,
|
|
2932
|
+
updated_text: result.updatedText,
|
|
2933
|
+
diff: result.updatedText === null ? null : createUnifiedDiff(input.text, result.updatedText, { originalLabel: sourceOperand, updatedLabel: "candidate" }),
|
|
2934
|
+
edits: result.changed && result.updatedText !== null ? [{ start_offset: 0, end_offset: input.text.length, replacement: result.updatedText }] : [],
|
|
2935
|
+
write: { mode: request.mode, target: request.target, written },
|
|
2936
|
+
governance: result.governance === null ? null : {
|
|
2937
|
+
...snakeJson(result.governance),
|
|
2938
|
+
schema_version: "Perttool.GovernanceDecision.v2",
|
|
2939
|
+
governance_interface_version: 2,
|
|
2940
|
+
governance_semantics_version: 2,
|
|
2941
|
+
},
|
|
2942
|
+
lifecycle: null,
|
|
2943
|
+
assurance_impact: null,
|
|
2944
|
+
});
|
|
2945
|
+
else if (result.updatedText !== null)
|
|
2946
|
+
process.stdout.write(result.updatedText);
|
|
2947
|
+
return result.ok ? 0 : 1;
|
|
2948
|
+
}
|
|
2949
|
+
async function runDocumentMigration(args) {
|
|
2950
|
+
const parsed = parseCommandOptions("document.migrate", args);
|
|
2951
|
+
if (parsed.positionals.length !== 1 || parsed.values.get("target-grammar") !== "7")
|
|
2952
|
+
throw new UsageError("document migrate requires <file> --target-grammar 7");
|
|
2953
|
+
const sourceOperand = parsed.positionals[0];
|
|
2954
|
+
if (sourceOperand === "-")
|
|
2955
|
+
throw new UsageError("document migrate requires a repository file");
|
|
2956
|
+
const format = outputFormat(parsed.values.get("format"));
|
|
2957
|
+
const input = await readDocument(sourceOperand);
|
|
2958
|
+
const baseline = await captureAdvanceHistoryBaseline({ targetPath: sourceOperand, expectedSourceDigest: input.digest });
|
|
2959
|
+
const toProof = (value) => value.status === "complete" && value.repositorySnapshotId !== null &&
|
|
2960
|
+
value.repositoryRelativePath !== null && value.objectFormat !== null &&
|
|
2961
|
+
value.headCommitId !== null && value.headBlobId !== null &&
|
|
2962
|
+
value.indexBlobId !== null && value.currentSourceDigest !== null
|
|
2963
|
+
? {
|
|
2964
|
+
repositoryId: value.repositorySnapshotId,
|
|
2965
|
+
repositoryRelativePath: value.repositoryRelativePath,
|
|
2966
|
+
objectFormat: value.objectFormat,
|
|
2967
|
+
headCommit: value.headCommitId,
|
|
2968
|
+
headBlob: value.headBlobId,
|
|
2969
|
+
stage0Blob: value.indexBlobId,
|
|
2970
|
+
sourceDigest: value.currentSourceDigest,
|
|
2971
|
+
}
|
|
2972
|
+
: null;
|
|
2973
|
+
const proof = toProof(baseline);
|
|
2974
|
+
let result = proof === null
|
|
2975
|
+
? { ok: false, modelVersion: 1, changed: false, sourceGrammarVersion: null, targetGrammarVersion: null, sourceDigest: input.digest, candidateDigest: null, grandfatheredMilestoneIds: Object.freeze([]), candidateText: null, diagnostics: Object.freeze(["PTMAC-109"]) }
|
|
2976
|
+
: planMilestoneAcceptanceMigration(input.text, proof);
|
|
2977
|
+
let race = false;
|
|
2978
|
+
if (result.ok && result.changed && result.candidateText !== null && parsed.flags.has("write")) {
|
|
2979
|
+
const current = toProof(await captureAdvanceHistoryBaseline({
|
|
2980
|
+
targetPath: sourceOperand,
|
|
2981
|
+
expectedSourceDigest: input.digest,
|
|
2982
|
+
}));
|
|
2983
|
+
if (proof === null || current === null || !recheckCommittedMigrationProof(proof, current)) {
|
|
2984
|
+
result = Object.freeze({ ...result, ok: false, diagnostics: Object.freeze(["PTMAC-110"]) });
|
|
2985
|
+
race = true;
|
|
2986
|
+
}
|
|
2987
|
+
else {
|
|
2988
|
+
await replaceValidatedDocumentFile(sourceOperand, result.candidateText, { initialDigest: input.digest, ...(parsed.values.get("expect-digest") === undefined ? {} : { expectedDigest: parsed.values.get("expect-digest") }) }, (candidate) => ({ ok: parseMilestoneAcceptanceSource(candidate, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY).ok, diagnostics: [] }));
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
if (format === "json")
|
|
2992
|
+
writeJson({ schema_version: "Perttool.MilestoneAcceptanceMigrationResult.v1", cli_contract_version: 8, tool_version: TOOL_VERSION, operation: "document.migrate", ...snakeJson(result) });
|
|
2993
|
+
else if (result.candidateText !== null)
|
|
2994
|
+
process.stdout.write(result.candidateText);
|
|
2995
|
+
return result.ok ? 0 : race ? 5 : 1;
|
|
2996
|
+
}
|
|
2667
2997
|
function runGuide(args) {
|
|
2668
2998
|
const parsed = parseCommandOptions("guide", args);
|
|
2669
2999
|
if (parsed.positionals.length > 2) {
|
|
@@ -2690,13 +3020,13 @@ function runGuide(args) {
|
|
|
2690
3020
|
}
|
|
2691
3021
|
function runCommandHelp(args) {
|
|
2692
3022
|
const parsed = parseCommandOptions("help", args);
|
|
2693
|
-
if (parsed.positionals.length >
|
|
2694
|
-
throw new UsageError("help accepts at most <resource> <action>");
|
|
3023
|
+
if (parsed.positionals.length > 3) {
|
|
3024
|
+
throw new UsageError("help accepts at most <resource> <group> <action>");
|
|
2695
3025
|
}
|
|
2696
3026
|
const format = outputFormat(parsed.values.get("format"));
|
|
2697
3027
|
const result = getAssuranceCommandDiscovery({
|
|
2698
3028
|
resource: parsed.positionals[0] ?? null,
|
|
2699
|
-
action: parsed.positionals
|
|
3029
|
+
action: parsed.positionals.length < 2 ? null : parsed.positionals.slice(1).join(" "),
|
|
2700
3030
|
});
|
|
2701
3031
|
if (format === "json") {
|
|
2702
3032
|
process.stdout.write(serializeAssuranceCommandHelpResult(result));
|
|
@@ -2770,7 +3100,7 @@ function runAgentHelp(args) {
|
|
|
2770
3100
|
const { schema_version: schemaVersion, ...payload } = projected;
|
|
2771
3101
|
writeJson({
|
|
2772
3102
|
schema_version: schemaVersion,
|
|
2773
|
-
cli_contract_version:
|
|
3103
|
+
cli_contract_version: 8,
|
|
2774
3104
|
...payload,
|
|
2775
3105
|
});
|
|
2776
3106
|
}
|
|
@@ -2974,14 +3304,14 @@ async function runAssuranceMutation(resource, action, args) {
|
|
|
2974
3304
|
});
|
|
2975
3305
|
if (result.ok && writeRequest.mode !== "preview") {
|
|
2976
3306
|
try {
|
|
2977
|
-
writeResult = await
|
|
3307
|
+
writeResult = await persistContract8CandidateResult(result, writeRequest);
|
|
2978
3308
|
}
|
|
2979
3309
|
catch (error) {
|
|
2980
3310
|
return writeFailureExit(error, operation, format === "json");
|
|
2981
3311
|
}
|
|
2982
3312
|
}
|
|
2983
3313
|
if (format === "json") {
|
|
2984
|
-
writeJson(
|
|
3314
|
+
writeJson(contract8MutationResultToJson(result, operation, source, writeResult));
|
|
2985
3315
|
}
|
|
2986
3316
|
else {
|
|
2987
3317
|
if (result.ok) {
|
|
@@ -3021,6 +3351,8 @@ async function dispatchCommand(descriptor, args) {
|
|
|
3021
3351
|
return runCheck(args);
|
|
3022
3352
|
case "document.format":
|
|
3023
3353
|
return runFormat(args);
|
|
3354
|
+
case "document.migrate":
|
|
3355
|
+
return runDocumentMigration(args);
|
|
3024
3356
|
case "agent.help":
|
|
3025
3357
|
return runAgentHelp(args);
|
|
3026
3358
|
case "project.init":
|
|
@@ -3051,6 +3383,14 @@ async function dispatchCommand(descriptor, args) {
|
|
|
3051
3383
|
return runLifecycleMutation("suspend", args);
|
|
3052
3384
|
case "task.resume":
|
|
3053
3385
|
return runLifecycleMutation("resume", args);
|
|
3386
|
+
case "milestone-acceptance.show":
|
|
3387
|
+
case "milestone-acceptance.replace":
|
|
3388
|
+
case "milestone-acceptance.verify":
|
|
3389
|
+
case "milestone-acceptance.fail":
|
|
3390
|
+
case "milestone-acceptance.unavailable":
|
|
3391
|
+
case "milestone-acceptance.revoke":
|
|
3392
|
+
case "milestone-acceptance.waive":
|
|
3393
|
+
return runMilestoneAcceptance(descriptor.path[2], args);
|
|
3054
3394
|
case "plan-assurance.show":
|
|
3055
3395
|
return runPlanAssuranceInspection("show", args);
|
|
3056
3396
|
case "plan-assurance.hash":
|
|
@@ -3069,7 +3409,7 @@ async function dispatchCommand(descriptor, args) {
|
|
|
3069
3409
|
const [resource, action] = descriptor.path;
|
|
3070
3410
|
return runMutation(resource, action, args);
|
|
3071
3411
|
}
|
|
3072
|
-
throw new Error(`no Contract
|
|
3412
|
+
throw new Error(`no Contract 8 handler for ${descriptor.operation}`);
|
|
3073
3413
|
}
|
|
3074
3414
|
function emitCommandUsage(error, json) {
|
|
3075
3415
|
if (json) {
|