perttool 0.9.3 → 0.10.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.
Files changed (233) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +63 -31
  3. package/dist/application/cli-facade.d.ts +33 -8
  4. package/dist/application/cli-facade.d.ts.map +1 -1
  5. package/dist/application/cli-facade.js +1 -2
  6. package/dist/application/cli-facade.js.map +1 -1
  7. package/dist/application/contract9-assurance-mutation.d.ts +35 -0
  8. package/dist/application/contract9-assurance-mutation.d.ts.map +1 -0
  9. package/dist/application/contract9-assurance-mutation.js +146 -0
  10. package/dist/application/contract9-assurance-mutation.js.map +1 -0
  11. package/dist/application/contract9-assurance.d.ts +23 -0
  12. package/dist/application/contract9-assurance.d.ts.map +1 -0
  13. package/dist/application/contract9-assurance.js +114 -0
  14. package/dist/application/contract9-assurance.js.map +1 -0
  15. package/dist/application/contract9-candidate.d.ts +33 -0
  16. package/dist/application/contract9-candidate.d.ts.map +1 -0
  17. package/dist/application/contract9-candidate.js +39 -0
  18. package/dist/application/contract9-candidate.js.map +1 -0
  19. package/dist/application/contract9-format-migration.d.ts +22 -0
  20. package/dist/application/contract9-format-migration.d.ts.map +1 -0
  21. package/dist/application/contract9-format-migration.js +52 -0
  22. package/dist/application/contract9-format-migration.js.map +1 -0
  23. package/dist/application/contract9-mixed-mutation.d.ts +14 -0
  24. package/dist/application/contract9-mixed-mutation.d.ts.map +1 -0
  25. package/dist/application/contract9-mixed-mutation.js +88 -0
  26. package/dist/application/contract9-mixed-mutation.js.map +1 -0
  27. package/dist/application/contract9-project.d.ts +15 -0
  28. package/dist/application/contract9-project.d.ts.map +1 -0
  29. package/dist/application/contract9-project.js +24 -0
  30. package/dist/application/contract9-project.js.map +1 -0
  31. package/dist/application/contract9-projection.d.ts +23 -0
  32. package/dist/application/contract9-projection.d.ts.map +1 -0
  33. package/dist/application/contract9-projection.js +89 -0
  34. package/dist/application/contract9-projection.js.map +1 -0
  35. package/dist/application/contract9-runtime.d.ts +43 -0
  36. package/dist/application/contract9-runtime.d.ts.map +1 -0
  37. package/dist/application/contract9-runtime.js +36 -0
  38. package/dist/application/contract9-runtime.js.map +1 -0
  39. package/dist/application/contract9-temporal-context.d.ts +15 -0
  40. package/dist/application/contract9-temporal-context.d.ts.map +1 -0
  41. package/dist/application/contract9-temporal-context.js +127 -0
  42. package/dist/application/contract9-temporal-context.js.map +1 -0
  43. package/dist/application/contract9-temporal-mutation.d.ts +20 -0
  44. package/dist/application/contract9-temporal-mutation.d.ts.map +1 -0
  45. package/dist/application/contract9-temporal-mutation.js +78 -0
  46. package/dist/application/contract9-temporal-mutation.js.map +1 -0
  47. package/dist/application/contract9-temporal.d.ts +17 -0
  48. package/dist/application/contract9-temporal.d.ts.map +1 -0
  49. package/dist/application/contract9-temporal.js +65 -0
  50. package/dist/application/contract9-temporal.js.map +1 -0
  51. package/dist/application/contract9-write.d.ts +28 -0
  52. package/dist/application/contract9-write.d.ts.map +1 -0
  53. package/dist/application/contract9-write.js +25 -0
  54. package/dist/application/contract9-write.js.map +1 -0
  55. package/dist/application/editor-milestone-acceptance.d.ts +4 -0
  56. package/dist/application/editor-milestone-acceptance.d.ts.map +1 -1
  57. package/dist/application/editor-milestone-acceptance.js +90 -0
  58. package/dist/application/editor-milestone-acceptance.js.map +1 -1
  59. package/dist/application/editor-repair.d.ts +12 -0
  60. package/dist/application/editor-repair.d.ts.map +1 -0
  61. package/dist/application/editor-repair.js +74 -0
  62. package/dist/application/editor-repair.js.map +1 -0
  63. package/dist/application/target-postdue-analysis.d.ts +18 -0
  64. package/dist/application/target-postdue-analysis.d.ts.map +1 -0
  65. package/dist/application/target-postdue-analysis.js +26 -0
  66. package/dist/application/target-postdue-analysis.js.map +1 -0
  67. package/dist/application/target-postdue-check.d.ts +10 -0
  68. package/dist/application/target-postdue-check.d.ts.map +1 -0
  69. package/dist/application/target-postdue-check.js +18 -0
  70. package/dist/application/target-postdue-check.js.map +1 -0
  71. package/dist/application/target-postdue-next.d.ts +10 -0
  72. package/dist/application/target-postdue-next.d.ts.map +1 -0
  73. package/dist/application/target-postdue-next.js +13 -0
  74. package/dist/application/target-postdue-next.js.map +1 -0
  75. package/dist/application/target-postdue-projection.d.ts +11 -0
  76. package/dist/application/target-postdue-projection.d.ts.map +1 -0
  77. package/dist/application/target-postdue-projection.js +17 -0
  78. package/dist/application/target-postdue-projection.js.map +1 -0
  79. package/dist/assurance/canonical.d.ts +3 -3
  80. package/dist/assurance/canonical.d.ts.map +1 -1
  81. package/dist/assurance/canonical.js +19 -6
  82. package/dist/assurance/canonical.js.map +1 -1
  83. package/dist/assurance/evaluate.d.ts.map +1 -1
  84. package/dist/assurance/evaluate.js +10 -2
  85. package/dist/assurance/evaluate.js.map +1 -1
  86. package/dist/assurance/types.d.ts +11 -1
  87. package/dist/assurance/types.d.ts.map +1 -1
  88. package/dist/cli.js +215 -92
  89. package/dist/cli.js.map +1 -1
  90. package/dist/command/contract9-discovery.d.ts +17 -0
  91. package/dist/command/contract9-discovery.d.ts.map +1 -0
  92. package/dist/command/contract9-discovery.js +126 -0
  93. package/dist/command/contract9-discovery.js.map +1 -0
  94. package/dist/command/contract9-usage.d.ts +24 -0
  95. package/dist/command/contract9-usage.d.ts.map +1 -0
  96. package/dist/command/contract9-usage.js +23 -0
  97. package/dist/command/contract9-usage.js.map +1 -0
  98. package/dist/core/index.d.ts +4 -3
  99. package/dist/core/index.d.ts.map +1 -1
  100. package/dist/core/index.js +1 -1
  101. package/dist/editor/repair.d.ts +95 -0
  102. package/dist/editor/repair.d.ts.map +1 -0
  103. package/dist/editor/repair.js +232 -0
  104. package/dist/editor/repair.js.map +1 -0
  105. package/dist/editor/semantic-fingerprint.d.ts +8 -0
  106. package/dist/editor/semantic-fingerprint.d.ts.map +1 -0
  107. package/dist/editor/semantic-fingerprint.js +177 -0
  108. package/dist/editor/semantic-fingerprint.js.map +1 -0
  109. package/dist/help/assurance-guide.js +7 -7
  110. package/dist/help/assurance-guide.js.map +1 -1
  111. package/dist/help/contract9-guide.d.ts +10 -0
  112. package/dist/help/contract9-guide.d.ts.map +1 -0
  113. package/dist/help/contract9-guide.js +32 -0
  114. package/dist/help/contract9-guide.js.map +1 -0
  115. package/dist/help/guide.d.ts +1 -1
  116. package/dist/help/guide.d.ts.map +1 -1
  117. package/dist/index.d.ts +10 -8
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +4 -4
  120. package/dist/index.js.map +1 -1
  121. package/dist/milestone-acceptance/advance.js +1 -1
  122. package/dist/milestone-acceptance/advance.js.map +1 -1
  123. package/dist/mutation/advance.d.ts.map +1 -1
  124. package/dist/mutation/advance.js.map +1 -1
  125. package/dist/perttool-vscode-private-0.0.0-d1578b9.vsix +0 -0
  126. package/dist/recommendation/override-types.d.ts +2 -2
  127. package/dist/recommendation/override.js +2 -2
  128. package/dist/schema/registry.d.ts +1 -1
  129. package/dist/schema/registry.js +8 -8
  130. package/dist/session/document-session.d.ts +23 -0
  131. package/dist/session/document-session.d.ts.map +1 -1
  132. package/dist/session/document-session.js +104 -2
  133. package/dist/session/document-session.js.map +1 -1
  134. package/dist/temporal-schedule/alert-types.d.ts +109 -0
  135. package/dist/temporal-schedule/alert-types.d.ts.map +1 -0
  136. package/dist/temporal-schedule/alert-types.js +2 -0
  137. package/dist/temporal-schedule/alert-types.js.map +1 -0
  138. package/dist/temporal-schedule/alert.d.ts +4 -0
  139. package/dist/temporal-schedule/alert.d.ts.map +1 -0
  140. package/dist/temporal-schedule/alert.js +214 -0
  141. package/dist/temporal-schedule/alert.js.map +1 -0
  142. package/dist/temporal-schedule/calendar-mutation.d.ts +11 -0
  143. package/dist/temporal-schedule/calendar-mutation.d.ts.map +1 -0
  144. package/dist/temporal-schedule/calendar-mutation.js +59 -0
  145. package/dist/temporal-schedule/calendar-mutation.js.map +1 -0
  146. package/dist/temporal-schedule/calendar.d.ts +16 -0
  147. package/dist/temporal-schedule/calendar.d.ts.map +1 -0
  148. package/dist/temporal-schedule/calendar.js +179 -0
  149. package/dist/temporal-schedule/calendar.js.map +1 -0
  150. package/dist/temporal-schedule/constraint-types.d.ts +47 -0
  151. package/dist/temporal-schedule/constraint-types.d.ts.map +1 -0
  152. package/dist/temporal-schedule/constraint-types.js +2 -0
  153. package/dist/temporal-schedule/constraint-types.js.map +1 -0
  154. package/dist/temporal-schedule/constraint.d.ts +7 -0
  155. package/dist/temporal-schedule/constraint.d.ts.map +1 -0
  156. package/dist/temporal-schedule/constraint.js +224 -0
  157. package/dist/temporal-schedule/constraint.js.map +1 -0
  158. package/dist/temporal-schedule/entity-mutation.d.ts +31 -0
  159. package/dist/temporal-schedule/entity-mutation.d.ts.map +1 -0
  160. package/dist/temporal-schedule/entity-mutation.js +107 -0
  161. package/dist/temporal-schedule/entity-mutation.js.map +1 -0
  162. package/dist/temporal-schedule/format.d.ts +9 -0
  163. package/dist/temporal-schedule/format.d.ts.map +1 -0
  164. package/dist/temporal-schedule/format.js +183 -0
  165. package/dist/temporal-schedule/format.js.map +1 -0
  166. package/dist/temporal-schedule/required-types.d.ts +68 -0
  167. package/dist/temporal-schedule/required-types.d.ts.map +1 -0
  168. package/dist/temporal-schedule/required-types.js +2 -0
  169. package/dist/temporal-schedule/required-types.js.map +1 -0
  170. package/dist/temporal-schedule/required.d.ts +5 -0
  171. package/dist/temporal-schedule/required.d.ts.map +1 -0
  172. package/dist/temporal-schedule/required.js +183 -0
  173. package/dist/temporal-schedule/required.js.map +1 -0
  174. package/dist/temporal-schedule/schedule-graph.d.ts +8 -0
  175. package/dist/temporal-schedule/schedule-graph.d.ts.map +1 -0
  176. package/dist/temporal-schedule/schedule-graph.js +33 -0
  177. package/dist/temporal-schedule/schedule-graph.js.map +1 -0
  178. package/dist/temporal-schedule/scheduler-types.d.ts +115 -0
  179. package/dist/temporal-schedule/scheduler-types.d.ts.map +1 -0
  180. package/dist/temporal-schedule/scheduler-types.js +2 -0
  181. package/dist/temporal-schedule/scheduler-types.js.map +1 -0
  182. package/dist/temporal-schedule/scheduler.d.ts +12 -0
  183. package/dist/temporal-schedule/scheduler.d.ts.map +1 -0
  184. package/dist/temporal-schedule/scheduler.js +584 -0
  185. package/dist/temporal-schedule/scheduler.js.map +1 -0
  186. package/dist/temporal-schedule/source-lexical.d.ts +30 -0
  187. package/dist/temporal-schedule/source-lexical.d.ts.map +1 -0
  188. package/dist/temporal-schedule/source-lexical.js +166 -0
  189. package/dist/temporal-schedule/source-lexical.js.map +1 -0
  190. package/dist/temporal-schedule/source-types.d.ts +124 -0
  191. package/dist/temporal-schedule/source-types.d.ts.map +1 -0
  192. package/dist/temporal-schedule/source-types.js +2 -0
  193. package/dist/temporal-schedule/source-types.js.map +1 -0
  194. package/dist/temporal-schedule/source-values.d.ts +17 -0
  195. package/dist/temporal-schedule/source-values.d.ts.map +1 -0
  196. package/dist/temporal-schedule/source-values.js +138 -0
  197. package/dist/temporal-schedule/source-values.js.map +1 -0
  198. package/dist/temporal-schedule/source.d.ts +17 -0
  199. package/dist/temporal-schedule/source.d.ts.map +1 -0
  200. package/dist/temporal-schedule/source.js +520 -0
  201. package/dist/temporal-schedule/source.js.map +1 -0
  202. package/dist/temporal-schedule/tzdb-2026c.d.ts +7 -0
  203. package/dist/temporal-schedule/tzdb-2026c.d.ts.map +1 -0
  204. package/dist/temporal-schedule/tzdb-2026c.js +611 -0
  205. package/dist/temporal-schedule/tzdb-2026c.js.map +1 -0
  206. package/dist/version.d.ts +1 -1
  207. package/dist/version.d.ts.map +1 -1
  208. package/dist/version.js +1 -1
  209. package/dist/version.js.map +1 -1
  210. package/package.json +6 -2
  211. package/schemas/Perttool.AdvanceResult.v3.schema.json +1 -1
  212. package/schemas/Perttool.AgentGuidanceResult.v1.schema.json +1 -1
  213. package/schemas/{Perttool.AnalysisResult.v6.schema.json → Perttool.AnalysisResult.v7.schema.json} +178 -6
  214. package/schemas/{Perttool.CheckResult.v5.schema.json → Perttool.CheckResult.v6.schema.json} +10 -6
  215. package/schemas/Perttool.CliError.v1.schema.json +1 -1
  216. package/schemas/Perttool.CommandHelpResult.v1.schema.json +2 -2
  217. package/schemas/Perttool.ExportResult.v1.schema.json +1 -1
  218. package/schemas/Perttool.FormatResult.v1.schema.json +1 -1
  219. package/schemas/Perttool.GuideResult.v1.schema.json +1 -1
  220. package/schemas/Perttool.HistoricalGraphResult.v1.schema.json +1 -1
  221. package/schemas/Perttool.ImportResult.v1.schema.json +1 -1
  222. package/schemas/Perttool.InitResult.v1.schema.json +1 -1
  223. package/schemas/Perttool.MilestoneAcceptanceMigrationResult.v1.schema.json +1 -1
  224. package/schemas/Perttool.MilestoneAcceptanceResult.v1.schema.json +1 -1
  225. package/schemas/{Perttool.MutationResult.v5.schema.json → Perttool.MutationResult.v6.schema.json} +4 -4
  226. package/schemas/{Perttool.NextResult.v7.schema.json → Perttool.NextResult.v8.schema.json} +10 -6
  227. package/schemas/Perttool.OverrideDecision.v1.schema.json +1 -1
  228. package/schemas/{Perttool.PlanAssuranceResult.v1.schema.json → Perttool.PlanAssuranceResult.v2.schema.json} +5 -5
  229. package/schemas/Perttool.ProjectHistoryResult.v1.schema.json +1 -1
  230. package/schemas/{Perttool.ProjectResult.v4.schema.json → Perttool.ProjectResult.v5.schema.json} +70 -7
  231. package/schemas/Perttool.SchemaResult.v1.schema.json +1 -1
  232. package/schemas/{Perttool.UnitMigrationResult.v3.schema.json → Perttool.UnitMigrationResult.v4.schema.json} +5 -5
  233. package/schemas/Perttool.VelocityObservationResult.v1.schema.json +1 -1
