perttool 0.3.0 → 0.4.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 (173) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/README.md +82 -22
  3. package/dist/analysis/temporal-deadline.d.ts +2 -2
  4. package/dist/analysis/temporal-deadline.d.ts.map +1 -1
  5. package/dist/analysis/temporal-deadline.js.map +1 -1
  6. package/dist/analysis/temporal-precedence.d.ts +2 -2
  7. package/dist/analysis/temporal-precedence.d.ts.map +1 -1
  8. package/dist/analysis/temporal-precedence.js.map +1 -1
  9. package/dist/analysis/temporal-resource.d.ts +2 -2
  10. package/dist/analysis/temporal-resource.d.ts.map +1 -1
  11. package/dist/analysis/temporal-resource.js.map +1 -1
  12. package/dist/application/contract4.js +3 -3
  13. package/dist/application/contract5-governance.d.ts +8 -0
  14. package/dist/application/contract5-governance.d.ts.map +1 -0
  15. package/dist/application/contract5-governance.js +12 -0
  16. package/dist/application/contract5-governance.js.map +1 -0
  17. package/dist/application/init.d.ts +3 -12
  18. package/dist/application/init.d.ts.map +1 -1
  19. package/dist/application/init.js +16 -138
  20. package/dist/application/init.js.map +1 -1
  21. package/dist/application/project.d.ts +4 -24
  22. package/dist/application/project.d.ts.map +1 -1
  23. package/dist/application/project.js +3 -52
  24. package/dist/application/project.js.map +1 -1
  25. package/dist/application/target-governance-init.d.ts +36 -0
  26. package/dist/application/target-governance-init.d.ts.map +1 -0
  27. package/dist/application/target-governance-init.js +185 -0
  28. package/dist/application/target-governance-init.js.map +1 -0
  29. package/dist/application/target-governance-mutation.d.ts +20 -0
  30. package/dist/application/target-governance-mutation.d.ts.map +1 -0
  31. package/dist/application/target-governance-mutation.js +175 -0
  32. package/dist/application/target-governance-mutation.js.map +1 -0
  33. package/dist/application/target-governance-project.d.ts +34 -0
  34. package/dist/application/target-governance-project.d.ts.map +1 -0
  35. package/dist/application/target-governance-project.js +80 -0
  36. package/dist/application/target-governance-project.js.map +1 -0
  37. package/dist/application/target-governance-projection.d.ts +18 -0
  38. package/dist/application/target-governance-projection.d.ts.map +1 -0
  39. package/dist/application/target-governance-projection.js +248 -0
  40. package/dist/application/target-governance-projection.js.map +1 -0
  41. package/dist/application/target-governance-write.d.ts +17 -0
  42. package/dist/application/target-governance-write.d.ts.map +1 -0
  43. package/dist/application/target-governance-write.js +55 -0
  44. package/dist/application/target-governance-write.js.map +1 -0
  45. package/dist/application/target-mutate.d.ts +4 -2
  46. package/dist/application/target-mutate.d.ts.map +1 -1
  47. package/dist/application/target-mutate.js +27 -2
  48. package/dist/application/target-mutate.js.map +1 -1
  49. package/dist/application/target-temporal-analysis.d.ts +6 -4
  50. package/dist/application/target-temporal-analysis.d.ts.map +1 -1
  51. package/dist/application/target-temporal-analysis.js +8 -3
  52. package/dist/application/target-temporal-analysis.js.map +1 -1
  53. package/dist/application/target-temporal-input.d.ts +5 -5
  54. package/dist/application/target-temporal-input.d.ts.map +1 -1
  55. package/dist/application/target-temporal-input.js +4 -2
  56. package/dist/application/target-temporal-input.js.map +1 -1
  57. package/dist/application/target-unit-migration-candidate.d.ts +2 -2
  58. package/dist/application/target-unit-migration-candidate.d.ts.map +1 -1
  59. package/dist/application/target-unit-migration-candidate.js +8 -4
  60. package/dist/application/target-unit-migration-candidate.js.map +1 -1
  61. package/dist/application/target-unit-migration-request.d.ts +4 -4
  62. package/dist/application/target-unit-migration-request.d.ts.map +1 -1
  63. package/dist/application/target-unit-migration-request.js +4 -2
  64. package/dist/application/target-unit-migration-request.js.map +1 -1
  65. package/dist/application/target-unit-migration-result.d.ts +2 -2
  66. package/dist/application/target-unit-migration-result.d.ts.map +1 -1
  67. package/dist/application/target-unit-migration-result.js.map +1 -1
  68. package/dist/application/unit-migration.d.ts +4 -1
  69. package/dist/application/unit-migration.d.ts.map +1 -1
  70. package/dist/application/unit-migration.js +5 -3
  71. package/dist/application/unit-migration.js.map +1 -1
  72. package/dist/cli.js +144 -131
  73. package/dist/cli.js.map +1 -1
  74. package/dist/command/registry.d.ts +7 -1
  75. package/dist/command/registry.d.ts.map +1 -1
  76. package/dist/command/registry.js.map +1 -1
  77. package/dist/command/target-governance-discovery.d.ts +31 -0
  78. package/dist/command/target-governance-discovery.d.ts.map +1 -0
  79. package/dist/command/target-governance-discovery.js +390 -0
  80. package/dist/command/target-governance-discovery.js.map +1 -0
  81. package/dist/command/target-governance-usage.d.ts +22 -0
  82. package/dist/command/target-governance-usage.d.ts.map +1 -0
  83. package/dist/command/target-governance-usage.js +116 -0
  84. package/dist/command/target-governance-usage.js.map +1 -0
  85. package/dist/command/usage.d.ts +2 -0
  86. package/dist/command/usage.d.ts.map +1 -1
  87. package/dist/command/usage.js +43 -25
  88. package/dist/command/usage.js.map +1 -1
  89. package/dist/conversion/mermaid-import.d.ts.map +1 -1
  90. package/dist/conversion/mermaid-import.js +3 -2
  91. package/dist/conversion/mermaid-import.js.map +1 -1
  92. package/dist/conversion/mermaid.d.ts.map +1 -1
  93. package/dist/conversion/mermaid.js +27 -0
  94. package/dist/conversion/mermaid.js.map +1 -1
  95. package/dist/formatter/source-formatter.d.ts.map +1 -1
  96. package/dist/formatter/source-formatter.js +13 -2
  97. package/dist/formatter/source-formatter.js.map +1 -1
  98. package/dist/formatter/target-source-formatter.d.ts +2 -1
  99. package/dist/formatter/target-source-formatter.d.ts.map +1 -1
  100. package/dist/formatter/target-source-formatter.js +18 -2
  101. package/dist/formatter/target-source-formatter.js.map +1 -1
  102. package/dist/governance/authority.d.ts +21 -0
  103. package/dist/governance/authority.d.ts.map +1 -0
  104. package/dist/governance/authority.js +206 -0
  105. package/dist/governance/authority.js.map +1 -0
  106. package/dist/governance/guidance.d.ts +2 -0
  107. package/dist/governance/guidance.d.ts.map +1 -0
  108. package/dist/governance/guidance.js +2 -0
  109. package/dist/governance/guidance.js.map +1 -0
  110. package/dist/governance/source.d.ts +37 -0
  111. package/dist/governance/source.d.ts.map +1 -0
  112. package/dist/governance/source.js +103 -0
  113. package/dist/governance/source.js.map +1 -0
  114. package/dist/governance/types.d.ts +41 -0
  115. package/dist/governance/types.d.ts.map +1 -0
  116. package/dist/governance/types.js +2 -0
  117. package/dist/governance/types.js.map +1 -0
  118. package/dist/help/guide.d.ts +8 -5
  119. package/dist/help/guide.d.ts.map +1 -1
  120. package/dist/help/guide.js.map +1 -1
  121. package/dist/help/registry.js +2 -2
  122. package/dist/help/registry.js.map +1 -1
  123. package/dist/help/target-governance-guide.d.ts +10 -0
  124. package/dist/help/target-governance-guide.d.ts.map +1 -0
  125. package/dist/help/target-governance-guide.js +57 -0
  126. package/dist/help/target-governance-guide.js.map +1 -0
  127. package/dist/index.d.ts +17 -12
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +6 -6
  130. package/dist/index.js.map +1 -1
  131. package/dist/io/safe-write.d.ts +4 -0
  132. package/dist/io/safe-write.d.ts.map +1 -1
  133. package/dist/io/safe-write.js +22 -1
  134. package/dist/io/safe-write.js.map +1 -1
  135. package/dist/io/target-safe-write.d.ts +5 -2
  136. package/dist/io/target-safe-write.d.ts.map +1 -1
  137. package/dist/io/target-safe-write.js +20 -2
  138. package/dist/io/target-safe-write.js.map +1 -1
  139. package/dist/migration/grammar-boundary.d.ts +1 -1
  140. package/dist/migration/grammar-boundary.d.ts.map +1 -1
  141. package/dist/migration/grammar-boundary.js +7 -4
  142. package/dist/migration/grammar-boundary.js.map +1 -1
  143. package/dist/model/declaration-fields.d.ts +7 -0
  144. package/dist/model/declaration-fields.d.ts.map +1 -1
  145. package/dist/model/declaration-fields.js +18 -0
  146. package/dist/model/declaration-fields.js.map +1 -1
  147. package/dist/mutation/advance.d.ts +11 -0
  148. package/dist/mutation/advance.d.ts.map +1 -1
  149. package/dist/mutation/advance.js +16 -3
  150. package/dist/mutation/advance.js.map +1 -1
  151. package/dist/mutation/project.d.ts +5 -1
  152. package/dist/mutation/project.d.ts.map +1 -1
  153. package/dist/mutation/project.js +99 -6
  154. package/dist/mutation/project.js.map +1 -1
  155. package/dist/mutation/target-types.d.ts +18 -1
  156. package/dist/mutation/target-types.d.ts.map +1 -1
  157. package/dist/mutation/types.d.ts +8 -1
  158. package/dist/mutation/types.d.ts.map +1 -1
  159. package/dist/parser/document-parser.d.ts +7 -0
  160. package/dist/parser/document-parser.d.ts.map +1 -1
  161. package/dist/parser/document-parser.js +57 -2
  162. package/dist/parser/document-parser.js.map +1 -1
  163. package/dist/semantic/target-validator.d.ts +11 -1
  164. package/dist/semantic/target-validator.d.ts.map +1 -1
  165. package/dist/semantic/target-validator.js +45 -2
  166. package/dist/semantic/target-validator.js.map +1 -1
  167. package/dist/semantic/validator.d.ts +1 -0
  168. package/dist/semantic/validator.d.ts.map +1 -1
  169. package/dist/semantic/validator.js +29 -1
  170. package/dist/semantic/validator.js.map +1 -1
  171. package/dist/version.d.ts +1 -1
  172. package/dist/version.js +1 -1
  173. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6,16 +6,19 @@ import { analyzeDocument, selectNextTasks, } from "./application/contract4.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
