perttool 0.4.0 → 0.5.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 (223) hide show
  1. package/CHANGELOG.md +44 -1
  2. package/README.md +84 -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 +285 -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 +271 -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 +52 -0
  142. package/dist/history/git-probe.d.ts.map +1 -0
  143. package/dist/history/git-probe.js +565 -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 +19 -10
  154. package/dist/index.d.ts.map +1 -1
  155. package/dist/index.js +9 -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/semantic/target-validator.d.ts +13 -2
  214. package/dist/semantic/target-validator.d.ts.map +1 -1
  215. package/dist/semantic/target-validator.js +46 -2
  216. package/dist/semantic/target-validator.js.map +1 -1
  217. package/dist/semantic/validator.d.ts +4 -1
  218. package/dist/semantic/validator.d.ts.map +1 -1
  219. package/dist/semantic/validator.js +152 -6
  220. package/dist/semantic/validator.js.map +1 -1
  221. package/dist/version.d.ts +1 -1
  222. package/dist/version.js +1 -1
  223. package/package.json +3 -2
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,7 @@ 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";
31
34
  import { TOOL_VERSION } from "./version.js";
32
35
  class UsageError extends Error {
33
36
  code = "PTCLI-001";
@@ -82,7 +85,7 @@ function parseOptions(args, valueOptions, flagOptions, repeatableOptions = new S
82
85
  return { positionals, values, repeatedValues, flags };
83
86
  }
84
87
  function parseCommandOptions(operation, args) {
85
- const descriptor = TARGET_GOVERNANCE_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
88
+ const descriptor = ACTUALS_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
86
89
  if (descriptor === undefined) {
87
90
  throw new Error(`command descriptor is missing for ${operation}`);
88
91
  }
@@ -220,7 +223,7 @@ function cliError(error, exitCode, operation, json) {
220
223
  if (json) {
221
224
  writeJson({
222
225
  schema_version: "Perttool.CliError.v1",
223
- cli_contract_version: 5,
226
+ cli_contract_version: 6,
224
227
  tool_version: TOOL_VERSION,
225
228
  operation,
226
229
  ok: false,
@@ -255,8 +258,8 @@ async function runCheck(args) {
255
258
  const ok = result.ok && !warningFailure;
256
259
  if (format === "json") {
257
260
  writeJson({
258
- schema_version: "Perttool.CheckResult.v2",
259
- cli_contract_version: 5,
261
+ schema_version: result.schemaVersion,
262
+ cli_contract_version: 6,
260
263
  tool_version: TOOL_VERSION,
261
264
  operation: "document.check",
262
265
  ok,
@@ -268,6 +271,12 @@ async function runCheck(args) {
268
271
  grammar_version: result.grammarVersion,
269
272
  summary: result.summary,
270
273
  temporal_inputs: snakeJson(result.temporalInputs),
274
+ actuals_inputs: result.actualsInputs === null
275
+ ? null
276
+ : {
277
+ model_version: result.actualsInputs.modelVersion,
278
+ events: result.actualsInputs.events.map(contract6WorkEventToJson),
279
+ },
271
280
  });
272
281
  }
273
282
  else {
@@ -306,7 +315,7 @@ async function runProjectShow(args) {
306
315
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
307
316
  const ok = result.ok && !warningFailure;
308
317
  if (format === "json") {
309
- writeJson(targetGovernanceProjectResultToJson(result, source, input.digest, ok));
318
+ writeJson(contract6ProjectResultToJson(result, source, input.digest, ok));
310
319
  }
311
320
  else {
312
321
  if (ok && result.project !== null) {
@@ -484,7 +493,7 @@ async function persistGovernedResult(result, request, sourceOperand) {
484
493
  written: false,
485
494
  });
486
495
  }
487
- return persistTargetGovernanceResult(result, TARGET_GRAMMAR_4_CAPABILITY, request.mode === "in_place"
496
+ return persistTargetActualsResult(result, TARGET_GRAMMAR_5_CAPABILITY, request.mode === "in_place"
488
497
  ? {
489
498
  mode: "in_place",
490
499
  target: request.target,
@@ -576,7 +585,7 @@ async function runFormat(args) {
576
585
  if (format === "json") {
577
586
  writeJson({
578
587
  schema_version: "Perttool.FormatResult.v1",
579
- cli_contract_version: 5,
588
+ cli_contract_version: 6,
580
589
  tool_version: TOOL_VERSION,
581
590
  operation: "document.format",
582
591
  ok,
@@ -620,6 +629,11 @@ function requiredOption(parsed, name) {
620
629
  throw new UsageError(`option --${name} is required`);
621
630
  return value;
622
631
  }
632
+ function exactMeasurementToken(value, suffix) {
633
+ return /^(?:[0-9]+(?:\.[0-9]+)?|[0-9]+\/[1-9][0-9]*)$/.test(value)
634
+ ? `${value}${suffix}`
635
+ : value;
636
+ }
623
637
  function optionalInteger(parsed, name, minimum, maximum) {
624
638
  const raw = parsed.values.get(name);
625
639
  return raw === undefined
@@ -1074,6 +1088,7 @@ async function runMutation(resource, action, args) {
1074
1088
  let sourceOperand;
1075
1089
  let writeRequest;
1076
1090
  let mutation;
1091
+ let lifecycleMutation = null;
1077
1092
  if (resource === "batch") {
1078
1093
  if (parsed.positionals.length !== 1) {
1079
1094
  throw new UsageError("batch apply requires exactly one <file>");
@@ -1108,6 +1123,37 @@ async function runMutation(resource, action, args) {
1108
1123
  : resourceMutationFromOptions(action, parsed);
1109
1124
  sourceOperand = parsed.positionals[0];
1110
1125
  writeRequest = editingWriteRequest(parsed, sourceOperand);
1126
+ if (resource === "task" &&
1127
+ action === "finish" &&
1128
+ parsed.values.has("at")) {
1129
+ lifecycleMutation = {
1130
+ kind: "task.finish.actual",
1131
+ taskId: parsed.positionals[1],
1132
+ event: {
1133
+ occurredAt: parsed.values.get("at"),
1134
+ ...(parsed.values.get("event-id") === undefined
1135
+ ? {}
1136
+ : { id: parsed.values.get("event-id") }),
1137
+ ...(parsed.values.get("active-time") === undefined
1138
+ ? {}
1139
+ : {
1140
+ activeTime: exactMeasurementToken(parsed.values.get("active-time"), "h"),
1141
+ }),
1142
+ ...(parsed.values.get("effort") === undefined
1143
+ ? {}
1144
+ : {
1145
+ effort: exactMeasurementToken(parsed.values.get("effort"), "ph"),
1146
+ }),
1147
+ },
1148
+ };
1149
+ }
1150
+ else if (resource === "task" &&
1151
+ action === "finish" &&
1152
+ (parsed.values.has("event-id") ||
1153
+ parsed.values.has("active-time") ||
1154
+ parsed.values.has("effort"))) {
1155
+ throw new UsageError("--event-id, --active-time, and --effort require --at");
1156
+ }
1111
1157
  }
1112
1158
  const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
1113
1159
  let input;
@@ -1123,9 +1169,11 @@ async function runMutation(resource, action, args) {
1123
1169
  updatedLabel: "candidate",
1124
1170
  governance: governanceRequest(parsed, writeRequest),
1125
1171
  };
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);
1172
+ const result = lifecycleMutation !== null
1173
+ ? planFinishActuals(input.text, lifecycleMutation, mutationOptions)
1174
+ : resource === "batch"
1175
+ ? planBatchMutation(input.text, mutation, mutationOptions)
1176
+ : planMutation(input.text, mutation, mutationOptions);
1129
1177
  const warningFailure = parsed.flags.has("warnings-as-errors") &&
1130
1178
  (result.diagnosticsTruncated ||
1131
1179
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
@@ -1146,7 +1194,7 @@ async function runMutation(resource, action, args) {
1146
1194
  }
1147
1195
  }
1148
1196
  if (format === "json") {
1149
- writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1197
+ writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1150
1198
  }
1151
1199
  else {
1152
1200
  if (ok) {
@@ -1172,6 +1220,94 @@ async function runMutation(resource, action, args) {
1172
1220
  }
1173
1221
  return ok ? 0 : 1;
1174
1222
  }
1223
+ async function runLifecycleMutation(action, args) {
1224
+ const operation = `task.${action}`;
1225
+ const parsed = parseCommandOptions(operation, args);
1226
+ if (parsed.positionals.length !== 2) {
1227
+ throw new UsageError(`task ${action} requires <file> <task-id>`);
1228
+ }
1229
+ const format = outputFormat(parsed.values.get("format"));
1230
+ const color = colorMode(parsed.values.get("color"), format);
1231
+ const maxDiagnostics = boundedInteger(parsed.values.get("max-diagnostics"), "max-diagnostics", 100, 1, 1000);
1232
+ const sourceOperand = parsed.positionals[0];
1233
+ const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
1234
+ const writeRequest = editingWriteRequest(parsed, sourceOperand);
1235
+ const event = {
1236
+ occurredAt: requiredOption(parsed, "at"),
1237
+ ...(parsed.values.get("event-id") === undefined
1238
+ ? {}
1239
+ : { id: parsed.values.get("event-id") }),
1240
+ ...(action !== "suspend" || parsed.values.get("reason") === undefined
1241
+ ? {}
1242
+ : { reason: parsed.values.get("reason") }),
1243
+ };
1244
+ const mutation = action === "start"
1245
+ ? { kind: "task.start", taskId: parsed.positionals[1], event }
1246
+ : action === "suspend"
1247
+ ? { kind: "task.suspend", taskId: parsed.positionals[1], event }
1248
+ : { kind: "task.resume", taskId: parsed.positionals[1], event };
1249
+ let input;
1250
+ try {
1251
+ input = await readDocument(sourceOperand);
1252
+ }
1253
+ catch (error) {
1254
+ return cliError(error instanceof Error ? error : new Error(String(error)), 3, operation, format === "json");
1255
+ }
1256
+ const result = planLifecycle(input.text, mutation, {
1257
+ maxDiagnostics,
1258
+ originalLabel: source,
1259
+ updatedLabel: "candidate",
1260
+ governance: governanceRequest(parsed, writeRequest),
1261
+ });
1262
+ const warningFailure = parsed.flags.has("warnings-as-errors") &&
1263
+ (result.diagnosticsTruncated ||
1264
+ result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
1265
+ const ok = result.ok && !warningFailure;
1266
+ let writeResult = Object.freeze({
1267
+ mode: writeRequest.mode,
1268
+ target: writeRequest.target,
1269
+ written: false,
1270
+ });
1271
+ if (result.ok && ok && writeRequest.mode !== "preview") {
1272
+ try {
1273
+ writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
1274
+ }
1275
+ catch (error) {
1276
+ return writeFailureExit(error, operation, format === "json");
1277
+ }
1278
+ }
1279
+ if (format === "json") {
1280
+ writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1281
+ }
1282
+ else {
1283
+ if (ok) {
1284
+ if (writeRequest.mode !== "preview") {
1285
+ process.stderr.write(renderGovernanceWriteSummary(operation, writeResult, result.updatedDigest));
1286
+ }
1287
+ else {
1288
+ process.stdout.write(parsed.flags.has("diff")
1289
+ ? (result.diff ?? "")
1290
+ : (result.updatedText ?? ""));
1291
+ if (!parsed.flags.has("diff")) {
1292
+ process.stderr.write(`PREVIEW ${operation} changed=${result.changed} original_digest=${result.originalDigest} updated_digest=${result.updatedDigest}\n`);
1293
+ }
1294
+ }
1295
+ }
1296
+ if (result.lifecycle !== null) {
1297
+ 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`);
1298
+ }
1299
+ if (result.governance !== null) {
1300
+ process.stderr.write(renderTargetGovernanceDecision(result.governance));
1301
+ }
1302
+ for (const diagnostic of result.diagnostics) {
1303
+ process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
1304
+ }
1305
+ if (result.diagnosticsTruncated) {
1306
+ process.stderr.write(`DIAGNOSTICS_TRUNCATED true limit=${maxDiagnostics}\n`);
1307
+ }
1308
+ }
1309
+ return ok ? 0 : 1;
1310
+ }
1175
1311
  function unitMigrationJson(result, source, sourceDigest, ok) {
1176
1312
  const exact = (value) => ({
1177
1313
  numerator: value.numerator.toString(),
@@ -1180,7 +1316,7 @@ function unitMigrationJson(result, source, sourceDigest, ok) {
1180
1316
  });
1181
1317
  return {
1182
1318
  schema_version: result.schemaVersion,
1183
- cli_contract_version: 5,
1319
+ cli_contract_version: 6,
1184
1320
  tool_version: TOOL_VERSION,
1185
1321
  operation: "project.migrate-unit",
1186
1322
  ok,
@@ -1308,10 +1444,90 @@ async function runUnitMigration(args) {
1308
1444
  }
1309
1445
  return ok ? 0 : 1;
1310
1446
  }
1447
+ async function readHistoryForCommand(operation, parsed, format) {
1448
+ if (parsed.positionals.length !== 1) {
1449
+ throw new UsageError(`${operation.replace(".", " ")} requires exactly one <file>`);
1450
+ }
1451
+ const source = parsed.positionals[0];
1452
+ if (source === "-") {
1453
+ throw new UsageError(`${operation.replace(".", " ")} requires an on-disk file`);
1454
+ }
1455
+ try {
1456
+ return await inspectTargetProjectHistoryFile({
1457
+ targetPath: source,
1458
+ ...(parsed.values.get("rev") === undefined
1459
+ ? {}
1460
+ : { revision: parsed.values.get("rev") }),
1461
+ ...(parsed.repeatedValues.get("task") === undefined
1462
+ ? {}
1463
+ : { taskIds: parsed.repeatedValues.get("task") }),
1464
+ }, TARGET_GRAMMAR_5_CAPABILITY);
1465
+ }
1466
+ catch (error) {
1467
+ return error instanceof Error ? error : new Error(String(error));
1468
+ }
1469
+ }
1470
+ async function runProjectHistory(args) {
1471
+ const parsed = parseCommandOptions("project.history", args);
1472
+ const format = outputFormat(parsed.values.get("format"));
1473
+ const color = colorMode(parsed.values.get("color"), format);
1474
+ const result = await readHistoryForCommand("project.history", parsed, format);
1475
+ if (result instanceof Error) {
1476
+ return cliError(result, 3, "project.history", format === "json");
1477
+ }
1478
+ const warningFailure = parsed.flags.has("warnings-as-errors") &&
1479
+ result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
1480
+ const ok = result.ok && !warningFailure;
1481
+ if (format === "json") {
1482
+ writeJson(targetProjectHistoryResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), parsed.positionals[0]));
1483
+ }
1484
+ else {
1485
+ if (ok)
1486
+ process.stdout.write(renderTargetProjectHistoryText(result));
1487
+ for (const diagnostic of result.diagnostics) {
1488
+ process.stderr.write(`${renderDiagnostic(diagnostic, parsed.positionals[0], color)}\n`);
1489
+ }
1490
+ }
1491
+ return ok ? 0 : 1;
1492
+ }
1493
+ async function runProjectVelocityObservation(args) {
1494
+ const parsed = parseCommandOptions("project.observe-velocity", args);
1495
+ const format = outputFormat(parsed.values.get("format"));
1496
+ const color = colorMode(parsed.values.get("color"), format);
1497
+ const history = await readHistoryForCommand("project.observe-velocity", parsed, format);
1498
+ if (history instanceof Error) {
1499
+ return cliError(history, 3, "project.observe-velocity", format === "json");
1500
+ }
1501
+ const evidenceValue = parsed.values.get("evidence") ?? "declared";
1502
+ const evidence = evidenceValue === "git-recorded"
1503
+ ? "git_recorded"
1504
+ : evidenceValue;
1505
+ const result = observeTargetProjectVelocity(history, {
1506
+ ...(parsed.repeatedValues.get("task") === undefined
1507
+ ? {}
1508
+ : { taskIds: parsed.repeatedValues.get("task") }),
1509
+ evidence,
1510
+ });
1511
+ const warningFailure = parsed.flags.has("warnings-as-errors") &&
1512
+ result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
1513
+ const ok = result.ok && !warningFailure;
1514
+ if (format === "json") {
1515
+ writeJson(targetVelocityObservationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), parsed.positionals[0]));
1516
+ }
1517
+ else {
1518
+ if (ok) {
1519
+ process.stdout.write(renderTargetVelocityObservationText(result));
1520
+ }
1521
+ for (const diagnostic of result.diagnostics) {
1522
+ process.stderr.write(`${renderDiagnostic(diagnostic, parsed.positionals[0], color)}\n`);
1523
+ }
1524
+ }
1525
+ return ok ? 0 : 1;
1526
+ }
1311
1527
  function renderAdvanceSummary(details) {
1312
1528
  const list = (ids) => ids.join(",") || "-";
1313
1529
  return [
1314
- `ADVANCE removed_tasks=${list(details.removedTaskIds)} removed_gates=${list(details.removedGateIds)} removed_milestones=${list(details.removedMilestoneIds)}`,
1530
+ `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
1531
  `ADVANCE frontier_before=${list(details.frontierBefore)} frontier_after=${list(details.frontierAfter)} ready_before=${list(details.readyBefore)} ready_after=${list(details.readyAfter)}`,
1316
1532
  "",
1317
1533
  ].join("\n");
@@ -1334,7 +1550,7 @@ async function runAdvance(args) {
1334
1550
  catch (error) {
1335
1551
  return cliError(error instanceof Error ? error : new Error(String(error)), 3, "dag.advance", format === "json");
1336
1552
  }
1337
- const result = planTargetGovernanceAdvance(input.text, TARGET_GRAMMAR_4_CAPABILITY, {
1553
+ const result = planAdvance(input.text, {
1338
1554
  maxDiagnostics,
1339
1555
  originalLabel: source,
1340
1556
  updatedLabel: "candidate",
@@ -1360,7 +1576,7 @@ async function runAdvance(args) {
1360
1576
  }
1361
1577
  }
1362
1578
  if (format === "json") {
1363
- writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
1579
+ writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
1364
1580
  }
1365
1581
  else {
1366
1582
  if (ok && result.advance !== null) {
@@ -1407,6 +1623,8 @@ function precedenceJson(result, unit, precision) {
1407
1623
  makespan: rationalJson(result.makespan, unit, precision),
1408
1624
  conditional_on_blocks_resolved: result.conditionalOnBlocksResolved,
1409
1625
  blocked_task_ids: result.blockedTaskIds,
1626
+ conditional_on_suspensions_resumed: result.conditionalOnSuspensionsResumed,
1627
+ suspended_task_ids: result.suspendedTaskIds,
1410
1628
  milestones: result.milestones.map((milestone) => ({
1411
1629
  id: milestone.id,
1412
1630
  earliest: rationalJson(milestone.earliest, unit, precision),
@@ -1458,6 +1676,8 @@ function resourceJson(result, unit, precision) {
1458
1676
  algorithm: result.algorithm,
1459
1677
  conditional_on_blocks_resolved: result.conditionalOnBlocksResolved,
1460
1678
  blocked_task_ids: result.blockedTaskIds,
1679
+ conditional_on_suspensions_resumed: result.conditionalOnSuspensionsResumed,
1680
+ suspended_task_ids: result.suspendedTaskIds,
1461
1681
  capacities: result.capacities.map((capacity) => ({
1462
1682
  id: capacity.id,
1463
1683
  declared: capacity.declared,
@@ -1566,11 +1786,14 @@ function renderAnalysisText(result) {
1566
1786
  const conditional = result.precedence?.conditionalOnBlocksResolved === true ||
1567
1787
  result.resource?.conditionalOnBlocksResolved === true;
1568
1788
  const blockedTaskIds = result.precedence?.blockedTaskIds ?? result.resource?.blockedTaskIds ?? [];
1789
+ const suspendedTaskIds = result.precedence?.suspendedTaskIds ??
1790
+ result.resource?.suspendedTaskIds ??
1791
+ [];
1569
1792
  const pathsTruncated = result.precedence?.critical.pathsTruncated === true ||
1570
1793
  result.resource?.scheduleCritical.pathsTruncated === true;
1571
1794
  const overrides = [...result.capacityOverrides]
1572
1795
  .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 ?? "-"}`);
1796
+ 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
1797
  if (result.precedence !== null) {
1575
1798
  const precedence = result.precedence;
1576
1799
  lines.push("", "PRECEDENCE", `MAKESPAN ${durationText(precedence.makespan, unit, result.precision)}`, ...(result.velocityForecast === null
@@ -1646,7 +1869,7 @@ function renderAnalysisText(result) {
1646
1869
  ["TEMPORAL PRECEDENCE", result.temporal.precedence],
1647
1870
  ["TEMPORAL RESOURCE", result.temporal.resource],
1648
1871
  ]) {
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(",") || "-"}`);
1872
+ 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
1873
  for (const task of projection.tasks) {
1651
1874
  lines.push(`${task.taskId} START ${temporalPoint(task.start)} FINISH ${temporalPoint(task.finish)}`);
1652
1875
  }
@@ -1701,8 +1924,8 @@ async function runAnalyze(args) {
1701
1924
  const ok = result.ok && !warningFailure;
1702
1925
  if (format === "json") {
1703
1926
  writeJson({
1704
- schema_version: "Perttool.AnalysisResult.v3",
1705
- cli_contract_version: 5,
1927
+ schema_version: "Perttool.AnalysisResult.v4",
1928
+ cli_contract_version: 6,
1706
1929
  tool_version: TOOL_VERSION,
1707
1930
  operation: "dag.analyze",
1708
1931
  ok,
@@ -1712,6 +1935,11 @@ async function runAnalyze(args) {
1712
1935
  diagnostics: result.diagnostics.map(jsonDiagnostic),
1713
1936
  diagnostics_truncated: result.diagnosticsTruncated,
1714
1937
  grammar_version: result.grammarVersion,
1938
+ task_actuals: result.taskActuals.map((actuals) => ({
1939
+ task_id: actuals.taskId,
1940
+ status: actuals.status,
1941
+ coverage: actuals.coverage,
1942
+ })),
1715
1943
  mode: result.mode,
1716
1944
  precision: result.precision,
1717
1945
  ...(result.durationUnit === null
@@ -1816,7 +2044,7 @@ async function runRender(args) {
1816
2044
  if (format === "json") {
1817
2045
  writeJson({
1818
2046
  schema_version: "Perttool.ExportResult.v1",
1819
- cli_contract_version: 5,
2047
+ cli_contract_version: 6,
1820
2048
  tool_version: TOOL_VERSION,
1821
2049
  operation: "dag.render",
1822
2050
  ok,
@@ -1908,7 +2136,7 @@ async function runImport(args) {
1908
2136
  if (format === "json") {
1909
2137
  writeJson({
1910
2138
  schema_version: "Perttool.ImportResult.v1",
1911
- cli_contract_version: 5,
2139
+ cli_contract_version: 6,
1912
2140
  tool_version: TOOL_VERSION,
1913
2141
  operation: "dag.import",
1914
2142
  ok,
@@ -1999,6 +2227,7 @@ function nextJson(result) {
1999
2227
  runnable_now: result.groups.runnableNow,
2000
2228
  blocked_now: result.groups.blockedNow,
2001
2229
  upcoming: result.groups.upcoming,
2230
+ suspended: result.groups.suspended,
2002
2231
  },
2003
2232
  tasks: result.tasks.map((task) => ({
2004
2233
  id: task.id,
@@ -2171,6 +2400,7 @@ function renderNextText(result) {
2171
2400
  section("RUNNABLE NOW", result.groups.runnableNow);
2172
2401
  section("READY / WAITING RESOURCE", result.groups.ready.filter((id) => !result.groups.runnableNow.includes(id)), "rejection");
2173
2402
  section("BLOCKED NOW", result.groups.blockedNow, "blocked");
2403
+ section("SUSPENDED", result.groups.suspended);
2174
2404
  section("UPCOMING", result.groups.upcoming, "explanation");
2175
2405
  lines.push("", "TEMPORAL CONTEXT");
2176
2406
  for (const temporal of result.temporal.tasks) {
@@ -2215,7 +2445,7 @@ async function runNext(args) {
2215
2445
  if (format === "json") {
2216
2446
  writeJson({
2217
2447
  schema_version: "Perttool.CliError.v1",
2218
- cli_contract_version: 5,
2448
+ cli_contract_version: 6,
2219
2449
  tool_version: TOOL_VERSION,
2220
2450
  operation: "dag.next",
2221
2451
  ok: false,
@@ -2235,8 +2465,8 @@ async function runNext(args) {
2235
2465
  const ok = result.ok && !warningFailure;
2236
2466
  if (format === "json") {
2237
2467
  writeJson({
2238
- schema_version: "Perttool.NextResult.v4",
2239
- cli_contract_version: 5,
2468
+ schema_version: "Perttool.NextResult.v5",
2469
+ cli_contract_version: 6,
2240
2470
  recommendation_interface_version: 1,
2241
2471
  tool_version: TOOL_VERSION,
2242
2472
  operation: "dag.next",
@@ -2272,12 +2502,12 @@ function runGuide(args) {
2272
2502
  colorMode(parsed.values.get("color"), format);
2273
2503
  const topicId = parsed.positionals.length === 0 ? null : parsed.positionals.join(".");
2274
2504
  const level = helpLevel(parsed.values.get("level"), topicId !== null);
2275
- const result = getTargetGovernanceGuide(topicId, level);
2505
+ const result = getActualsGuide(topicId, level);
2276
2506
  if (format === "json") {
2277
- process.stdout.write(serializeTargetGovernanceGuideResult(result));
2507
+ process.stdout.write(serializeActualsGuideResult(result));
2278
2508
  }
2279
2509
  else {
2280
- const rendered = renderTargetGovernanceGuideResult(result);
2510
+ const rendered = renderActualsGuideResult(result);
2281
2511
  if (result.ok) {
2282
2512
  process.stdout.write(rendered);
2283
2513
  }
@@ -2293,15 +2523,15 @@ function runCommandHelp(args) {
2293
2523
  throw new UsageError("help accepts at most <resource> <action>");
2294
2524
  }
2295
2525
  const format = outputFormat(parsed.values.get("format"));
2296
- const result = getTargetGovernanceCommandDiscovery({
2526
+ const result = getActualsCommandDiscovery({
2297
2527
  resource: parsed.positionals[0] ?? null,
2298
2528
  action: parsed.positionals[1] ?? null,
2299
2529
  });
2300
2530
  if (format === "json") {
2301
- process.stdout.write(serializeTargetGovernanceCommandHelpResult(result));
2531
+ process.stdout.write(serializeActualsCommandHelpResult(result));
2302
2532
  }
2303
2533
  else {
2304
- const rendered = renderTargetGovernanceCommandHelpResult(result);
2534
+ const rendered = renderActualsCommandHelpResult(result);
2305
2535
  if (result.ok) {
2306
2536
  process.stdout.write(rendered);
2307
2537
  }
@@ -2331,7 +2561,7 @@ function runAgentHelp(args) {
2331
2561
  const { schema_version: schemaVersion, ...payload } = projected;
2332
2562
  writeJson({
2333
2563
  schema_version: schemaVersion,
2334
- cli_contract_version: 5,
2564
+ cli_contract_version: 6,
2335
2565
  ...payload,
2336
2566
  });
2337
2567
  }
@@ -2369,6 +2599,10 @@ async function dispatchCommand(descriptor, args) {
2369
2599
  return runProjectInit(args);
2370
2600
  case "project.show":
2371
2601
  return runProjectShow(args);
2602
+ case "project.history":
2603
+ return runProjectHistory(args);
2604
+ case "project.observe-velocity":
2605
+ return runProjectVelocityObservation(args);
2372
2606
  case "project.migrate-unit":
2373
2607
  return runUnitMigration(args);
2374
2608
  case "dag.analyze":
@@ -2381,6 +2615,12 @@ async function dispatchCommand(descriptor, args) {
2381
2615
  return runRender(args);
2382
2616
  case "dag.import":
2383
2617
  return runImport(args);
2618
+ case "task.start":
2619
+ return runLifecycleMutation("start", args);
2620
+ case "task.suspend":
2621
+ return runLifecycleMutation("suspend", args);
2622
+ case "task.resume":
2623
+ return runLifecycleMutation("resume", args);
2384
2624
  }
2385
2625
  if (descriptor.path.length === 2
2386
2626
  && (descriptor.operation === "project.set"
@@ -2389,14 +2629,14 @@ async function dispatchCommand(descriptor, args) {
2389
2629
  const [resource, action] = descriptor.path;
2390
2630
  return runMutation(resource, action, args);
2391
2631
  }
2392
- throw new Error(`no Contract 5 handler for ${descriptor.operation}`);
2632
+ throw new Error(`no Contract 6 handler for ${descriptor.operation}`);
2393
2633
  }
2394
2634
  function emitCommandUsage(error, json) {
2395
2635
  if (json) {
2396
- process.stdout.write(serializeTargetGovernanceCommandUsageError(error));
2636
+ process.stdout.write(serializeActualsCommandUsageError(error));
2397
2637
  }
2398
2638
  else {
2399
- process.stderr.write(renderTargetGovernanceCommandUsageError(error));
2639
+ process.stderr.write(renderActualsCommandUsageError(error));
2400
2640
  }
2401
2641
  return 2;
2402
2642
  }
@@ -2408,13 +2648,13 @@ async function main(argv) {
2408
2648
  if (argv.length === 1 && argv[0] === "--help") {
2409
2649
  return runCommandHelp([]);
2410
2650
  }
2411
- const validation = validateTargetGovernanceCommandInvocation(argv);
2651
+ const validation = validateActualsCommandInvocation(argv);
2412
2652
  if (!validation.ok) {
2413
2653
  if (jsonRequested(argv)) {
2414
- process.stdout.write(serializeTargetGovernanceCommandUsageError(validation.error));
2654
+ process.stdout.write(serializeActualsCommandUsageError(validation.error));
2415
2655
  }
2416
2656
  else {
2417
- process.stderr.write(renderTargetGovernanceCommandUsageError(validation.error));
2657
+ process.stderr.write(renderActualsCommandUsageError(validation.error));
2418
2658
  }
2419
2659
  return 2;
2420
2660
  }