package/dist/cli.js CHANGED
@@ -7,14 +7,15 @@ import { createNodeHost } from "./node/host.js";
7
7
  import { createHistoricalGraphGitEvidenceHost } from "./node/historical-host.js";
8
8
  import { exportMermaid, } from "./conversion/mermaid.js";
9
9
  import { importMermaid } from "./conversion/mermaid-import.js";
10
- import { getAssuranceGuide, renderAssuranceGuideResult, serializeAssuranceGuideResult, } from "./help/assurance-guide.js";
10
+ import { getContract9Guide as getAssuranceGuide, renderContract9GuideResult as renderAssuranceGuideResult, serializeContract9GuideResult as serializeAssuranceGuideResult, } from "./help/contract9-guide.js";
11
11
  import { commandOptionSets, } from "./command/registry.js";
12
- import { ASSURANCE_COMMAND_REGISTRY, getAssuranceCommandDiscovery, renderAssuranceCommandHelpResult, serializeAssuranceCommandHelpResult, } from "./command/assurance-discovery.js";
12
+ import { CONTRACT9_COMMAND_REGISTRY as ASSURANCE_COMMAND_REGISTRY, getContract9CommandDiscovery as getAssuranceCommandDiscovery, renderContract9CommandHelpResult as renderAssuranceCommandHelpResult, serializeContract9CommandHelpResult as serializeAssuranceCommandHelpResult, } from "./command/contract9-discovery.js";
13
13
  import { handlerCommandUsageError, } from "./command/usage.js";
