perttool 0.4.0 → 0.5.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.
Files changed (246) hide show
  1. package/CHANGELOG.md +63 -1
  2. package/README.md +107 -34
  3. package/dist/actuals/lifecycle.d.ts +101 -0
  4. package/dist/actuals/lifecycle.d.ts.map +1 -0
  5. package/dist/actuals/lifecycle.js +329 -0
  6. package/dist/actuals/lifecycle.js.map +1 -0
  7. package/dist/actuals/source.d.ts +36 -0
  8. package/dist/actuals/source.d.ts.map +1 -0
  9. package/dist/actuals/source.js +119 -0
  10. package/dist/actuals/source.js.map +1 -0
  11. package/dist/analysis/temporal-deadline.d.ts +2 -2
  12. package/dist/analysis/temporal-deadline.d.ts.map +1 -1
  13. package/dist/analysis/temporal-deadline.js.map +1 -1
  14. package/dist/analysis/temporal-precedence.d.ts +2 -2
  15. package/dist/analysis/temporal-precedence.d.ts.map +1 -1
  16. package/dist/analysis/temporal-precedence.js +2 -0
  17. package/dist/analysis/temporal-precedence.js.map +1 -1
  18. package/dist/analysis/temporal-resource.d.ts +2 -2
  19. package/dist/analysis/temporal-resource.d.ts.map +1 -1
  20. package/dist/analysis/temporal-resource.js +2 -0
  21. package/dist/analysis/temporal-resource.js.map +1 -1
  22. package/dist/application/analyze.d.ts +1 -0
  23. package/dist/application/analyze.d.ts.map +1 -1
  24. package/dist/application/analyze.js +38 -29
  25. package/dist/application/analyze.js.map +1 -1
  26. package/dist/application/check.d.ts +3 -0
  27. package/dist/application/check.d.ts.map +1 -1
  28. package/dist/application/check.js +17 -1
  29. package/dist/application/check.js.map +1 -1
  30. package/dist/application/contract6-actuals.d.ts +24 -0
  31. package/dist/application/contract6-actuals.d.ts.map +1 -0
  32. package/dist/application/contract6-actuals.js +51 -0
  33. package/dist/application/contract6-actuals.js.map +1 -0
  34. package/dist/application/contract6-mutation.d.ts +18 -0
  35. package/dist/application/contract6-mutation.d.ts.map +1 -0
  36. package/dist/application/contract6-mutation.js +173 -0
  37. package/dist/application/contract6-mutation.js.map +1 -0
  38. package/dist/application/contract6-projection.d.ts +9 -0
  39. package/dist/application/contract6-projection.d.ts.map +1 -0
  40. package/dist/application/contract6-projection.js +105 -0
  41. package/dist/application/contract6-projection.js.map +1 -0
  42. package/dist/application/init.d.ts +1 -1
  43. package/dist/application/init.js +3 -3
  44. package/dist/application/project.js +2 -2
  45. package/dist/application/target-actuals-advance.d.ts +12 -0
  46. package/dist/application/target-actuals-advance.d.ts.map +1 -0
  47. package/dist/application/target-actuals-advance.js +113 -0
  48. package/dist/application/target-actuals-advance.js.map +1 -0
  49. package/dist/application/target-actuals-analysis.d.ts +76 -0
  50. package/dist/application/target-actuals-analysis.d.ts.map +1 -0
  51. package/dist/application/target-actuals-analysis.js +250 -0
  52. package/dist/application/target-actuals-analysis.js.map +1 -0
  53. package/dist/application/target-actuals-mutation.d.ts +28 -0
  54. package/dist/application/target-actuals-mutation.d.ts.map +1 -0
  55. package/dist/application/target-actuals-mutation.js +404 -0
  56. package/dist/application/target-actuals-mutation.js.map +1 -0
  57. package/dist/application/target-actuals-write.d.ts +7 -0
  58. package/dist/application/target-actuals-write.d.ts.map +1 -0
  59. package/dist/application/target-actuals-write.js +37 -0
  60. package/dist/application/target-actuals-write.js.map +1 -0
  61. package/dist/application/target-governance-init.d.ts +3 -3
  62. package/dist/application/target-governance-init.d.ts.map +1 -1
  63. package/dist/application/target-governance-init.js +20 -10
  64. package/dist/application/target-governance-init.js.map +1 -1
  65. package/dist/application/target-governance-project.d.ts +4 -4
  66. package/dist/application/target-governance-project.d.ts.map +1 -1
  67. package/dist/application/target-governance-project.js +4 -2
  68. package/dist/application/target-governance-project.js.map +1 -1
  69. package/dist/application/target-governance-write.d.ts +8 -0
  70. package/dist/application/target-governance-write.d.ts.map +1 -1
  71. package/dist/application/target-governance-write.js +1 -1
  72. package/dist/application/target-governance-write.js.map +1 -1
  73. package/dist/application/target-mutate.d.ts +3 -1
  74. package/dist/application/target-mutate.d.ts.map +1 -1
  75. package/dist/application/target-mutate.js +34 -2
  76. package/dist/application/target-mutate.js.map +1 -1
  77. package/dist/application/target-project-history.d.ts +18 -0
  78. package/dist/application/target-project-history.d.ts.map +1 -0
  79. package/dist/application/target-project-history.js +279 -0
  80. package/dist/application/target-project-history.js.map +1 -0
  81. package/dist/application/target-temporal-analysis.d.ts +7 -1
  82. package/dist/application/target-temporal-analysis.d.ts.map +1 -1
  83. package/dist/application/target-temporal-analysis.js +10 -8
  84. package/dist/application/target-temporal-analysis.js.map +1 -1
  85. package/dist/application/target-temporal-input.d.ts +6 -4
  86. package/dist/application/target-temporal-input.d.ts.map +1 -1
  87. package/dist/application/target-temporal-input.js +10 -1
  88. package/dist/application/target-temporal-input.js.map +1 -1
  89. package/dist/application/target-unit-migration-candidate.d.ts +2 -2
  90. package/dist/application/target-unit-migration-candidate.d.ts.map +1 -1
  91. package/dist/application/target-unit-migration-candidate.js +21 -10
  92. package/dist/application/target-unit-migration-candidate.js.map +1 -1
  93. package/dist/application/target-unit-migration-request.d.ts +4 -4
  94. package/dist/application/target-unit-migration-request.d.ts.map +1 -1
  95. package/dist/application/target-unit-migration-request.js +6 -4
  96. package/dist/application/target-unit-migration-request.js.map +1 -1
  97. package/dist/application/target-unit-migration-result.d.ts +5 -5
  98. package/dist/application/target-unit-migration-result.d.ts.map +1 -1
  99. package/dist/application/target-unit-migration-result.js +1 -1
  100. package/dist/application/target-unit-migration-result.js.map +1 -1
  101. package/dist/application/target-velocity-observation.d.ts +11 -0
  102. package/dist/application/target-velocity-observation.d.ts.map +1 -0
  103. package/dist/application/target-velocity-observation.js +201 -0
  104. package/dist/application/target-velocity-observation.js.map +1 -0
  105. package/dist/application/unit-migration.d.ts +2 -2
  106. package/dist/application/unit-migration.d.ts.map +1 -1
  107. package/dist/application/unit-migration.js +2 -2
  108. package/dist/cli.js +309 -45
  109. package/dist/cli.js.map +1 -1
  110. package/dist/command/actuals-discovery.d.ts +26 -0
  111. package/dist/command/actuals-discovery.d.ts.map +1 -0
  112. package/dist/command/actuals-discovery.js +328 -0
  113. package/dist/command/actuals-discovery.js.map +1 -0
  114. package/dist/command/actuals-usage.d.ts +22 -0
  115. package/dist/command/actuals-usage.d.ts.map +1 -0
  116. package/dist/command/actuals-usage.js +122 -0
  117. package/dist/command/actuals-usage.js.map +1 -0
  118. package/dist/formatter/source-formatter.d.ts +3 -3
  119. package/dist/formatter/source-formatter.d.ts.map +1 -1
  120. package/dist/formatter/source-formatter.js +53 -5
  121. package/dist/formatter/source-formatter.js.map +1 -1
  122. package/dist/formatter/target-source-formatter.d.ts +2 -1
  123. package/dist/formatter/target-source-formatter.d.ts.map +1 -1
  124. package/dist/formatter/target-source-formatter.js +18 -2
  125. package/dist/formatter/target-source-formatter.js.map +1 -1
  126. package/dist/governance/authority.d.ts +7 -3
  127. package/dist/governance/authority.d.ts.map +1 -1
  128. package/dist/governance/authority.js.map +1 -1
  129. package/dist/governance/source.d.ts +2 -2
  130. package/dist/governance/source.d.ts.map +1 -1
  131. package/dist/governance/source.js.map +1 -1
  132. package/dist/help/actuals-guide.d.ts +10 -0
  133. package/dist/help/actuals-guide.d.ts.map +1 -0
  134. package/dist/help/actuals-guide.js +23 -0
  135. package/dist/help/actuals-guide.js.map +1 -0
  136. package/dist/help/guide.d.ts +1 -1
  137. package/dist/help/guide.d.ts.map +1 -1
  138. package/dist/help/registry.d.ts.map +1 -1
  139. package/dist/help/registry.js +97 -7
  140. package/dist/help/registry.js.map +1 -1
  141. package/dist/history/git-probe.d.ts +56 -0
  142. package/dist/history/git-probe.d.ts.map +1 -0
  143. package/dist/history/git-probe.js +574 -0
  144. package/dist/history/git-probe.js.map +1 -0
  145. package/dist/history/project-history.d.ts +112 -0
  146. package/dist/history/project-history.d.ts.map +1 -0
  147. package/dist/history/project-history.js +786 -0
  148. package/dist/history/project-history.js.map +1 -0
  149. package/dist/history/velocity-observation.d.ts +69 -0
  150. package/dist/history/velocity-observation.d.ts.map +1 -0
  151. package/dist/history/velocity-observation.js +604 -0
  152. package/dist/history/velocity-observation.js.map +1 -0
  153. package/dist/index.d.ts +21 -10
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/index.js +10 -5
  156. package/dist/index.js.map +1 -1
  157. package/dist/io/target-safe-write.d.ts +4 -1
  158. package/dist/io/target-safe-write.d.ts.map +1 -1
  159. package/dist/io/target-safe-write.js +19 -1
  160. package/dist/io/target-safe-write.js.map +1 -1
  161. package/dist/migration/conversion.d.ts +1 -1
  162. package/dist/migration/conversion.d.ts.map +1 -1
  163. package/dist/migration/grammar-boundary.d.ts +1 -1
  164. package/dist/migration/grammar-boundary.d.ts.map +1 -1
  165. package/dist/migration/grammar-boundary.js +11 -3
  166. package/dist/migration/grammar-boundary.js.map +1 -1
  167. package/dist/migration/request.d.ts +5 -5
  168. package/dist/migration/request.d.ts.map +1 -1
  169. package/dist/migration/request.js +15 -2
  170. package/dist/migration/request.js.map +1 -1
  171. package/dist/model/calendar.d.ts +2 -0
  172. package/dist/model/calendar.d.ts.map +1 -1
  173. package/dist/model/calendar.js +19 -0
  174. package/dist/model/calendar.js.map +1 -1
  175. package/dist/model/declaration-fields.d.ts +8 -0
  176. package/dist/model/declaration-fields.d.ts.map +1 -1
  177. package/dist/model/declaration-fields.js +13 -0
  178. package/dist/model/declaration-fields.js.map +1 -1
  179. package/dist/model/exact-person-hours-source.d.ts +2 -0
  180. package/dist/model/exact-person-hours-source.d.ts.map +1 -0
  181. package/dist/model/exact-person-hours-source.js +10 -0
  182. package/dist/model/exact-person-hours-source.js.map +1 -0
  183. package/dist/model/syntax.d.ts +23 -8
  184. package/dist/model/syntax.d.ts.map +1 -1
  185. package/dist/model/syntax.js.map +1 -1
  186. package/dist/mutation/actuals.d.ts +17 -0
  187. package/dist/mutation/actuals.d.ts.map +1 -0
  188. package/dist/mutation/actuals.js +90 -0
  189. package/dist/mutation/actuals.js.map +1 -0
  190. package/dist/mutation/advance.d.ts +9 -3
  191. package/dist/mutation/advance.d.ts.map +1 -1
  192. package/dist/mutation/advance.js +41 -12
  193. package/dist/mutation/advance.js.map +1 -1
  194. package/dist/mutation/entity-editor.d.ts +2 -2
  195. package/dist/mutation/entity-editor.d.ts.map +1 -1
  196. package/dist/mutation/entity-editor.js.map +1 -1
  197. package/dist/mutation/project.d.ts +2 -0
  198. package/dist/mutation/project.d.ts.map +1 -1
  199. package/dist/mutation/project.js +13 -4
  200. package/dist/mutation/project.js.map +1 -1
  201. package/dist/mutation/source.d.ts +3 -3
  202. package/dist/mutation/source.d.ts.map +1 -1
  203. package/dist/mutation/source.js.map +1 -1
  204. package/dist/parser/document-parser.d.ts +8 -1
  205. package/dist/parser/document-parser.d.ts.map +1 -1
  206. package/dist/parser/document-parser.js +151 -23
  207. package/dist/parser/document-parser.js.map +1 -1
  208. package/dist/recommendation/override-types.d.ts +2 -2
  209. package/dist/recommendation/override.d.ts +2 -2
  210. package/dist/recommendation/override.d.ts.map +1 -1
  211. package/dist/recommendation/override.js +2 -2
  212. package/dist/recommendation/override.js.map +1 -1
  213. package/dist/schema/registry.d.ts +36 -0
  214. package/dist/schema/registry.d.ts.map +1 -0
  215. package/dist/schema/registry.js +156 -0
  216. package/dist/schema/registry.js.map +1 -0
  217. package/dist/semantic/target-validator.d.ts +13 -2
  218. package/dist/semantic/target-validator.d.ts.map +1 -1
  219. package/dist/semantic/target-validator.js +46 -2
  220. package/dist/semantic/target-validator.js.map +1 -1
  221. package/dist/semantic/validator.d.ts +4 -1
  222. package/dist/semantic/validator.d.ts.map +1 -1
  223. package/dist/semantic/validator.js +152 -6
  224. package/dist/semantic/validator.js.map +1 -1
  225. package/dist/version.d.ts +1 -1
  226. package/dist/version.js +1 -1
  227. package/package.json +7 -3
  228. package/schemas/Perttool.AgentGuidanceResult.v1.schema.json +152 -0
  229. package/schemas/Perttool.AnalysisResult.v4.schema.json +124 -0
  230. package/schemas/Perttool.CheckResult.v3.schema.json +159 -0
  231. package/schemas/Perttool.CliError.v1.schema.json +83 -0
  232. package/schemas/Perttool.CommandHelpResult.v1.schema.json +165 -0
  233. package/schemas/Perttool.Common.v1.schema.json +508 -0
  234. package/schemas/Perttool.ExportResult.v1.schema.json +96 -0
  235. package/schemas/Perttool.FormatResult.v1.schema.json +82 -0
  236. package/schemas/Perttool.GuideResult.v1.schema.json +104 -0
  237. package/schemas/Perttool.ImportResult.v1.schema.json +111 -0
  238. package/schemas/Perttool.InitResult.v1.schema.json +70 -0
  239. package/schemas/Perttool.MutationResult.v3.schema.json +143 -0
  240. package/schemas/Perttool.NextResult.v5.schema.json +139 -0
  241. package/schemas/Perttool.OverrideDecision.v1.schema.json +170 -0
  242. package/schemas/Perttool.ProjectHistoryResult.v1.schema.json +139 -0
  243. package/schemas/Perttool.ProjectResult.v3.schema.json +144 -0
  244. package/schemas/Perttool.SchemaResult.v1.schema.json +84 -0
  245. package/schemas/Perttool.UnitMigrationResult.v3.schema.json +205 -0
  246. package/schemas/Perttool.VelocityObservationResult.v1.schema.json +102 -0