- import { planBatchMutation, planMutation } from "./application/mutate.js";
10
9
  import { planUnitMigration, withUnitMigrationWrite, } from "./application/unit-migration.js";
11
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";
12
14
  import { getAgentHelp } from "./application/agent-help.js";
13
15
  import { exportMermaid, } from "./conversion/mermaid.js";
14
16
  import { importMermaid } from "./conversion/mermaid-import.js";
15
- import { getGuide, renderGuideResult, serializeGuideResult, } from "./help/guide.js";
17
+ import { getTargetGovernanceGuide, renderTargetGovernanceGuideResult, serializeTargetGovernanceGuideResult, } from "./help/target-governance-guide.js";
16
18
  import { commandOptionSets, } from "./command/registry.js";
17
- import { CONTRACT4_COMMAND_REGISTRY, getCommandDiscovery, renderCommandHelpResult, serializeCommandHelpResult, } from "./command/discovery.js";
18
- import { handlerCommandUsageError, renderCommandUsageError, serializeCommandUsageError, validateCommandInvocation, } from "./command/usage.js";
19
+ import { TARGET_GOVERNANCE_COMMAND_REGISTRY, getTargetGovernanceCommandDiscovery, renderTargetGovernanceCommandHelpResult, serializeTargetGovernanceCommandHelpResult, } from "./command/target-governance-discovery.js";
20
+ import { handlerCommandUsageError, } from "./command/usage.js";
21
+ import { renderTargetGovernanceCommandUsageError, serializeTargetGovernanceCommandUsageError, validateTargetGovernanceCommandInvocation, } from "./command/target-governance-usage.js";
19
22
  import { agentGuidanceResultToJson } from "./guidance/projection.js";