14
- import { renderAssuranceCommandUsageError, serializeAssuranceCommandUsageError, validateAssuranceCommandInvocation, } from "./command/assurance-usage.js";
14
+ import { renderContract9CommandUsageError as renderAssuranceCommandUsageError, serializeContract9CommandUsageError as serializeAssuranceCommandUsageError, validateContract9CommandInvocation as validateAssuranceCommandInvocation, } from "./command/contract9-usage.js";
15
15
  import { agentGuidanceResultToJson } from "./guidance/projection.js";
16
16
  import { agentGuidanceExitCode, renderAgentGuidanceText, } from "./guidance/text.js";
17
17
  import { SafeWriteConflictError, SafeWriteVerificationError, } from "./io/safe-write.js";
18
+ import { limitDiagnostics, sortDiagnostics, } from "./model/diagnostics.js";
18
19
  import { formatDecimal } from "./model/rational.js";
19
20
  import { convertWithVelocity, durationSuffix } from "./model/units.js";
20
21
  import { recommendationInvariantExitCode } from "./recommendation/failure.js";
@@ -26,8 +27,13 @@ import { TARGET_GRAMMAR_6_CAPABILITY, } from "./parser/document-parser.js";
26
27
  import { exportPlanAssuranceMermaid, importPlanAssuranceMermaid, } from "./assurance/mermaid.js";
27
28
  import { getJsonSchemaResult, renderJsonSchemaResult, serializeJsonSchemaResult, } from "./schema/registry.js";