package/dist/cli.js CHANGED
@@ -2,23 +2,26 @@
2
2
  import { readFile } from "node:fs/promises";
3
3
  import process from "node:process";
4
4
  import { TextDecoder } from "node:util";
5
- import { analyzeDocument, selectNextTasks, } from "./application/contract4.js";
5
+ import { analyzeDocument, selectNextTasks, } from "./application/contract6-actuals.js";
6
6
  import { checkDocument } from "./application/check.js";
7
7
  import { planFormat } from "./application/format.js";
8
8
  import { planProjectInit, projectInitResultToJson, renderProjectInitResult, withProjectInitOutput, } from "./application/init.js";
9
9
  import { planUnitMigration, withUnitMigrationWrite, } from "./application/unit-migration.js";
10
10
  import { getProjectMetadata, } from "./application/project.js";
11
- import { planTargetGovernanceAdvance, planTargetGovernanceBatchMutation, planTargetGovernanceMutation, } from "./application/target-governance-mutation.js";
12
- import { renderTargetGovernanceDecision, renderTargetGovernanceProjectText, targetGovernanceMutationResultToJson, targetGovernanceProjectResultToJson, } from "./application/target-governance-projection.js";
13
- import { persistTargetGovernanceResult, } from "./application/target-governance-write.js";
11
+ import { planAdvance, planBatchMutation, planFinishActuals, planLifecycle, planMutation, } from "./application/contract6-mutation.js";
12
+ import { renderTargetGovernanceDecision, renderTargetGovernanceProjectText, } from "./application/target-governance-projection.js";
13
+ import { contract6MutationResultToJson, contract6ProjectResultToJson, contract6WorkEventToJson, } from "./application/contract6-projection.js";
14
+ import { persistTargetActualsResult, } from "./application/target-actuals-write.js";
15
+ import { inspectTargetProjectHistoryFile, renderTargetProjectHistoryText, targetProjectHistoryResultToJson, } from "./application/target-project-history.js";
16
+ import { observeTargetProjectVelocity, renderTargetVelocityObservationText, targetVelocityObservationResultToJson, } from "./application/target-velocity-observation.js";
14
17
  import { getAgentHelp } from "./application/agent-help.js";