20
23
  import { agentGuidanceExitCode, renderAgentGuidanceText, } from "./guidance/text.js";
21
24
  import { documentContentFromBytes, readDocumentFile, } from "./io/document-file.js";
@@ -24,7 +27,7 @@ import { formatDecimal } from "./model/rational.js";
24
27
  import { convertWithVelocity, durationSuffix } from "./model/units.js";
25
28
  import { recommendationInvariantExitCode } from "./recommendation/failure.js";
26
29
  import { recommendationAnalysisToJson } from "./recommendation/json.js";
27
- import { planAdvance, } from "./mutation/advance.js";
30
+ import { TARGET_GRAMMAR_4_CAPABILITY, } from "./parser/document-parser.js";
28
31
  import { TOOL_VERSION } from "./version.js";
29
32
  class UsageError extends Error {
30
33
  code = "PTCLI-001";
@@ -79,7 +82,7 @@ function parseOptions(args, valueOptions, flagOptions, repeatableOptions = new S
79
82
  return { positionals, values, repeatedValues, flags };
80
83
  }
81
84
  function parseCommandOptions(operation, args) {
82
- const descriptor = CONTRACT4_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
85
+ const descriptor = TARGET_GOVERNANCE_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
83
86
  if (descriptor === undefined) {
84
87
  throw new Error(`command descriptor is missing for ${operation}`);
85
88
  }
@@ -217,7 +220,7 @@ function cliError(error, exitCode, operation, json) {
217
220
  if (json) {
218
221
  writeJson({
219
222
  schema_version: "Perttool.CliError.v1",
220
- cli_contract_version: 4,
223
+ cli_contract_version: 5,
221
224
  tool_version: TOOL_VERSION,
222
225
  operation,
223
226
  ok: false,
@@ -253,7 +256,7 @@ async function runCheck(args) {
253
256
  if (format === "json") {
254
257
  writeJson({
255
258
  schema_version: "Perttool.CheckResult.v2",
256
- cli_contract_version: 4,
259
+ cli_contract_version: 5,
257
260
  tool_version: TOOL_VERSION,
258
261
  operation: "document.check",
259
262
  ok,
@@ -280,41 +283,6 @@ async function runCheck(args) {
280
283
  }
281
284
  return ok ? 0 : 1;
282
285
  }
283
- function projectJson(project) {
284
- return {
285
- id: project.id,
286
- version: project.version,
287
- title: project.title,
288
- description: project.description,
289
- as_of: snakeJson(project.asOf),
290
- duration_unit: project.durationUnit,
291
- velocity: project.velocity,
292
- finish: project.finish,
293
- finish_deadline: snakeJson(project.finishDeadline),
294
- critical_epsilon: project.criticalEpsilon,
295
- target_duration: project.targetDuration,
296
- };
297
- }
298
- function renderProjectText(project) {
299
- const optional = (value) => value ?? "-";
300
- const calendar = (value) => value === null
301
- ? "-"
302
- : `${value.kind.toUpperCase()} ${value.sourceText ?? "-"}`;
303
- return [
304
- `PROJECT ${project.id}`,
305
- `VERSION ${project.version}`,
306
- `TITLE ${JSON.stringify(project.title)}`,
307
- `DESCRIPTION ${project.description === null ? "-" : JSON.stringify(project.description)}`,
308
- `AS_OF ${calendar(project.asOf)}`,
309
- `DURATION_UNIT ${project.durationUnit}`,
310
- `VELOCITY ${optional(project.velocity)}`,
311
- `FINISH ${project.finish}`,
312
- `FINISH_DEADLINE ${calendar(project.finishDeadline)}`,
313
- `CRITICAL_EPSILON ${optional(project.criticalEpsilon)}`,
314
- `TARGET_DURATION ${optional(project.targetDuration)}`,
315
- "",
316
- ].join("\n");
317
- }
318
286
  async function runProjectShow(args) {
319
287
  const parsed = parseCommandOptions("project.show", args);
320
288
  if (parsed.positionals.length !== 1) {
@@ -338,24 +306,11 @@ async function runProjectShow(args) {
338
306
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
339
307
  const ok = result.ok && !warningFailure;
340
308
  if (format === "json") {
341
- writeJson({
342
- schema_version: "Perttool.ProjectResult.v2",
343
- cli_contract_version: 4,
344
- tool_version: TOOL_VERSION,
345
- operation: "project.show",
346
- ok,
347
- document_id: result.documentId,
348
- source,
349
- source_digest: input.digest,
350
- diagnostics: result.diagnostics.map(jsonDiagnostic),
351
- diagnostics_truncated: result.diagnosticsTruncated,
352
- grammar_version: result.grammarVersion,
353
- project: result.project === null ? null : projectJson(result.project),
354
- });
309
+ writeJson(targetGovernanceProjectResultToJson(result, source, input.digest, ok));
355
310
  }
356
311
  else {
357
312
  if (ok && result.project !== null) {
358
- process.stdout.write(renderProjectText(result.project));
313
+ process.stdout.write(renderTargetGovernanceProjectText(result.project));
359
314
  }
360
315
  for (const diagnostic of result.diagnostics) {
361
316
  process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
@@ -391,6 +346,22 @@ async function runProjectInit(args) {
391
346
  : {
392
347
  initialMilestoneDeadline: parsed.values.get("initial-milestone-deadline"),
393
348
  }),
349
+ ...(parsed.values.get("goal-owner") === undefined
350
+ ? {}
351
+ : { goalOwner: parsed.values.get("goal-owner") }),
352
+ ...(parsed.values.get("goal-delegates") === undefined
353
+ ? {}
354
+ : {
355
+ goalDelegates: principalListOption(parsed.values.get("goal-delegates")),
356
+ }),
357
+ ...(parsed.values.get("dag-owner") === undefined
358
+ ? {}
359
+ : { dagOwner: parsed.values.get("dag-owner") }),
360
+ ...(parsed.values.get("dag-delegates") === undefined
361
+ ? {}
362
+ : {
363
+ dagDelegates: principalListOption(parsed.values.get("dag-delegates")),
364
+ }),
394
365
  });
395
366
  let writeResult = null;
396
367
  const output = parsed.values.get("out");
@@ -494,6 +465,39 @@ function editingWriteRequest(parsed, sourceOperand, check = false) {
494
465
  return { mode: "out", target: out };
495
466
  return { mode: "preview", target: null };
496
467
  }
468
+ function governanceRequest(parsed, writeRequest) {
469
+ return Object.freeze({
470
+ intent: writeRequest.mode === "preview"
471
+ ? "preview"
472
+ : "persist",
473
+ actor: parsed.values.get("actor") ?? null,
474
+ acceptedByOwner: Object.freeze([
475
+ ...(parsed.repeatedValues.get("accepted-by-owner") ?? []),
476
+ ]),
477
+ });
478
+ }
479
+ async function persistGovernedResult(result, request, sourceOperand) {
480
+ if (request.mode === "preview") {
481
+ return Object.freeze({
482
+ mode: "preview",
483
+ target: null,
484
+ written: false,
485
+ });
486
+ }
487
+ return persistTargetGovernanceResult(result, TARGET_GRAMMAR_4_CAPABILITY, request.mode === "in_place"
488
+ ? {
489
+ mode: "in_place",
490
+ target: request.target,
491
+ ...(request.expectedDigest === undefined
492
+ ? {}
493
+ : { expectedDigest: request.expectedDigest }),
494
+ }
495
+ : {
496
+ mode: "out",
497
+ source: sourceOperand,
498
+ target: request.target,
499
+ });
500
+ }
497
501
  function assertExpectedDigest(request, initialDigest) {
498
502
  if (request.mode === "in_place" &&
499
503
  request.expectedDigest !== undefined &&
@@ -526,6 +530,9 @@ function writeFailureExit(error, operation, json) {
526
530
  function renderWriteSummary(operation, result) {
527
531
  return `WRITE ${operation} mode=${result.mode} target=${result.target} digest=${result.digest} written=${result.written}\n`;
528
532
  }
533
+ function renderGovernanceWriteSummary(operation, result, digest) {
534
+ return `WRITE ${operation} mode=${result.mode} target=${result.target ?? "-"} digest=${digest ?? "-"} written=${result.written}\n`;
535
+ }
529
536
  async function runFormat(args) {
530
537
  const parsed = parseCommandOptions("document.format", args);
531
538
  if (parsed.positionals.length !== 1) {
@@ -569,7 +576,7 @@ async function runFormat(args) {
569
576
  if (format === "json") {
570
577
  writeJson({
571
578
  schema_version: "Perttool.FormatResult.v1",
572
- cli_contract_version: 4,
579
+ cli_contract_version: 5,
573
580
  tool_version: TOOL_VERSION,
574
581
  operation: "document.format",
575
582
  ok,
@@ -637,6 +644,12 @@ function uniqueRepeated(parsed, option) {
637
644
  }
638
645
  return values;
639
646
  }
647
+ function principalListOption(value) {
648
+ const interior = value.slice(1, -1).trim();
649
+ return interior === ""
650
+ ? Object.freeze([])
651
+ : Object.freeze(interior.split(",").map((item) => item.trim()));
652
+ }
640
653
  function enumRepeated(parsed, option, allowed) {
641
654
  return uniqueRepeated(parsed, option).map((value) => {
642
655
  if (!allowed.has(value)) {
@@ -823,6 +836,10 @@ function projectMutationFromOptions(parsed) {
823
836
  "velocity",
824
837
  "critical_epsilon",
825
838
  "target_duration",
839
+ "goal_owner",
840
+ "goal_delegates",
841
+ "dag_owner",
842
+ "dag_delegates",
826
843
  ]));
827
844
  const conflicts = new Map([
828
845
  ["description", parsed.values.has("description")],
@@ -830,6 +847,10 @@ function projectMutationFromOptions(parsed) {
830
847
  ["velocity", parsed.values.has("velocity")],
831
848
  ["critical_epsilon", parsed.values.has("critical-epsilon")],
832
849
  ["target_duration", parsed.values.has("target-duration")],
850
+ ["goal_owner", parsed.values.has("goal-owner")],
851
+ ["goal_delegates", parsed.values.has("goal-delegates")],
852
+ ["dag_owner", parsed.values.has("dag-owner")],
853
+ ["dag_delegates", parsed.values.has("dag-delegates")],
833
854
  ]);
834
855
  const conflict = clear.find((field) => conflicts.get(field) === true);
835
856
  if (conflict !== undefined) {
@@ -860,6 +881,22 @@ function projectMutationFromOptions(parsed) {
860
881
  ...(parsed.values.get("target-duration") === undefined
861
882
  ? {}
862
883
  : { targetDuration: parsed.values.get("target-duration") }),
884
+ ...(parsed.values.get("goal-owner") === undefined
885
+ ? {}
886
+ : { goalOwner: parsed.values.get("goal-owner") }),
887
+ ...(parsed.values.get("goal-delegates") === undefined
888
+ ? {}
889
+ : {
890
+ goalDelegates: principalListOption(parsed.values.get("goal-delegates")),
891
+ }),
892
+ ...(parsed.values.get("dag-owner") === undefined
893
+ ? {}
894
+ : { dagOwner: parsed.values.get("dag-owner") }),
895
+ ...(parsed.values.get("dag-delegates") === undefined
896
+ ? {}
897
+ : {
898
+ dagDelegates: principalListOption(parsed.values.get("dag-delegates")),
899
+ }),
863
900
  };
864
901
  return {
865
902
  kind: "project.set",
@@ -1084,20 +1121,24 @@ async function runMutation(resource, action, args) {
1084
1121
  maxDiagnostics,
1085
1122
  originalLabel: source,
1086
1123
  updatedLabel: "candidate",
1124
+ governance: governanceRequest(parsed, writeRequest),
1087
1125
  };
1088
1126
  const result = resource === "batch"
1089
- ? planBatchMutation(input.text, mutation, mutationOptions)
1090
- : planMutation(input.text, mutation, mutationOptions);
1127
+ ? planTargetGovernanceBatchMutation(input.text, mutation, TARGET_GRAMMAR_4_CAPABILITY, mutationOptions)
1128
+ : planTargetGovernanceMutation(input.text, mutation, TARGET_GRAMMAR_4_CAPABILITY, mutationOptions);
1091
1129
  const warningFailure = parsed.flags.has("warnings-as-errors") &&
1092
1130
  (result.diagnosticsTruncated ||
1093
1131
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
1094
1132
  const ok = result.ok && !warningFailure;
1095
- let writeResult = null;
1133
+ let writeResult = Object.freeze({
1134
+ mode: writeRequest.mode,
1135
+ target: writeRequest.target,
1136
+ written: false,
1137
+ });
1096
1138
  if (result.ok) {
1097
1139
  try {
1098
- assertExpectedDigest(writeRequest, input.digest);
1099
1140
  if (ok && writeRequest.mode !== "preview") {
1100
- writeResult = await commitCandidate(writeRequest, result.updatedText, input.digest);
1141
+ writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
1101
1142
  }
1102
1143
  }
1103
1144
  catch (error) {
@@ -1105,24 +1146,12 @@ async function runMutation(resource, action, args) {
1105
1146
  }
1106
1147
  }
1107
1148
  if (format === "json") {
1108
- writeJson({
1109
- schema_version: "Perttool.MutationResult.v1",
1110
- cli_contract_version: 4,
1111
- tool_version: TOOL_VERSION,
1112
- operation,
1113
- ok,
1114
- document_id: result.documentId,
1115
- source,
1116
- source_digest: input.digest,
1117
- diagnostics: result.diagnostics.map(jsonDiagnostic),
1118
- diagnostics_truncated: result.diagnosticsTruncated,
1119
- ...previewResultJson(result, result.ok, writeRequest, writeResult),
1120
- });
1149
+ writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
1121
1150
  }
1122
1151
  else {
1123
1152
  if (ok) {
1124
- if (writeResult !== null) {
1125
- process.stderr.write(renderWriteSummary(operation, writeResult));
1153
+ if (writeRequest.mode !== "preview") {
1154
+ process.stderr.write(renderGovernanceWriteSummary(operation, writeResult, result.updatedDigest));
1126
1155
  }
1127
1156
  else {
1128
1157
  process.stdout.write(parsed.flags.has("diff") ? (result.diff ?? "") : (result.updatedText ?? ""));
@@ -1131,6 +1160,9 @@ async function runMutation(resource, action, args) {
1131
1160
  }
1132
1161
  }
1133
1162
  }
1163
+ if (result.governance !== null) {
1164
+ process.stderr.write(renderTargetGovernanceDecision(result.governance));
1165
+ }
1134
1166
  for (const diagnostic of result.diagnostics) {
1135
1167
  process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
1136
1168
  }
@@ -1148,7 +1180,7 @@ function unitMigrationJson(result, source, sourceDigest, ok) {
1148
1180
  });
1149
1181
  return {
1150
1182
  schema_version: result.schemaVersion,
1151
- cli_contract_version: 4,
1183
+ cli_contract_version: 5,
1152
1184
  tool_version: TOOL_VERSION,
1153
1185
  operation: "project.migrate-unit",
1154
1186
  ok,
@@ -1276,19 +1308,6 @@ async function runUnitMigration(args) {
1276
1308
  }
1277
1309
  return ok ? 0 : 1;
1278
1310
  }
1279
- function advanceResultJson(details) {
1280
- return details === null
1281
- ? null
1282
- : {
1283
- removed_task_ids: details.removedTaskIds,
1284
- removed_gate_ids: details.removedGateIds,
1285
- removed_milestone_ids: details.removedMilestoneIds,
1286
- frontier_before: details.frontierBefore,
1287
- frontier_after: details.frontierAfter,
1288
- ready_before: details.readyBefore,
1289
- ready_after: details.readyAfter,
1290
- };
1291
- }
1292
1311
  function renderAdvanceSummary(details) {
1293
1312
  const list = (ids) => ids.join(",") || "-";
1294
1313
  return [
@@ -1315,21 +1334,25 @@ async function runAdvance(args) {
1315
1334
  catch (error) {
1316
1335
  return cliError(error instanceof Error ? error : new Error(String(error)), 3, "dag.advance", format === "json");
1317
1336
  }
1318
- const result = planAdvance(input.text, {
1337
+ const result = planTargetGovernanceAdvance(input.text, TARGET_GRAMMAR_4_CAPABILITY, {
1319
1338
  maxDiagnostics,
1320
1339
  originalLabel: source,
1321
1340
  updatedLabel: "candidate",
1341
+ governance: governanceRequest(parsed, writeRequest),
1322
1342
  });
1323
1343
  const warningFailure = parsed.flags.has("warnings-as-errors") &&
1324
1344
  (result.diagnosticsTruncated ||
1325
1345
  result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
1326
1346
  const ok = result.ok && !warningFailure;
1327
- let writeResult = null;
1347
+ let writeResult = Object.freeze({
1348
+ mode: writeRequest.mode,
1349
+ target: writeRequest.target,
1350
+ written: false,
1351
+ });
1328
1352
  if (result.ok) {
1329
1353
  try {
1330
- assertExpectedDigest(writeRequest, input.digest);
1331
1354
  if (ok && writeRequest.mode !== "preview") {
1332
- writeResult = await commitCandidate(writeRequest, result.updatedText, input.digest);
1355
+ writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
1333
1356
  }
1334
1357
  }
1335
1358
  catch (error) {
@@ -1337,25 +1360,12 @@ async function runAdvance(args) {
1337
1360
  }
1338
1361
  }
1339
1362
  if (format === "json") {
1340
- writeJson({
1341
- schema_version: "Perttool.MutationResult.v1",
1342
- cli_contract_version: 4,
1343
- tool_version: TOOL_VERSION,
1344
- operation: "dag.advance",
1345
- ok,
1346
- document_id: result.documentId,
1347
- source,
1348
- source_digest: input.digest,
1349
- diagnostics: result.diagnostics.map(jsonDiagnostic),
1350
- diagnostics_truncated: result.diagnosticsTruncated,
1351
- ...previewResultJson(result, result.ok, writeRequest, writeResult),
1352
- advance: advanceResultJson(result.advance),
1353
- });
1363
+ writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
1354
1364
  }
1355
1365
  else {
1356
1366
  if (ok && result.advance !== null) {
1357
- if (writeResult !== null) {
1358
- process.stderr.write(renderWriteSummary("dag.advance", writeResult));
1367
+ if (writeRequest.mode !== "preview") {
1368
+ process.stderr.write(renderGovernanceWriteSummary("dag.advance", writeResult, result.updatedDigest));
1359
1369
  }
1360
1370
  else {
1361
1371
  process.stdout.write(parsed.flags.has("diff") ? (result.diff ?? "") : (result.updatedText ?? ""));
@@ -1365,6 +1375,9 @@ async function runAdvance(args) {
1365
1375
  }
1366
1376
  process.stderr.write(renderAdvanceSummary(result.advance));
1367
1377
  }
1378
+ if (result.governance !== null) {
1379
+ process.stderr.write(renderTargetGovernanceDecision(result.governance));
1380
+ }
1368
1381
  for (const diagnostic of result.diagnostics) {
1369
1382
  process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
1370
1383
  }
@@ -1689,7 +1702,7 @@ async function runAnalyze(args) {
1689
1702
  if (format === "json") {
1690
1703
  writeJson({
1691
1704
  schema_version: "Perttool.AnalysisResult.v3",
1692
- cli_contract_version: 4,
1705
+ cli_contract_version: 5,
1693
1706
  tool_version: TOOL_VERSION,
1694
1707
  operation: "dag.analyze",
1695
1708
  ok,
@@ -1803,7 +1816,7 @@ async function runRender(args) {
1803
1816
  if (format === "json") {
1804
1817
  writeJson({
1805
1818
  schema_version: "Perttool.ExportResult.v1",
1806
- cli_contract_version: 4,
1819
+ cli_contract_version: 5,
1807
1820
  tool_version: TOOL_VERSION,
1808
1821
  operation: "dag.render",
1809
1822
  ok,
@@ -1895,7 +1908,7 @@ async function runImport(args) {
1895
1908
  if (format === "json") {
1896
1909
  writeJson({
1897
1910
  schema_version: "Perttool.ImportResult.v1",
1898
- cli_contract_version: 4,
1911
+ cli_contract_version: 5,
1899
1912
  tool_version: TOOL_VERSION,
1900
1913
  operation: "dag.import",
1901
1914
  ok,
@@ -2202,7 +2215,7 @@ async function runNext(args) {
2202
2215
  if (format === "json") {
2203
2216
  writeJson({
2204
2217
  schema_version: "Perttool.CliError.v1",
2205
- cli_contract_version: 4,
2218
+ cli_contract_version: 5,
2206
2219
  tool_version: TOOL_VERSION,
2207
2220
  operation: "dag.next",
2208
2221
  ok: false,
@@ -2223,7 +2236,7 @@ async function runNext(args) {
2223
2236
  if (format === "json") {
2224
2237
  writeJson({
2225
2238
  schema_version: "Perttool.NextResult.v4",
2226
- cli_contract_version: 4,
2239
+ cli_contract_version: 5,
2227
2240
  recommendation_interface_version: 1,
2228
2241
  tool_version: TOOL_VERSION,
2229
2242
  operation: "dag.next",
@@ -2259,12 +2272,12 @@ function runGuide(args) {
2259
2272
  colorMode(parsed.values.get("color"), format);
2260
2273
  const topicId = parsed.positionals.length === 0 ? null : parsed.positionals.join(".");
2261
2274
  const level = helpLevel(parsed.values.get("level"), topicId !== null);
2262
- const result = getGuide(topicId, level);
2275
+ const result = getTargetGovernanceGuide(topicId, level);
2263
2276
  if (format === "json") {
2264
- process.stdout.write(serializeGuideResult(result));
2277
+ process.stdout.write(serializeTargetGovernanceGuideResult(result));
2265
2278
  }
2266
2279
  else {
2267
- const rendered = renderGuideResult(result);
2280
+ const rendered = renderTargetGovernanceGuideResult(result);
2268
2281
  if (result.ok) {
2269
2282
  process.stdout.write(rendered);
2270
2283
  }
@@ -2280,15 +2293,15 @@ function runCommandHelp(args) {
2280
2293
  throw new UsageError("help accepts at most <resource> <action>");
2281
2294
  }
2282
2295
  const format = outputFormat(parsed.values.get("format"));
2283
- const result = getCommandDiscovery({
2296
+ const result = getTargetGovernanceCommandDiscovery({
2284
2297
  resource: parsed.positionals[0] ?? null,
2285
2298
  action: parsed.positionals[1] ?? null,
2286
2299
  });
2287
2300
  if (format === "json") {
2288
- process.stdout.write(serializeCommandHelpResult(result));
2301
+ process.stdout.write(serializeTargetGovernanceCommandHelpResult(result));
2289
2302
  }
2290
2303
  else {
2291
- const rendered = renderCommandHelpResult(result);
2304
+ const rendered = renderTargetGovernanceCommandHelpResult(result);
2292
2305
  if (result.ok) {
2293
2306
  process.stdout.write(rendered);
2294
2307
  }
@@ -2318,7 +2331,7 @@ function runAgentHelp(args) {
2318
2331
  const { schema_version: schemaVersion, ...payload } = projected;
2319
2332
  writeJson({
2320
2333
  schema_version: schemaVersion,
2321
- cli_contract_version: 4,
2334
+ cli_contract_version: 5,
2322
2335
  ...payload,
2323
2336
  });
2324
2337
  }
@@ -2376,14 +2389,14 @@ async function dispatchCommand(descriptor, args) {
2376
2389
  const [resource, action] = descriptor.path;
2377
2390
  return runMutation(resource, action, args);
2378
2391
  }
2379
- throw new Error(`no Contract 4 handler for ${descriptor.operation}`);
2392
+ throw new Error(`no Contract 5 handler for ${descriptor.operation}`);
2380
2393
  }
2381
2394
  function emitCommandUsage(error, json) {
2382
2395
  if (json) {
2383
- process.stdout.write(serializeCommandUsageError(error));
2396
+ process.stdout.write(serializeTargetGovernanceCommandUsageError(error));
2384
2397
  }
2385
2398
  else {
2386
- process.stderr.write(renderCommandUsageError(error));
2399
+ process.stderr.write(renderTargetGovernanceCommandUsageError(error));
2387
2400
  }
2388
2401
  return 2;
2389
2402
  }
@@ -2395,13 +2408,13 @@ async function main(argv) {
2395
2408
  if (argv.length === 1 && argv[0] === "--help") {
2396
2409
  return runCommandHelp([]);
2397
2410
  }
2398
- const validation = validateCommandInvocation(argv);
2411
+ const validation = validateTargetGovernanceCommandInvocation(argv);
2399
2412
  if (!validation.ok) {
2400
2413
  if (jsonRequested(argv)) {
2401
- process.stdout.write(serializeCommandUsageError(validation.error));
2414
+ process.stdout.write(serializeTargetGovernanceCommandUsageError(validation.error));
2402
2415
  }
2403
2416
  else {
2404
- process.stderr.write(renderCommandUsageError(validation.error));
2417
+ process.stderr.write(renderTargetGovernanceCommandUsageError(validation.error));
2405
2418
  }
2406
2419
  return 2;
2407
2420
  }