28
29
  import { TOOL_VERSION } from "./version.js";
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";
30
+ import { analyzeDocument as analyzeContract8Document, checkDocument as checkContract8Document, selectNextTasks as selectContract8NextTasks, } from "./application/contract9-temporal.js";
31
+ import { contract9CheckResultToJson, contract9ProjectResultToJson, liftContract9AnalysisResultJson, liftContract9NextResultJson, renderContract9ScheduleAlerts, contract9WireJson, } from "./application/contract9-projection.js";
32
+ import { planContract9GrammarMigration } from "./application/contract9-format-migration.js";
33
+ import { planContract9TemporalMutation } from "./application/contract9-temporal-mutation.js";
34
+ import { composeContract9MixedMutation, composeContract9TemporalMutation } from "./application/contract9-mixed-mutation.js";
35
+ import { planAcceptanceReceiptMutation, planCriterionSetReplacement, showMilestoneAcceptance, } from "./milestone-acceptance/mutation.js";
36
+ import { scanTemporalDeclarationBlocks, temporalScheduleBaseText, } from "./temporal-schedule/source-lexical.js";
31
37
  import { planMilestoneAcceptanceMigration, recheckCommittedMigrationProof, } from "./milestone-acceptance/migration.js";
32
38
  import { MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY, milestoneAcceptanceBaseText, parseMilestoneAcceptanceSource } from "./milestone-acceptance/source.js";
33
39
  import { coalesceMilestoneAcceptanceDeletionOverlaps, planMilestoneAcceptanceAdvance, preserveMilestoneAcceptanceRecords, } from "./milestone-acceptance/advance.js";