15
18
  import { exportMermaid, } from "./conversion/mermaid.js";
16
19
  import { importMermaid } from "./conversion/mermaid-import.js";
17
- import { getTargetGovernanceGuide, renderTargetGovernanceGuideResult, serializeTargetGovernanceGuideResult, } from "./help/target-governance-guide.js";
20
+ import { getActualsGuide, renderActualsGuideResult, serializeActualsGuideResult, } from "./help/actuals-guide.js";
18
21
  import { commandOptionSets, } from "./command/registry.js";
19
- import { TARGET_GOVERNANCE_COMMAND_REGISTRY, getTargetGovernanceCommandDiscovery, renderTargetGovernanceCommandHelpResult, serializeTargetGovernanceCommandHelpResult, } from "./command/target-governance-discovery.js";
22
+ import { ACTUALS_COMMAND_REGISTRY, getActualsCommandDiscovery, renderActualsCommandHelpResult, serializeActualsCommandHelpResult, } from "./command/actuals-discovery.js";
20
23
  import { handlerCommandUsageError, } from "./command/usage.js";
21
- import { renderTargetGovernanceCommandUsageError, serializeTargetGovernanceCommandUsageError, validateTargetGovernanceCommandInvocation, } from "./command/target-governance-usage.js";
24
+ import { renderActualsCommandUsageError, serializeActualsCommandUsageError, validateActualsCommandInvocation, } from "./command/actuals-usage.js";
22
25
  import { agentGuidanceResultToJson } from "./guidance/projection.js";
23
26
  import { agentGuidanceExitCode, renderAgentGuidanceText, } from "./guidance/text.js";
24
27
  import { documentContentFromBytes, readDocumentFile, } from "./io/document-file.js";
@@ -27,7 +30,8 @@ import { formatDecimal } from "./model/rational.js";
27
30
  import { convertWithVelocity, durationSuffix } from "./model/units.js";
28
31
  import { recommendationInvariantExitCode } from "./recommendation/failure.js";
29
32
  import { recommendationAnalysisToJson } from "./recommendation/json.js";
30
- import { TARGET_GRAMMAR_4_CAPABILITY, } from "./parser/document-parser.js";
33
+ import { TARGET_GRAMMAR_5_CAPABILITY, } from "./parser/document-parser.js";
34
+ import { getJsonSchemaResult, renderJsonSchemaResult, serializeJsonSchemaResult, } from "./schema/registry.js";
31
35
  import { TOOL_VERSION } from "./version.js";