@@ -35,11 +41,11 @@ const { analyzeDocument: _analyzeContract7Document, checkDocument: _checkContrac
35
41
  const analyzeDocument = analyzeContract8Document;
36
42
  const checkDocument = checkContract8Document;
37
43
  const selectNextTasks = selectContract8NextTasks;
38
- function contract8MutationResultToJson(result, ...args) {
44
+ function contract9MutationResultToJson(result, ...args) {
39
45
  return Object.freeze({
40
46
  ...contract7MutationResultToJson(result, ...args),
41
- schema_version: "Perttool.MutationResult.v5",
42
- cli_contract_version: 8,
47
+ schema_version: "Perttool.MutationResult.v6",
48
+ cli_contract_version: 9,
43
49
  });
44
50
  }
45
51
  class UsageError extends Error {
@@ -215,7 +221,7 @@ async function readStdin() {
215
221
  function writeJson(value) {
216
222
  const contract8Value = typeof value === "object" && value !== null && !Array.isArray(value) &&
217
223
  "cli_contract_version" in value
218
- ? { ...value, cli_contract_version: 8 }
224
+ ? { ...value, cli_contract_version: 9 }
219
225
  : value;
220
226
  process.stdout.write(`${JSON.stringify(contract8Value)}\n`);
221
227
  }
@@ -288,30 +294,7 @@ async function runCheck(args) {
288
294
  const warningFailure = warningsAsErrors && result.summary.warnings > 0;
289
295
  const ok = result.ok && !warningFailure;
290
296
  if (format === "json") {
291
- writeJson({
292
- schema_version: result.schemaVersion,
293
- cli_contract_version: 8,
294
- tool_version: TOOL_VERSION,
295
- operation: "document.check",
296
- ok,
297
- document_id: result.documentId,
298
- source,
299
- source_digest: input.digest,
300
- diagnostics: result.diagnostics.map(jsonDiagnostic),
301
- diagnostics_truncated: result.diagnosticsTruncated,
302
- grammar_version: result.grammarVersion,
303
- summary: result.summary,
304
- temporal_inputs: snakeJson(result.temporalInputs),
305
- actuals_inputs: result.actualsInputs === null
306
- ? null
307
- : {
308
- model_version: result.actualsInputs.modelVersion,
309
- events: result.actualsInputs.events.map(contract6WorkEventToJson),
310
- },
311
- assurance: contract7SnakeJson(result.assurance),
312
- assurance_state_counts: contract7SnakeJson(result.assuranceStateCounts),
313
- acceptance: snakeJson(result.acceptance),
314
- });
297
+ writeJson(contract9CheckResultToJson(result, { source, sourceDigest: input.digest, ok }));
315
298
  }
316
299
  else {
317
300
  if (ok) {
@@ -320,6 +303,7 @@ async function runCheck(args) {
320
303
  for (const diagnostic of result.diagnostics) {
321
304
  process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
322
305
  }
306
+ process.stdout.write(renderContract9ScheduleAlerts(result.scheduleAlerts));
323
307
  if (result.diagnosticsTruncated) {
324
308
  process.stderr.write(`DIAGNOSTICS_TRUNCATED true limit=${maxDiagnostics}\n`);
325
309
  }
@@ -349,7 +333,7 @@ async function runProjectShow(args) {
349
333
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
350
334
  const ok = result.ok && !warningFailure;
351
335
  if (format === "json") {
352
- writeJson(contract7ProjectResultToJson(result, source, input.digest, ok));
336
+ writeJson(contract9ProjectResultToJson(result, { source, sourceDigest: input.digest, ok }));
353
337
  }
354
338
  else {
355
339
  if (ok && result.project !== null) {
@@ -548,10 +532,15 @@ async function persistContract8CandidateResult(result, request) {
548
532
  if (!result.ok || !result.governance?.writeAuthorized || result.updatedText === null) {
549
533
  throw new TypeError("authorized Contract 8 result does not contain a digest-bound candidate");
550
534
  }
551
- const validator = (candidate) => {
552
- const parsed = parseMilestoneAcceptanceSource(candidate, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
553
- return { ok: parsed.ok, diagnostics: [] };
554
- };
535
+ const validator = /^ version 8$/mu.test(result.updatedText)
536
+ ? (candidate) => {
537
+ const checked = checkDocument(candidate);
538
+ return { ok: checked.ok, diagnostics: checked.diagnostics };
539
+ }
540
+ : (candidate) => {
541
+ const parsed = parseMilestoneAcceptanceSource(candidate, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
542
+ return { ok: parsed.ok, diagnostics: [] };
543
+ };
555
544
  if (request.mode === "in_place") {
556
545
  await replaceValidatedDocumentFile(request.target, result.updatedText, {
557
546
  initialDigest: result.originalDigest,
@@ -574,6 +563,20 @@ async function commitCandidate(request, candidateText, initialDigest) {
574
563
  if (candidateText === null) {
575
564
  throw new SafeWriteVerificationError("invalid_candidate", "successful editing result has no candidate text");
576
565
  }
566
+ if (/^ version 8$/mu.test(candidateText)) {
567
+ const validator = (candidate) => {
568
+ const checked = checkDocument(candidate);
569
+ return { ok: checked.ok, diagnostics: checked.diagnostics };
570
+ };
571
+ return request.mode === "in_place"
572
+ ? replaceValidatedDocumentFile(request.target, candidateText, {
573
+ initialDigest,
574
+ ...(request.expectedDigest === undefined
575
+ ? {}
576
+ : { expectedDigest: request.expectedDigest }),
577
+ }, validator)
578
+ : createValidatedDocumentFile(request.target, candidateText, validator);
579
+ }
577
580
  const acceptanceSource = parseMilestoneAcceptanceSource(candidateText, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
578
581
  if (acceptanceSource.grammarVersion === 7) {
579
582
  const validator = (candidate) => {
@@ -613,6 +616,26 @@ function renderWriteSummary(operation, result) {
613
616
  function renderGovernanceWriteSummary(operation, result, digest) {
614
617
  return `WRITE ${operation} mode=${result.mode} target=${result.target ?? "-"} digest=${digest ?? "-"} written=${result.written}\n`;
615
618
  }
619
+ async function runContract9DocumentMigration(args) {
620
+ const parsed = parseCommandOptions("document.migrate", args);
621
+ if (parsed.positionals.length !== 1 || parsed.values.get("target-grammar") !== "8")
622
+ throw new UsageError("document migrate requires <file> --target-grammar 8");
623
+ const sourceOperand = parsed.positionals[0];
624
+ const format = outputFormat(parsed.values.get("format"));
625
+ const input = await readDocument(sourceOperand);
626
+ const result = planContract9GrammarMigration(input.text);
627
+ if (result.ok && result.updatedText !== null && parsed.flags.has("write")) {
628
+ if (sourceOperand === "-")
629
+ throw new UsageError("document migrate --write requires a file");
630
+ await replaceValidatedDocumentFile(sourceOperand, result.updatedText, { initialDigest: input.digest, ...(parsed.values.get("expect-digest") === undefined ? {} : { expectedDigest: parsed.values.get("expect-digest") }) }, (candidate) => ({ ok: checkDocument(candidate).ok, diagnostics: [] }));
631
+ }
632
+ if (format === "json")
633
+ writeJson({ schema_version: "Perttool.UnitMigrationResult.v4", cli_contract_version: 9,
634
+ tool_version: TOOL_VERSION, operation: "document.migrate", ...snakeJson(result) });
635
+ else if (result.updatedText !== null)
636
+ process.stdout.write(parsed.flags.has("diff") ? result.diff ?? "" : result.updatedText);
637
+ return result.ok ? 0 : 1;
638
+ }
616
639
  async function runFormat(args) {
617
640
  const parsed = parseCommandOptions("document.format", args);
618
641
  if (parsed.positionals.length !== 1) {
@@ -656,7 +679,7 @@ async function runFormat(args) {
656
679
  if (format === "json") {
657
680
  writeJson({
658
681
  schema_version: "Perttool.FormatResult.v1",
659
- cli_contract_version: 8,
682
+ cli_contract_version: 9,
660
683
  tool_version: TOOL_VERSION,
661
684
  operation: "document.format",
662
685
  ok,
@@ -1240,11 +1263,21 @@ async function runMutation(resource, action, args) {
1240
1263
  updatedLabel: "candidate",
1241
1264
  governance: governanceRequest(parsed, writeRequest),
1242
1265
  };
1243
- const result = lifecycleMutation !== null
1244
- ? planFinishActuals(input.text, lifecycleMutation, mutationOptions)
1266
+ const legacyPlanner = (text) => lifecycleMutation !== null
1267
+ ? planFinishActuals(text, lifecycleMutation, mutationOptions)
1245
1268
  : resource === "batch"
1246
- ? planBatchMutation(input.text, mutation, mutationOptions)
1247
- : planMutation(input.text, mutation, mutationOptions);
1269
+ ? planBatchMutation(text, mutation, mutationOptions)
1270
+ : planMutation(text, mutation, mutationOptions);
1271
+ const contract9Invocation = validateAssuranceCommandInvocation([resource, action, ...args]);
1272
+ const temporalRequest = contract9Invocation.ok
1273
+ ? planContract9TemporalMutation(input.text, contract9Invocation, { maxDiagnostics })
1274
+ : null;
1275
+ const legacyPreview = legacyPlanner(input.text);
1276
+ const result = temporalRequest === null
1277
+ ? legacyPreview
1278
+ : !legacyPreview.ok
1279
+ ? composeContract9TemporalMutation(input.text, (candidate) => planContract9TemporalMutation(candidate, contract9Invocation, { maxDiagnostics }), { originalLabel: source, updatedLabel: "candidate" })
1280
+ : composeContract9MixedMutation(input.text, (base) => legacyPlanner(base), (candidate) => planContract9TemporalMutation(candidate, contract9Invocation, { maxDiagnostics }), { originalLabel: source, updatedLabel: "candidate" });
1248
1281
  const warningFailure = parsed.flags.has("warnings-as-errors") &&
1249
1282
  (result.diagnosticsTruncated ||
1250
1283
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
@@ -1265,7 +1298,7 @@ async function runMutation(resource, action, args) {
1265
1298
  }
1266
1299
  }
1267
1300
  if (format === "json") {
1268
- writeJson(contract8MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1301
+ writeJson(contract9MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1269
1302
  }
1270
1303
  else {
1271
1304
  if (ok) {
@@ -1348,7 +1381,7 @@ async function runLifecycleMutation(action, args) {
1348
1381
  }
1349
1382
  }
1350
1383
  if (format === "json") {
1351
- writeJson(contract8MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1384
+ writeJson(contract9MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1352
1385
  }
1353
1386
  else {
1354
1387
  if (ok) {
@@ -1387,7 +1420,7 @@ function unitMigrationJson(result, source, sourceDigest, ok) {
1387
1420
  });
1388
1421
  return {
1389
1422
  schema_version: result.schemaVersion,
1390
- cli_contract_version: 8,
1423
+ cli_contract_version: 9,
1391
1424
  tool_version: TOOL_VERSION,
1392
1425
  operation: "project.migrate-unit",
1393
1426
  ok,
@@ -1677,6 +1710,22 @@ function renderAdvanceSummary(details) {
1677
1710
  "",
1678
1711
  ].join("\n");
1679
1712
  }
1713
+ function mergeAdvanceCandidateDiagnostics(candidateDiagnostics, operationDiagnostics, maximum) {
1714
+ const identities = new Set();
1715
+ const unique = [...candidateDiagnostics, ...operationDiagnostics].filter((diagnostic) => {
1716
+ const identity = [
1717
+ diagnostic.code,
1718
+ diagnostic.severity,
1719
+ diagnostic.message,
1720
+ diagnostic.entityId ?? "",
1721
+ ].join("\u0000");
1722
+ if (identities.has(identity))
1723
+ return false;
1724
+ identities.add(identity);
1725
+ return true;
1726
+ });
1727
+ return limitDiagnostics(sortDiagnostics(unique), maximum);
1728
+ }
1680
1729
  function renderAssuranceGuard(guard) {
1681
1730
  const list = (values) => values.join(",") || "-";
1682
1731
  return [
@@ -1768,18 +1817,21 @@ async function runAdvance(args) {
1768
1817
  const combinedEdits = contract7Planned.updatedText === null
1769
1818
  ? contract7Planned.edits
1770
1819
  : normalizeTextEdits(input.text, coalesceMilestoneAcceptanceDeletionOverlaps([
1771
- ...preserveMilestoneAcceptanceRecords(input.text, contract7Planned.edits, acceptancePlan.provisional.advance.stateChangedMilestoneIds),
1820
+ ...preserveMilestoneAcceptanceRecords(input.text, contract7Planned.edits, acceptancePlan.provisional.advance.keptMilestoneIds),
1772
1821
  ...acceptancePlan.provisional.edits,
1773
1822
  ]), "Contract 8 acceptance-aware advance");
1774
1823
  const combinedText = contract7Planned.updatedText === null
1775
1824
  ? null
1776
1825
  : applyTextEdits(input.text, combinedEdits);
1777
- const combinedSource = combinedText === null
1826
+ const combinedCheck = combinedText === null
1778
1827
  ? null
1779
- : parseMilestoneAcceptanceSource(combinedText, MILESTONE_ACCEPTANCE_SOURCE_CAPABILITY);
1780
- if (combinedSource !== null && !combinedSource.ok) {
1781
- throw new Error("acceptance-aware assurance advance lost Grammar 7 validation");
1828
+ : checkContract8Document(combinedText, { maxDiagnostics });
1829
+ if (combinedCheck !== null && !combinedCheck.ok) {
1830
+ throw new Error("acceptance-aware assurance advance lost Contract 8 validation");
1782
1831
  }
1832
+ const combinedDiagnostics = combinedCheck === null
1833
+ ? null
1834
+ : mergeAdvanceCandidateDiagnostics(combinedCheck.diagnostics, contract7Planned.diagnostics, maxDiagnostics);
1783
1835
  const planned = Object.freeze({
1784
1836
  ...contract7Planned,
1785
1837
  schemaVersion: "Perttool.AdvanceResult.v3",
@@ -1791,11 +1843,15 @@ async function runAdvance(args) {
1791
1843
  updatedLabel: "candidate",
1792
1844
  }),
1793
1845
  edits: combinedEdits,
1846
+ diagnostics: combinedDiagnostics?.diagnostics ?? contract7Planned.diagnostics,
1847
+ diagnosticsTruncated: contract7Planned.diagnosticsTruncated ||
1848
+ (combinedCheck?.diagnosticsTruncated ?? false) ||
1849
+ (combinedDiagnostics?.truncated ?? false),
1794
1850
  acceptanceGuard: acceptancePlan.acceptanceGuard,
1795
1851
  });
1796
1852
  const initialWarningFailure = parsed.flags.has("warnings-as-errors") &&
1797
- (planned.diagnosticsTruncated ||
1798
- planned.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
1853
+ (contract7Planned.diagnosticsTruncated ||
1854
+ contract7Planned.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
1799
1855
  const preparedBase = await prepareAdvanceHistory(input.text, planned, {
1800
1856
  mode: writeRequest.mode === "out"
1801
1857
  ? "out"
@@ -2237,8 +2293,8 @@ async function runAnalyze(args) {
2237
2293
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
2238
2294
  const ok = result.ok && !warningFailure;
2239
2295
  if (format === "json") {
2240
- writeJson({
2241
- schema_version: result.schemaVersion,
2296
+ writeJson(liftContract9AnalysisResultJson({
2297
+ schema_version: "Perttool.AnalysisResult.v6",
2242
2298
  cli_contract_version: 8,
2243
2299
  tool_version: TOOL_VERSION,
2244
2300
  operation: "dag.analyze",
@@ -2273,7 +2329,7 @@ async function runAnalyze(args) {
2273
2329
  temporal: snakeJson(result.temporal),
2274
2330
  assurance: contract7SnakeJson(result.assurance),
2275
2331
  acceptance: snakeJson(result.acceptance),
2276
- });
2332
+ }, result));
2277
2333
  }
2278
2334
  else {
2279
2335
  if (ok)
@@ -2809,7 +2865,7 @@ async function runNext(args) {
2809
2865
  if (format === "json") {
2810
2866
  writeJson({
2811
2867
  schema_version: "Perttool.CliError.v1",
2812
- cli_contract_version: 8,
2868
+ cli_contract_version: 9,
2813
2869
  tool_version: TOOL_VERSION,
2814
2870
  operation: "dag.next",
2815
2871
  ok: false,
@@ -2828,8 +2884,8 @@ async function runNext(args) {
2828
2884
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
2829
2885
  const ok = result.ok && !warningFailure;
2830
2886
  if (format === "json") {
2831
- writeJson({
2832
- schema_version: result.schemaVersion,
2887
+ writeJson(liftContract9NextResultJson({
2888
+ schema_version: "Perttool.NextResult.v7",
2833
2889
  cli_contract_version: 8,
2834
2890
  recommendation_interface_version: 1,
2835
2891
  tool_version: TOOL_VERSION,
@@ -2845,7 +2901,7 @@ async function runNext(args) {
2845
2901
  temporal: snakeJson(result.temporal),
2846
2902
  assurance: contract7SnakeJson(result.assurance),
2847
2903
  acceptance: snakeJson(result.acceptance),
2848
- });
2904
+ }, result));
2849
2905
  }
2850
2906
  else {
2851
2907
  if (ok)
@@ -2859,6 +2915,49 @@ async function runNext(args) {
2859
2915
  }
2860
2916
  return ok ? 0 : 1;
2861
2917
  }
2918
+ function parseMilestoneAcceptanceCriteria(values) {
2919
+ return values.map((value) => {
2920
+ const [criterionId, requiredText, evidenceKind, ...description] = value.split(":");
2921
+ if (criterionId === undefined || !["required", "optional"].includes(requiredText ?? "") || !["test", "command", "artifact", "observation", "owner"].includes(evidenceKind ?? "") || description.length === 0)
2922
+ throw new UsageError("--criterion must be ID:required|optional:kind:description");
2923
+ return {
2924
+ criterionId,
2925
+ required: requiredText === "required",
2926
+ evidenceKind: evidenceKind,
2927
+ description: description.join(":"),
2928
+ };
2929
+ });
2930
+ }
2931
+ function planContract9AcceptanceMutation(text, planner) {
2932
+ if (!/^ version 8$/mu.test(text))
2933
+ return planner(text);
2934
+ const base = temporalScheduleBaseText(text, scanTemporalDeclarationBlocks(text));
2935
+ const planned = planner(base);
2936
+ const originalDigest = sha256DigestUtf8(text);
2937
+ if (!planned.ok || planned.updatedText === null) {
2938
+ return Object.freeze({ ...planned, originalDigest });
2939
+ }
2940
+ let prefix = 0;
2941
+ while (prefix < base.length &&
2942
+ prefix < planned.updatedText.length &&
2943
+ base[prefix] === planned.updatedText[prefix])
2944
+ prefix += 1;
2945
+ let suffix = 0;
2946
+ while (suffix < base.length - prefix &&
2947
+ suffix < planned.updatedText.length - prefix &&
2948
+ base[base.length - 1 - suffix] ===
2949
+ planned.updatedText[planned.updatedText.length - 1 - suffix])
2950
+ suffix += 1;
2951
+ const candidate = text.slice(0, prefix) +
2952
+ planned.updatedText.slice(prefix, planned.updatedText.length - suffix) +
2953
+ text.slice(text.length - suffix);
2954
+ const checked = checkDocument(candidate);
2955
+ if (!checked.ok)
2956
+ return Object.freeze({ ...planned, ok: false, changed: false,
2957
+ originalDigest, updatedDigest: null, updatedText: null });
2958
+ return Object.freeze({ ...planned, originalDigest, changed: candidate !== text,
2959
+ updatedDigest: sha256DigestUtf8(candidate), updatedText: candidate });
2960
+ }
2862
2961
  async function runMilestoneAcceptance(action, args) {
2863
2962
  const operation = `milestone-acceptance.${action}`;
2864
2963
  const parsed = parseCommandOptions(operation, args);
@@ -2885,16 +2984,11 @@ async function runMilestoneAcceptance(action, args) {
2885
2984
  const governance = governanceRequest(parsed, request);
2886
2985
  let result;
2887
2986
  if (action === "replace") {
2888
- const criteria = (parsed.repeatedValues.get("criterion") ?? []).map((value) => {
2889
- const [criterionId, requiredText, evidenceKind, ...description] = value.split(":");
2890
- if (criterionId === undefined || !["required", "optional"].includes(requiredText ?? "") || !["test", "command", "artifact", "observation", "owner"].includes(evidenceKind ?? "") || description.length === 0)
2891
- throw new UsageError("--criterion must be ID:required|optional:kind:description");
2892
- return { criterionId, required: requiredText === "required", evidenceKind: evidenceKind, description: description.join(":") };
2893
- });
2894
- result = planCriterionSetReplacement(input.text, { milestoneId: parsed.positionals[1], setId: parsed.positionals[2], revisionId: parsed.positionals[3], criteria }, { governance });
2987
+ const criteria = parseMilestoneAcceptanceCriteria(parsed.repeatedValues.get("criterion") ?? []);
2988
+ result = planContract9AcceptanceMutation(input.text, (text) => planCriterionSetReplacement(text, { milestoneId: parsed.positionals[1], setId: parsed.positionals[2], revisionId: parsed.positionals[3], criteria }, { governance }));
2895
2989
  }
2896
2990
  else {
2897
- result = planAcceptanceReceiptMutation(input.text, {
2991
+ result = planContract9AcceptanceMutation(input.text, (text) => planAcceptanceReceiptMutation(text, {
2898
2992
  setId: parsed.positionals[1], criterionId: parsed.positionals[2], receiptId: parsed.positionals[3], action: action,
2899
2993
  ...(parsed.values.get("evidence-kind") === undefined ? {} : { evidenceKind: parsed.values.get("evidence-kind") }),
2900
2994
  ...(parsed.values.get("evidence-reference") === undefined ? {} : { evidenceReference: parsed.values.get("evidence-reference") }),
@@ -2903,16 +2997,16 @@ async function runMilestoneAcceptance(action, args) {
2903
2997
  ...(parsed.values.get("occurred-at") === undefined ? {} : { occurredAt: parsed.values.get("occurred-at") }),
2904
2998
  ...(parsed.values.get("reason") === undefined ? {} : { reason: parsed.values.get("reason") }),
2905
2999
  ...(parsed.values.get("revokes") === undefined ? {} : { revokes: parsed.values.get("revokes") }),
2906
- }, { governance });
3000
+ }, { governance }));
2907
3001
  }
2908
3002
  let written = false;
2909
3003
  if (result.ok && request.mode === "in_place" && result.changed) {
2910
- await persistMilestoneAcceptanceMutation(sourceOperand, result, request.expectedDigest);
3004
+ await commitCandidate(request, result.updatedText, input.digest);
2911
3005
  written = true;
2912
3006
  }
2913
3007
  if (format === "json")
2914
3008
  writeJson({
2915
- schema_version: "Perttool.MutationResult.v5",
3009
+ schema_version: "Perttool.MutationResult.v6",
2916
3010
  cli_contract_version: 8,
2917
3011
  tool_version: TOOL_VERSION,
2918
3012
  operation,
@@ -2948,39 +3042,36 @@ async function runMilestoneAcceptance(action, args) {
2948
3042
  return result.ok ? 0 : 1;
2949
3043
  }
2950
3044
  async function runDocumentMigration(args) {
3045
+ const target = args.includes("--target-grammar")
3046
+ ? args[args.indexOf("--target-grammar") + 1]
3047
+ : args.find((value) => value.startsWith("--target-grammar="))?.slice("--target-grammar=".length);
3048
+ if (target === "8")
3049
+ return runContract9DocumentMigration(args);
2951
3050
  const parsed = parseCommandOptions("document.migrate", args);
2952
3051
  if (parsed.positionals.length !== 1 || parsed.values.get("target-grammar") !== "7")
2953
- throw new UsageError("document migrate requires <file> --target-grammar 7");
3052
+ throw new UsageError("document migrate requires <file> --target-grammar 8");
2954
3053
  const sourceOperand = parsed.positionals[0];
2955
3054
  if (sourceOperand === "-")
2956
3055
  throw new UsageError("document migrate requires a repository file");
2957
3056
  const format = outputFormat(parsed.values.get("format"));
2958
3057
  const input = await readDocument(sourceOperand);
2959
3058
  const baseline = await captureAdvanceHistoryBaseline({ targetPath: sourceOperand, expectedSourceDigest: input.digest });
2960
- const toProof = (value) => value.status === "complete" && value.repositorySnapshotId !== null &&
2961
- value.repositoryRelativePath !== null && value.objectFormat !== null &&
2962
- value.headCommitId !== null && value.headBlobId !== null &&
3059
+ const toProof = (value) => value.status === "complete" && value.repositorySnapshotId !== null && value.repositoryRelativePath !== null &&
3060
+ value.objectFormat !== null && value.headCommitId !== null && value.headBlobId !== null &&
2963
3061
  value.indexBlobId !== null && value.currentSourceDigest !== null
2964
- ? {
2965
- repositoryId: value.repositorySnapshotId,
2966
- repositoryRelativePath: value.repositoryRelativePath,
2967
- objectFormat: value.objectFormat,
2968
- headCommit: value.headCommitId,
2969
- headBlob: value.headBlobId,
2970
- stage0Blob: value.indexBlobId,
2971
- sourceDigest: value.currentSourceDigest,
2972
- }
3062
+ ? { repositoryId: value.repositorySnapshotId, repositoryRelativePath: value.repositoryRelativePath,
3063
+ objectFormat: value.objectFormat, headCommit: value.headCommitId, headBlob: value.headBlobId,
3064
+ stage0Blob: value.indexBlobId, sourceDigest: value.currentSourceDigest }
2973
3065
  : null;
2974
3066
  const proof = toProof(baseline);
2975
3067
  let result = proof === null
2976
- ? { 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"]) }
3068
+ ? { ok: false, modelVersion: 1, changed: false, sourceGrammarVersion: null, targetGrammarVersion: null,
3069
+ sourceDigest: input.digest, candidateDigest: null, grandfatheredMilestoneIds: Object.freeze([]),
3070
+ candidateText: null, diagnostics: Object.freeze(["PTMAC-109"]) }
2977
3071
  : planMilestoneAcceptanceMigration(input.text, proof);
2978
3072
  let race = false;
2979
3073
  if (result.ok && result.changed && result.candidateText !== null && parsed.flags.has("write")) {
2980
- const current = toProof(await captureAdvanceHistoryBaseline({
2981
- targetPath: sourceOperand,
2982
- expectedSourceDigest: input.digest,
2983
- }));
3074
+ const current = toProof(await captureAdvanceHistoryBaseline({ targetPath: sourceOperand, expectedSourceDigest: input.digest }));
2984
3075
  if (proof === null || current === null || !recheckCommittedMigrationProof(proof, current)) {
2985
3076
  result = Object.freeze({ ...result, ok: false, diagnostics: Object.freeze(["PTMAC-110"]) });
2986
3077
  race = true;
@@ -2990,7 +3081,8 @@ async function runDocumentMigration(args) {
2990
3081
  }
2991
3082
  }
2992
3083
  if (format === "json")
2993
- writeJson({ schema_version: "Perttool.MilestoneAcceptanceMigrationResult.v1", cli_contract_version: 8, tool_version: TOOL_VERSION, operation: "document.migrate", ...snakeJson(result) });
3084
+ writeJson({ schema_version: "Perttool.MilestoneAcceptanceMigrationResult.v1", cli_contract_version: 8,
3085
+ tool_version: TOOL_VERSION, operation: "document.migrate", ...snakeJson(result) });
2994
3086
  else if (result.candidateText !== null)
2995
3087
  process.stdout.write(result.candidateText);
2996
3088
  return result.ok ? 0 : race ? 5 : 1;
@@ -3164,7 +3256,8 @@ async function runPlanAssuranceInspection(action, args) {
3164
3256
  (result.diagnosticsTruncated || result.diagnostics.some(({ severity }) => severity === "warning"));
3165
3257
  const ok = result.ok && !warningFailure;
3166
3258
  if (format === "json") {
3167
- writeJson(contract7InspectionResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), source));
3259
+ writeJson({ ...contract9WireJson(ok ? result : Object.freeze({ ...result, ok: false })),
3260
+ source, cli_contract_version: 9 });
3168
3261
  }
3169
3262
  else if (ok) {
3170
3263
  if (action === "hash") {
@@ -3312,7 +3405,7 @@ async function runAssuranceMutation(resource, action, args) {
3312
3405
  }
3313
3406
  }
3314
3407
  if (format === "json") {
3315
- writeJson(contract8MutationResultToJson(result, operation, source, writeResult));
3408
+ writeJson(contract9MutationResultToJson(result, operation, source, writeResult));
3316
3409
  }
3317
3410
  else {
3318
3411
  if (result.ok) {
@@ -3340,6 +3433,32 @@ async function runAssuranceMutation(resource, action, args) {
3340
3433
  }
3341
3434
  return result.ok ? 0 : 1;
3342
3435
  }
3436
+ async function runCalendarMutation(action, args) {
3437
+ const operation = `calendar.${action}`;
3438
+ const validation = validateAssuranceCommandInvocation(["calendar", action, ...args]);
3439
+ if (!validation.ok)
3440
+ return emitCommandUsage(validation.error, jsonRequested(args));
3441
+ const parsed = parseCommandOptions(operation, args);
3442
+ const format = outputFormat(parsed.values.get("format"));
3443
+ const sourceOperand = parsed.positionals[0];
3444
+ const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
3445
+ const input = await readDocument(sourceOperand);
3446
+ const temporal = (candidate) => planContract9TemporalMutation(candidate, validation);
3447
+ const result = composeContract9TemporalMutation(input.text, temporal, { originalLabel: source, updatedLabel: "candidate" });
3448
+ const writeRequest = editingWriteRequest(parsed, sourceOperand);
3449
+ let writeResult = Object.freeze({ mode: writeRequest.mode, target: writeRequest.target, written: false });
3450
+ if (result.ok && writeRequest.mode !== "preview") {
3451
+ writeResult = await persistContract8CandidateResult(result, writeRequest);
3452
+ }
3453
+ if (format === "json") {
3454
+ writeJson({ ...contract9WireJson(result), operation,
3455
+ source, write: contract9WireJson(writeResult), cli_contract_version: 9 });
3456
+ }
3457
+ else if (result.ok) {
3458
+ process.stdout.write(parsed.flags.has("diff") ? result.diff ?? "" : result.updatedText ?? "");
3459
+ }
3460
+ return result.ok ? 0 : 1;
3461
+ }
3343
3462
  async function dispatchCommand(descriptor, args) {
3344
3463
  switch (descriptor.operation) {
3345
3464
  case "help":
@@ -3378,6 +3497,10 @@ async function dispatchCommand(descriptor, args) {
3378
3497
  return runHistoricalGraph(args);
3379
3498
  case "dag.import":
3380
3499
  return runImport(args);
3500
+ case "calendar.add":
3501
+ case "calendar.set":
3502
+ case "calendar.remove":
3503
+ return runCalendarMutation(descriptor.path[1], args);
3381
3504
  case "task.start":
3382
3505
  return runLifecycleMutation("start", args);
3383
3506
  case "task.suspend":