32
36
  class UsageError extends Error {
33
37
  code = "PTCLI-001";
@@ -82,7 +86,7 @@ function parseOptions(args, valueOptions, flagOptions, repeatableOptions = new S
82
86
  return { positionals, values, repeatedValues, flags };
83
87
  }
84
88
  function parseCommandOptions(operation, args) {
85
- const descriptor = TARGET_GOVERNANCE_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
89
+ const descriptor = ACTUALS_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
86
90
  if (descriptor === undefined) {
87
91
  throw new Error(`command descriptor is missing for ${operation}`);
88
92
  }
@@ -220,7 +224,7 @@ function cliError(error, exitCode, operation, json) {
220
224
  if (json) {
221
225
  writeJson({
222
226
  schema_version: "Perttool.CliError.v1",
223
- cli_contract_version: 5,
227
+ cli_contract_version: 6,
224
228
  tool_version: TOOL_VERSION,
225
229
  operation,
226
230
  ok: false,
@@ -255,8 +259,8 @@ async function runCheck(args) {
255
259
  const ok = result.ok && !warningFailure;
256
260
  if (format === "json") {
257
261
  writeJson({
258
- schema_version: "Perttool.CheckResult.v2",
259
- cli_contract_version: 5,
262
+ schema_version: result.schemaVersion,
263
+ cli_contract_version: 6,
260
264
  tool_version: TOOL_VERSION,
261
265
  operation: "document.check",
262
266
  ok,
@@ -268,6 +272,12 @@ async function runCheck(args) {
268
272
  grammar_version: result.grammarVersion,
269
273
  summary: result.summary,
270
274
  temporal_inputs: snakeJson(result.temporalInputs),
275
+ actuals_inputs: result.actualsInputs === null
276
+ ? null
277
+ : {
278
+ model_version: result.actualsInputs.modelVersion,
279
+ events: result.actualsInputs.events.map(contract6WorkEventToJson),
280
+ },
271
281
  });
272
282
  }
273
283
  else {
@@ -306,7 +316,7 @@ async function runProjectShow(args) {
306
316
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
307
317
  const ok = result.ok && !warningFailure;
308
318
  if (format === "json") {
309
- writeJson(targetGovernanceProjectResultToJson(result, source, input.digest, ok));
319
+ writeJson(contract6ProjectResultToJson(result, source, input.digest, ok));
310
320
  }
311
321
  else {
312
322
  if (ok && result.project !== null) {
@@ -484,7 +494,7 @@ async function persistGovernedResult(result, request, sourceOperand) {
484
494
  written: false,
485
495
  });
486
496
  }
487
- return persistTargetGovernanceResult(result, TARGET_GRAMMAR_4_CAPABILITY, request.mode === "in_place"
497
+ return persistTargetActualsResult(result, TARGET_GRAMMAR_5_CAPABILITY, request.mode === "in_place"
488
498
  ? {
489
499
  mode: "in_place",
490
500
  target: request.target,
@@ -576,7 +586,7 @@ async function runFormat(args) {
576
586
  if (format === "json") {
577
587
  writeJson({
578
588
  schema_version: "Perttool.FormatResult.v1",
579
- cli_contract_version: 5,
589
+ cli_contract_version: 6,
580
590
  tool_version: TOOL_VERSION,
581
591
  operation: "document.format",
582
592
  ok,
@@ -620,6 +630,11 @@ function requiredOption(parsed, name) {
620
630
  throw new UsageError(`option --${name} is required`);
621
631
  return value;
622
632
  }
633
+ function exactMeasurementToken(value, suffix) {
634
+ return /^(?:[0-9]+(?:\.[0-9]+)?|[0-9]+\/[1-9][0-9]*)$/.test(value)
635
+ ? `${value}${suffix}`
636
+ : value;
637
+ }
623
638
  function optionalInteger(parsed, name, minimum, maximum) {
624
639
  const raw = parsed.values.get(name);
625
640
  return raw === undefined
@@ -1074,6 +1089,7 @@ async function runMutation(resource, action, args) {
1074
1089
  let sourceOperand;
1075
1090
  let writeRequest;
1076
1091
  let mutation;
1092
+ let lifecycleMutation = null;
1077
1093
  if (resource === "batch") {
1078
1094
  if (parsed.positionals.length !== 1) {
1079
1095
  throw new UsageError("batch apply requires exactly one <file>");
@@ -1108,6 +1124,37 @@ async function runMutation(resource, action, args) {
1108
1124
  : resourceMutationFromOptions(action, parsed);
1109
1125
  sourceOperand = parsed.positionals[0];
1110
1126
  writeRequest = editingWriteRequest(parsed, sourceOperand);
1127
+ if (resource === "task" &&
1128
+ action === "finish" &&
1129
+ parsed.values.has("at")) {
1130
+ lifecycleMutation = {
1131
+ kind: "task.finish.actual",
1132
+ taskId: parsed.positionals[1],
1133
+ event: {
1134
+ occurredAt: parsed.values.get("at"),
1135
+ ...(parsed.values.get("event-id") === undefined
1136
+ ? {}
1137
+ : { id: parsed.values.get("event-id") }),
1138
+ ...(parsed.values.get("active-time") === undefined
1139
+ ? {}
1140
+ : {
1141
+ activeTime: exactMeasurementToken(parsed.values.get("active-time"), "h"),
1142
+ }),
1143
+ ...(parsed.values.get("effort") === undefined
1144
+ ? {}
1145
+ : {
1146
+ effort: exactMeasurementToken(parsed.values.get("effort"), "ph"),
1147
+ }),
1148
+ },
1149
+ };
1150
+ }
1151
+ else if (resource === "task" &&
1152
+ action === "finish" &&
1153
+ (parsed.values.has("event-id") ||
1154
+ parsed.values.has("active-time") ||
1155
+ parsed.values.has("effort"))) {
1156
+ throw new UsageError("--event-id, --active-time, and --effort require --at");
1157
+ }
1111
1158
  }
1112
1159
  const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
1113
1160
  let input;
@@ -1123,9 +1170,11 @@ async function runMutation(resource, action, args) {
1123
1170
  updatedLabel: "candidate",
1124
1171
  governance: governanceRequest(parsed, writeRequest),
1125
1172
  };
1126
- const result = resource === "batch"
1127
- ? planTargetGovernanceBatchMutation(input.text, mutation, TARGET_GRAMMAR_4_CAPABILITY, mutationOptions)
1128
- : planTargetGovernanceMutation(input.text, mutation, TARGET_GRAMMAR_4_CAPABILITY, mutationOptions);
1173
+ const result = lifecycleMutation !== null
1174
+ ? planFinishActuals(input.text, lifecycleMutation, mutationOptions)
1175
+ : resource === "batch"
1176
+ ? planBatchMutation(input.text, mutation, mutationOptions)
1177
+ : planMutation(input.text, mutation, mutationOptions);
1129
1178
  const warningFailure = parsed.flags.has("warnings-as-errors") &&
1130
1179
  (result.diagnosticsTruncated ||
1131
1180
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
@@ -1146,7 +1195,7 @@ async function runMutation(resource, action, args) {
1146
1195
  }
1147
1196
  }
1148
1197
  if (format === "json") {
1149
- writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1198
+ writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1150
1199
  }
1151
1200
  else {
1152
1201
  if (ok) {
@@ -1172,6 +1221,94 @@ async function runMutation(resource, action, args) {
1172
1221
  }
1173
1222
  return ok ? 0 : 1;
1174
1223
  }
1224
+ async function runLifecycleMutation(action, args) {
1225
+ const operation = `task.${action}`;
1226
+ const parsed = parseCommandOptions(operation, args);
1227
+ if (parsed.positionals.length !== 2) {
1228
+ throw new UsageError(`task ${action} requires <file> <task-id>`);
1229
+ }
1230
+ const format = outputFormat(parsed.values.get("format"));
1231
+ const color = colorMode(parsed.values.get("color"), format);
1232
+ const maxDiagnostics = boundedInteger(parsed.values.get("max-diagnostics"), "max-diagnostics", 100, 1, 1000);
1233
+ const sourceOperand = parsed.positionals[0];
1234
+ const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
1235
+ const writeRequest = editingWriteRequest(parsed, sourceOperand);
1236
+ const event = {
1237
+ occurredAt: requiredOption(parsed, "at"),
1238
+ ...(parsed.values.get("event-id") === undefined
1239
+ ? {}
1240
+ : { id: parsed.values.get("event-id") }),
1241
+ ...(action !== "suspend" || parsed.values.get("reason") === undefined
1242
+ ? {}
1243
+ : { reason: parsed.values.get("reason") }),
1244
+ };
1245
+ const mutation = action === "start"
1246
+ ? { kind: "task.start", taskId: parsed.positionals[1], event }
1247
+ : action === "suspend"
1248
+ ? { kind: "task.suspend", taskId: parsed.positionals[1], event }
1249
+ : { kind: "task.resume", taskId: parsed.positionals[1], event };
1250
+ let input;
1251
+ try {
1252
+ input = await readDocument(sourceOperand);
1253
+ }
1254
+ catch (error) {
1255
+ return cliError(error instanceof Error ? error : new Error(String(error)), 3, operation, format === "json");
1256
+ }
1257
+ const result = planLifecycle(input.text, mutation, {
1258
+ maxDiagnostics,
1259
+ originalLabel: source,
1260
+ updatedLabel: "candidate",
1261
+ governance: governanceRequest(parsed, writeRequest),
1262
+ });
1263
+ const warningFailure = parsed.flags.has("warnings-as-errors") &&
1264
+ (result.diagnosticsTruncated ||
1265
+ result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
1266
+ const ok = result.ok && !warningFailure;
1267
+ let writeResult = Object.freeze({
1268
+ mode: writeRequest.mode,
1269
+ target: writeRequest.target,
1270
+ written: false,
1271
+ });
1272
+ if (result.ok && ok && writeRequest.mode !== "preview") {
1273
+ try {
1274
+ writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
1275
+ }
1276
+ catch (error) {
1277
+ return writeFailureExit(error, operation, format === "json");
1278
+ }
1279
+ }
1280
+ if (format === "json") {
1281
+ writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1282
+ }
1283
+ else {
1284
+ if (ok) {
1285
+ if (writeRequest.mode !== "preview") {
1286
+ process.stderr.write(renderGovernanceWriteSummary(operation, writeResult, result.updatedDigest));
1287
+ }
1288
+ else {
1289
+ process.stdout.write(parsed.flags.has("diff")
1290
+ ? (result.diff ?? "")
1291
+ : (result.updatedText ?? ""));
1292
+ if (!parsed.flags.has("diff")) {
1293
+ process.stderr.write(`PREVIEW ${operation} changed=${result.changed} original_digest=${result.originalDigest} updated_digest=${result.updatedDigest}\n`);
1294
+ }
1295
+ }
1296
+ }
1297
+ if (result.lifecycle !== null) {
1298
+ process.stderr.write(`LIFECYCLE task=${result.lifecycle.taskId} from=${result.lifecycle.fromState} to=${result.lifecycle.toState} event=${result.lifecycle.event.id} coverage=${result.lifecycle.coverage}\n`);
1299
+ }
1300
+ if (result.governance !== null) {
1301
+ process.stderr.write(renderTargetGovernanceDecision(result.governance));
1302
+ }
1303
+ for (const diagnostic of result.diagnostics) {
1304
+ process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
1305
+ }
1306
+ if (result.diagnosticsTruncated) {
1307
+ process.stderr.write(`DIAGNOSTICS_TRUNCATED true limit=${maxDiagnostics}\n`);
1308
+ }
1309
+ }
1310
+ return ok ? 0 : 1;
1311
+ }
1175
1312
  function unitMigrationJson(result, source, sourceDigest, ok) {
1176
1313
  const exact = (value) => ({
1177
1314
  numerator: value.numerator.toString(),
@@ -1180,7 +1317,7 @@ function unitMigrationJson(result, source, sourceDigest, ok) {
1180
1317
  });
1181
1318
  return {
1182
1319
  schema_version: result.schemaVersion,
1183
- cli_contract_version: 5,
1320
+ cli_contract_version: 6,
1184
1321
  tool_version: TOOL_VERSION,
1185
1322
  operation: "project.migrate-unit",
1186
1323
  ok,
@@ -1308,10 +1445,90 @@ async function runUnitMigration(args) {
1308
1445
  }
1309
1446
  return ok ? 0 : 1;
1310
1447
  }
1448
+ async function readHistoryForCommand(operation, parsed, format) {
1449
+ if (parsed.positionals.length !== 1) {
1450
+ throw new UsageError(`${operation.replace(".", " ")} requires exactly one <file>`);
1451
+ }
1452
+ const source = parsed.positionals[0];
1453
+ if (source === "-") {
1454
+ throw new UsageError(`${operation.replace(".", " ")} requires an on-disk file`);
1455
+ }
1456
+ try {
1457
+ return await inspectTargetProjectHistoryFile({
1458
+ targetPath: source,
1459
+ ...(parsed.values.get("rev") === undefined
1460
+ ? {}
1461
+ : { revision: parsed.values.get("rev") }),
1462
+ ...(parsed.repeatedValues.get("task") === undefined
1463
+ ? {}
1464
+ : { taskIds: parsed.repeatedValues.get("task") }),
1465
+ }, TARGET_GRAMMAR_5_CAPABILITY);
1466
+ }
1467
+ catch (error) {
1468
+ return error instanceof Error ? error : new Error(String(error));
1469
+ }
1470
+ }
1471
+ async function runProjectHistory(args) {
1472
+ const parsed = parseCommandOptions("project.history", args);
1473
+ const format = outputFormat(parsed.values.get("format"));
1474
+ const color = colorMode(parsed.values.get("color"), format);
1475
+ const result = await readHistoryForCommand("project.history", parsed, format);
1476
+ if (result instanceof Error) {
1477
+ return cliError(result, 3, "project.history", format === "json");
1478
+ }
1479
+ const warningFailure = parsed.flags.has("warnings-as-errors") &&
1480
+ result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
1481
+ const ok = result.ok && !warningFailure;
1482
+ if (format === "json") {
1483
+ writeJson(targetProjectHistoryResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), parsed.positionals[0]));
1484
+ }
1485
+ else {
1486
+ if (ok)
1487
+ process.stdout.write(renderTargetProjectHistoryText(result));
1488
+ for (const diagnostic of result.diagnostics) {
1489
+ process.stderr.write(`${renderDiagnostic(diagnostic, parsed.positionals[0], color)}\n`);
1490
+ }
1491
+ }
1492
+ return ok ? 0 : 1;
1493
+ }
1494
+ async function runProjectVelocityObservation(args) {
1495
+ const parsed = parseCommandOptions("project.observe-velocity", args);
1496
+ const format = outputFormat(parsed.values.get("format"));
1497
+ const color = colorMode(parsed.values.get("color"), format);
1498
+ const history = await readHistoryForCommand("project.observe-velocity", parsed, format);
1499
+ if (history instanceof Error) {
1500
+ return cliError(history, 3, "project.observe-velocity", format === "json");
1501
+ }
1502
+ const evidenceValue = parsed.values.get("evidence") ?? "declared";
1503
+ const evidence = evidenceValue === "git-recorded"
1504
+ ? "git_recorded"
1505
+ : evidenceValue;
1506
+ const result = observeTargetProjectVelocity(history, {
1507
+ ...(parsed.repeatedValues.get("task") === undefined
1508
+ ? {}
1509
+ : { taskIds: parsed.repeatedValues.get("task") }),
1510
+ evidence,
1511
+ });
1512
+ const warningFailure = parsed.flags.has("warnings-as-errors") &&
1513
+ result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
1514
+ const ok = result.ok && !warningFailure;
1515
+ if (format === "json") {
1516
+ writeJson(targetVelocityObservationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), parsed.positionals[0]));
1517
+ }
1518
+ else {
1519
+ if (ok) {
1520
+ process.stdout.write(renderTargetVelocityObservationText(result));
1521
+ }
1522
+ for (const diagnostic of result.diagnostics) {
1523
+ process.stderr.write(`${renderDiagnostic(diagnostic, parsed.positionals[0], color)}\n`);
1524
+ }
1525
+ }
1526
+ return ok ? 0 : 1;
1527
+ }
1311
1528
  function renderAdvanceSummary(details) {
1312
1529
  const list = (ids) => ids.join(",") || "-";
1313
1530
  return [
1314
- `ADVANCE removed_tasks=${list(details.removedTaskIds)} removed_gates=${list(details.removedGateIds)} removed_milestones=${list(details.removedMilestoneIds)}`,
1531
+ `ADVANCE removed_tasks=${list(details.removedTaskIds)} removed_gates=${list(details.removedGateIds)} removed_milestones=${list(details.removedMilestoneIds)} removed_work_events=${list("removedWorkEventIds" in details ? details.removedWorkEventIds : [])}`,
1315
1532
  `ADVANCE frontier_before=${list(details.frontierBefore)} frontier_after=${list(details.frontierAfter)} ready_before=${list(details.readyBefore)} ready_after=${list(details.readyAfter)}`,
1316
1533
  "",
1317
1534
  ].join("\n");
@@ -1334,7 +1551,7 @@ async function runAdvance(args) {
1334
1551
  catch (error) {
1335
1552
  return cliError(error instanceof Error ? error : new Error(String(error)), 3, "dag.advance", format === "json");
1336
1553
  }
1337
- const result = planTargetGovernanceAdvance(input.text, TARGET_GRAMMAR_4_CAPABILITY, {
1554
+ const result = planAdvance(input.text, {
1338
1555
  maxDiagnostics,
1339
1556
  originalLabel: source,
1340
1557
  updatedLabel: "candidate",
@@ -1360,7 +1577,7 @@ async function runAdvance(args) {
1360
1577
  }
1361
1578
  }
1362
1579
  if (format === "json") {
1363
- writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
1580
+ writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
1364
1581
  }
1365
1582
  else {
1366
1583
  if (ok && result.advance !== null) {
@@ -1407,6 +1624,8 @@ function precedenceJson(result, unit, precision) {
1407
1624
  makespan: rationalJson(result.makespan, unit, precision),
1408
1625
  conditional_on_blocks_resolved: result.conditionalOnBlocksResolved,
1409
1626
  blocked_task_ids: result.blockedTaskIds,
1627
+ conditional_on_suspensions_resumed: result.conditionalOnSuspensionsResumed,
1628
+ suspended_task_ids: result.suspendedTaskIds,
1410
1629
  milestones: result.milestones.map((milestone) => ({
1411
1630
  id: milestone.id,
1412
1631
  earliest: rationalJson(milestone.earliest, unit, precision),
@@ -1458,6 +1677,8 @@ function resourceJson(result, unit, precision) {
1458
1677
  algorithm: result.algorithm,
1459
1678
  conditional_on_blocks_resolved: result.conditionalOnBlocksResolved,
1460
1679
  blocked_task_ids: result.blockedTaskIds,
1680
+ conditional_on_suspensions_resumed: result.conditionalOnSuspensionsResumed,
1681
+ suspended_task_ids: result.suspendedTaskIds,
1461
1682
  capacities: result.capacities.map((capacity) => ({
1462
1683
  id: capacity.id,
1463
1684
  declared: capacity.declared,
@@ -1566,11 +1787,14 @@ function renderAnalysisText(result) {
1566
1787
  const conditional = result.precedence?.conditionalOnBlocksResolved === true ||
1567
1788
  result.resource?.conditionalOnBlocksResolved === true;
1568
1789
  const blockedTaskIds = result.precedence?.blockedTaskIds ?? result.resource?.blockedTaskIds ?? [];
1790
+ const suspendedTaskIds = result.precedence?.suspendedTaskIds ??
1791
+ result.resource?.suspendedTaskIds ??
1792
+ [];
1569
1793
  const pathsTruncated = result.precedence?.critical.pathsTruncated === true ||
1570
1794
  result.resource?.scheduleCritical.pathsTruncated === true;
1571
1795
  const overrides = [...result.capacityOverrides]
1572
1796
  .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));
1573
- lines.push(`CONDITIONAL_ON_BLOCKS_RESOLVED ${conditional}`, `BLOCKED_TASKS ${blockedTaskIds.join(", ") || "-"}`, `PATHS_TRUNCATED ${pathsTruncated}`, `CAPACITY_OVERRIDES ${overrides.map(([id, capacity]) => `${id}=${capacity}`).join(", ") || "-"}`, `VELOCITY ${result.velocity === null ? "-" : velocityText(result.velocity, result.precision)}`, `VELOCITY_FORECAST_UNIT ${result.velocityForecast?.targetUnit ?? "-"}`);
1797
+ lines.push(`CONDITIONAL_ON_BLOCKS_RESOLVED ${conditional}`, `BLOCKED_TASKS ${blockedTaskIds.join(", ") || "-"}`, `CONDITIONAL_ON_SUSPENSIONS_RESUMED ${suspendedTaskIds.length > 0}`, `SUSPENDED_TASKS ${suspendedTaskIds.join(", ") || "-"}`, `PATHS_TRUNCATED ${pathsTruncated}`, `CAPACITY_OVERRIDES ${overrides.map(([id, capacity]) => `${id}=${capacity}`).join(", ") || "-"}`, `VELOCITY ${result.velocity === null ? "-" : velocityText(result.velocity, result.precision)}`, `VELOCITY_FORECAST_UNIT ${result.velocityForecast?.targetUnit ?? "-"}`);
1574
1798
  if (result.precedence !== null) {
1575
1799
  const precedence = result.precedence;
1576
1800
  lines.push("", "PRECEDENCE", `MAKESPAN ${durationText(precedence.makespan, unit, result.precision)}`, ...(result.velocityForecast === null
@@ -1646,7 +1870,7 @@ function renderAnalysisText(result) {
1646
1870
  ["TEMPORAL PRECEDENCE", result.temporal.precedence],
1647
1871
  ["TEMPORAL RESOURCE", result.temporal.resource],
1648
1872
  ]) {
1649
- lines.push("", title, `STATE ${projection.state}`, `ALGORITHM ${projection.algorithm === null ? "-" : `${projection.algorithm.id}@${projection.algorithm.version} optimal=${projection.algorithm.optimal}`}`, `CONDITIONAL_ON_BLOCKS_RESOLVED ${projection.conditionalOnBlocksResolved}`, `BLOCKED_TASKS ${projection.blockedTaskIds.join(",") || "-"}`);
1873
+ lines.push("", title, `STATE ${projection.state}`, `ALGORITHM ${projection.algorithm === null ? "-" : `${projection.algorithm.id}@${projection.algorithm.version} optimal=${projection.algorithm.optimal}`}`, `CONDITIONAL_ON_BLOCKS_RESOLVED ${projection.conditionalOnBlocksResolved}`, `BLOCKED_TASKS ${projection.blockedTaskIds.join(",") || "-"}`, `CONDITIONAL_ON_SUSPENSIONS_RESUMED ${projection.conditionalOnSuspensionsResumed}`, `SUSPENDED_TASKS ${projection.suspendedTaskIds.join(",") || "-"}`);
1650
1874
  for (const task of projection.tasks) {
1651
1875
  lines.push(`${task.taskId} START ${temporalPoint(task.start)} FINISH ${temporalPoint(task.finish)}`);
1652
1876
  }
@@ -1701,8 +1925,8 @@ async function runAnalyze(args) {
1701
1925
  const ok = result.ok && !warningFailure;
1702
1926
  if (format === "json") {
1703
1927
  writeJson({
1704
- schema_version: "Perttool.AnalysisResult.v3",
1705
- cli_contract_version: 5,
1928
+ schema_version: "Perttool.AnalysisResult.v4",
1929
+ cli_contract_version: 6,
1706
1930
  tool_version: TOOL_VERSION,
1707
1931
  operation: "dag.analyze",
1708
1932
  ok,
@@ -1712,6 +1936,11 @@ async function runAnalyze(args) {
1712
1936
  diagnostics: result.diagnostics.map(jsonDiagnostic),
1713
1937
  diagnostics_truncated: result.diagnosticsTruncated,
1714
1938
  grammar_version: result.grammarVersion,
1939
+ task_actuals: result.taskActuals.map((actuals) => ({
1940
+ task_id: actuals.taskId,
1941
+ status: actuals.status,
1942
+ coverage: actuals.coverage,
1943
+ })),
1715
1944
  mode: result.mode,
1716
1945
  precision: result.precision,
1717
1946
  ...(result.durationUnit === null
@@ -1816,7 +2045,7 @@ async function runRender(args) {
1816
2045
  if (format === "json") {
1817
2046
  writeJson({
1818
2047
  schema_version: "Perttool.ExportResult.v1",
1819
- cli_contract_version: 5,
2048
+ cli_contract_version: 6,
1820
2049
  tool_version: TOOL_VERSION,
1821
2050
  operation: "dag.render",
1822
2051
  ok,
@@ -1908,7 +2137,7 @@ async function runImport(args) {
1908
2137
  if (format === "json") {
1909
2138
  writeJson({
1910
2139
  schema_version: "Perttool.ImportResult.v1",
1911
- cli_contract_version: 5,
2140
+ cli_contract_version: 6,
1912
2141
  tool_version: TOOL_VERSION,
1913
2142
  operation: "dag.import",
1914
2143
  ok,
@@ -1999,6 +2228,7 @@ function nextJson(result) {
1999
2228
  runnable_now: result.groups.runnableNow,
2000
2229
  blocked_now: result.groups.blockedNow,
2001
2230
  upcoming: result.groups.upcoming,
2231
+ suspended: result.groups.suspended,
2002
2232
  },
2003
2233
  tasks: result.tasks.map((task) => ({
2004
2234
  id: task.id,
@@ -2171,6 +2401,7 @@ function renderNextText(result) {
2171
2401
  section("RUNNABLE NOW", result.groups.runnableNow);
2172
2402
  section("READY / WAITING RESOURCE", result.groups.ready.filter((id) => !result.groups.runnableNow.includes(id)), "rejection");
2173
2403
  section("BLOCKED NOW", result.groups.blockedNow, "blocked");
2404
+ section("SUSPENDED", result.groups.suspended);
2174
2405
  section("UPCOMING", result.groups.upcoming, "explanation");
2175
2406
  lines.push("", "TEMPORAL CONTEXT");
2176
2407
  for (const temporal of result.temporal.tasks) {
@@ -2215,7 +2446,7 @@ async function runNext(args) {
2215
2446
  if (format === "json") {
2216
2447
  writeJson({
2217
2448
  schema_version: "Perttool.CliError.v1",
2218
- cli_contract_version: 5,
2449
+ cli_contract_version: 6,
2219
2450
  tool_version: TOOL_VERSION,
2220
2451
  operation: "dag.next",
2221
2452
  ok: false,
@@ -2235,8 +2466,8 @@ async function runNext(args) {
2235
2466
  const ok = result.ok && !warningFailure;
2236
2467
  if (format === "json") {
2237
2468
  writeJson({
2238
- schema_version: "Perttool.NextResult.v4",
2239
- cli_contract_version: 5,
2469
+ schema_version: "Perttool.NextResult.v5",
2470
+ cli_contract_version: 6,
2240
2471
  recommendation_interface_version: 1,
2241
2472
  tool_version: TOOL_VERSION,
2242
2473
  operation: "dag.next",
@@ -2272,12 +2503,12 @@ function runGuide(args) {
2272
2503
  colorMode(parsed.values.get("color"), format);
2273
2504
  const topicId = parsed.positionals.length === 0 ? null : parsed.positionals.join(".");
2274
2505
  const level = helpLevel(parsed.values.get("level"), topicId !== null);
2275
- const result = getTargetGovernanceGuide(topicId, level);
2506
+ const result = getActualsGuide(topicId, level);
2276
2507
  if (format === "json") {
2277
- process.stdout.write(serializeTargetGovernanceGuideResult(result));
2508
+ process.stdout.write(serializeActualsGuideResult(result));
2278
2509
  }
2279
2510
  else {
2280
- const rendered = renderTargetGovernanceGuideResult(result);
2511
+ const rendered = renderActualsGuideResult(result);
2281
2512
  if (result.ok) {
2282
2513
  process.stdout.write(rendered);
2283
2514
  }
@@ -2293,15 +2524,36 @@ function runCommandHelp(args) {
2293
2524
  throw new UsageError("help accepts at most <resource> <action>");
2294
2525
  }
2295
2526
  const format = outputFormat(parsed.values.get("format"));
2296
- const result = getTargetGovernanceCommandDiscovery({
2527
+ const result = getActualsCommandDiscovery({
2297
2528
  resource: parsed.positionals[0] ?? null,
2298
2529
  action: parsed.positionals[1] ?? null,
2299
2530
  });
2300
2531
  if (format === "json") {
2301
- process.stdout.write(serializeTargetGovernanceCommandHelpResult(result));
2532
+ process.stdout.write(serializeActualsCommandHelpResult(result));
2533
+ }
2534
+ else {
2535
+ const rendered = renderActualsCommandHelpResult(result);
2536
+ if (result.ok) {
2537
+ process.stdout.write(rendered);
2538
+ }
2539
+ else {
2540
+ process.stderr.write(rendered);
2541
+ }
2542
+ }
2543
+ return result.ok ? 0 : 1;
2544
+ }
2545
+ function runJsonSchema(args) {
2546
+ const parsed = parseCommandOptions("schema", args);
2547
+ if (parsed.positionals.length > 1) {
2548
+ throw new UsageError("schema accepts at most one <schema-id>");
2549
+ }
2550
+ const format = outputFormat(parsed.values.get("format"));
2551
+ const result = getJsonSchemaResult(parsed.positionals[0] ?? null);
2552
+ if (format === "json") {
2553
+ process.stdout.write(serializeJsonSchemaResult(result));
2302
2554
  }
2303
2555
  else {
2304
- const rendered = renderTargetGovernanceCommandHelpResult(result);
2556
+ const rendered = renderJsonSchemaResult(result);
2305
2557
  if (result.ok) {
2306
2558
  process.stdout.write(rendered);
2307
2559
  }
@@ -2331,7 +2583,7 @@ function runAgentHelp(args) {
2331
2583
  const { schema_version: schemaVersion, ...payload } = projected;
2332
2584
  writeJson({
2333
2585
  schema_version: schemaVersion,
2334
- cli_contract_version: 5,
2586
+ cli_contract_version: 6,
2335
2587
  ...payload,
2336
2588
  });
2337
2589
  }
@@ -2357,6 +2609,8 @@ async function dispatchCommand(descriptor, args) {
2357
2609
  switch (descriptor.operation) {
2358
2610
  case "help":
2359
2611
  return runCommandHelp(args);
2612
+ case "schema":
2613
+ return runJsonSchema(args);
2360
2614
  case "guide":
2361
2615
  return runGuide(args);
2362
2616
  case "document.check":
@@ -2369,6 +2623,10 @@ async function dispatchCommand(descriptor, args) {
2369
2623
  return runProjectInit(args);
2370
2624
  case "project.show":
2371
2625
  return runProjectShow(args);
2626
+ case "project.history":
2627
+ return runProjectHistory(args);
2628
+ case "project.observe-velocity":
2629
+ return runProjectVelocityObservation(args);
2372
2630
  case "project.migrate-unit":
2373
2631
  return runUnitMigration(args);
2374
2632
  case "dag.analyze":
@@ -2381,6 +2639,12 @@ async function dispatchCommand(descriptor, args) {
2381
2639
  return runRender(args);
2382
2640
  case "dag.import":
2383
2641
  return runImport(args);
2642
+ case "task.start":
2643
+ return runLifecycleMutation("start", args);
2644
+ case "task.suspend":
2645
+ return runLifecycleMutation("suspend", args);
2646
+ case "task.resume":
2647
+ return runLifecycleMutation("resume", args);
2384
2648
  }
2385
2649
  if (descriptor.path.length === 2
2386
2650
  && (descriptor.operation === "project.set"
@@ -2389,14 +2653,14 @@ async function dispatchCommand(descriptor, args) {
2389
2653
  const [resource, action] = descriptor.path;
2390
2654
  return runMutation(resource, action, args);
2391
2655
  }
2392
- throw new Error(`no Contract 5 handler for ${descriptor.operation}`);
2656
+ throw new Error(`no Contract 6 handler for ${descriptor.operation}`);
2393
2657
  }
2394
2658
  function emitCommandUsage(error, json) {
2395
2659
  if (json) {
2396
- process.stdout.write(serializeTargetGovernanceCommandUsageError(error));
2660
+ process.stdout.write(serializeActualsCommandUsageError(error));
2397
2661
  }
2398
2662
  else {
2399
- process.stderr.write(renderTargetGovernanceCommandUsageError(error));
2663
+ process.stderr.write(renderActualsCommandUsageError(error));
2400
2664
  }
2401
2665
  return 2;
2402
2666
  }
@@ -2408,13 +2672,13 @@ async function main(argv) {
2408
2672
  if (argv.length === 1 && argv[0] === "--help") {
2409
2673
  return runCommandHelp([]);
2410
2674
  }
2411
- const validation = validateTargetGovernanceCommandInvocation(argv);
2675
+ const validation = validateActualsCommandInvocation(argv);
2412
2676
  if (!validation.ok) {
2413
2677
  if (jsonRequested(argv)) {
2414
- process.stdout.write(serializeTargetGovernanceCommandUsageError(validation.error));
2678
+ process.stdout.write(serializeActualsCommandUsageError(validation.error));
2415
2679
  }
2416
2680
  else {
2417
- process.stderr.write(renderTargetGovernanceCommandUsageError(validation.error));
2681
+ process.stderr.write(renderActualsCommandUsageError(validation.error));
2418
2682
  }
2419
2683
  return 2;
2420
2684
  }