perttool 0.2.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.
- package/CHANGELOG.md +81 -1
- package/README.md +121 -28
- package/dist/analysis/temporal-deadline.d.ts +59 -0
- package/dist/analysis/temporal-deadline.d.ts.map +1 -0
- package/dist/analysis/temporal-deadline.js +387 -0
- package/dist/analysis/temporal-deadline.js.map +1 -0
- package/dist/analysis/temporal-precedence.d.ts +45 -0
- package/dist/analysis/temporal-precedence.d.ts.map +1 -0
- package/dist/analysis/temporal-precedence.js +123 -0
- package/dist/analysis/temporal-precedence.js.map +1 -0
- package/dist/analysis/temporal-resource.d.ts +66 -0
- package/dist/analysis/temporal-resource.d.ts.map +1 -0
- package/dist/analysis/temporal-resource.js +292 -0
- package/dist/analysis/temporal-resource.js.map +1 -0
- package/dist/application/check.d.ts +16 -0
- package/dist/application/check.d.ts.map +1 -1
- package/dist/application/check.js +51 -0
- package/dist/application/check.js.map +1 -1
- package/dist/application/contract4.d.ts +17 -0
- package/dist/application/contract4.d.ts.map +1 -0
- package/dist/application/contract4.js +27 -0
- package/dist/application/contract4.js.map +1 -0
- package/dist/application/contract5-governance.d.ts +8 -0
- package/dist/application/contract5-governance.d.ts.map +1 -0
- package/dist/application/contract5-governance.js +12 -0
- package/dist/application/contract5-governance.js.map +1 -0
- package/dist/application/init.d.ts +3 -11
- package/dist/application/init.d.ts.map +1 -1
- package/dist/application/init.js +16 -129
- package/dist/application/init.js.map +1 -1
- package/dist/application/mutate.d.ts +19 -0
- package/dist/application/mutate.d.ts.map +1 -1
- package/dist/application/mutate.js +34 -16
- package/dist/application/mutate.js.map +1 -1
- package/dist/application/next.d.ts +2 -0
- package/dist/application/next.d.ts.map +1 -1
- package/dist/application/next.js +7 -1
- package/dist/application/next.js.map +1 -1
- package/dist/application/project.d.ts +4 -22
- package/dist/application/project.d.ts.map +1 -1
- package/dist/application/project.js +3 -51
- package/dist/application/project.js.map +1 -1
- package/dist/application/target-check.d.ts +34 -0
- package/dist/application/target-check.d.ts.map +1 -0
- package/dist/application/target-check.js +90 -0
- package/dist/application/target-check.js.map +1 -0
- package/dist/application/target-governance-init.d.ts +36 -0
- package/dist/application/target-governance-init.d.ts.map +1 -0
- package/dist/application/target-governance-init.js +185 -0
- package/dist/application/target-governance-init.js.map +1 -0
- package/dist/application/target-governance-mutation.d.ts +20 -0
- package/dist/application/target-governance-mutation.d.ts.map +1 -0
- package/dist/application/target-governance-mutation.js +175 -0
- package/dist/application/target-governance-mutation.js.map +1 -0
- package/dist/application/target-governance-project.d.ts +34 -0
- package/dist/application/target-governance-project.d.ts.map +1 -0
- package/dist/application/target-governance-project.js +80 -0
- package/dist/application/target-governance-project.js.map +1 -0
- package/dist/application/target-governance-projection.d.ts +18 -0
- package/dist/application/target-governance-projection.d.ts.map +1 -0
- package/dist/application/target-governance-projection.js +248 -0
- package/dist/application/target-governance-projection.js.map +1 -0
- package/dist/application/target-governance-write.d.ts +17 -0
- package/dist/application/target-governance-write.d.ts.map +1 -0
- package/dist/application/target-governance-write.js +55 -0
- package/dist/application/target-governance-write.js.map +1 -0
- package/dist/application/target-grammar-boundary.d.ts +22 -0
- package/dist/application/target-grammar-boundary.d.ts.map +1 -0
- package/dist/application/target-grammar-boundary.js +91 -0
- package/dist/application/target-grammar-boundary.js.map +1 -0
- package/dist/application/target-mutate.d.ts +10 -0
- package/dist/application/target-mutate.d.ts.map +1 -0
- package/dist/application/target-mutate.js +81 -0
- package/dist/application/target-mutate.js.map +1 -0
- package/dist/application/target-project.d.ts +28 -0
- package/dist/application/target-project.d.ts.map +1 -0
- package/dist/application/target-project.js +60 -0
- package/dist/application/target-project.js.map +1 -0
- package/dist/application/target-temporal-analysis.d.ts +140 -0
- package/dist/application/target-temporal-analysis.d.ts.map +1 -0
- package/dist/application/target-temporal-analysis.js +414 -0
- package/dist/application/target-temporal-analysis.js.map +1 -0
- package/dist/application/target-temporal-input.d.ts +86 -0
- package/dist/application/target-temporal-input.d.ts.map +1 -0
- package/dist/application/target-temporal-input.js +240 -0
- package/dist/application/target-temporal-input.js.map +1 -0
- package/dist/application/target-unit-migration-candidate.d.ts +60 -0
- package/dist/application/target-unit-migration-candidate.d.ts.map +1 -0
- package/dist/application/target-unit-migration-candidate.js +294 -0
- package/dist/application/target-unit-migration-candidate.js.map +1 -0
- package/dist/application/target-unit-migration-request.d.ts +35 -0
- package/dist/application/target-unit-migration-request.d.ts.map +1 -0
- package/dist/application/target-unit-migration-request.js +70 -0
- package/dist/application/target-unit-migration-request.js.map +1 -0
- package/dist/application/target-unit-migration-result.d.ts +66 -0
- package/dist/application/target-unit-migration-result.d.ts.map +1 -0
- package/dist/application/target-unit-migration-result.js +86 -0
- package/dist/application/target-unit-migration-result.js.map +1 -0
- package/dist/application/unit-migration.d.ts +16 -0
- package/dist/application/unit-migration.d.ts.map +1 -0
- package/dist/application/unit-migration.js +11 -0
- package/dist/application/unit-migration.js.map +1 -0
- package/dist/cli.js +383 -132
- package/dist/cli.js.map +1 -1
- package/dist/command/discovery.d.ts +3 -3
- package/dist/command/discovery.d.ts.map +1 -1
- package/dist/command/discovery.js +149 -22
- package/dist/command/discovery.js.map +1 -1
- package/dist/command/registry.d.ts +8 -2
- package/dist/command/registry.d.ts.map +1 -1
- package/dist/command/registry.js +14 -1
- package/dist/command/registry.js.map +1 -1
- package/dist/command/target-governance-discovery.d.ts +31 -0
- package/dist/command/target-governance-discovery.d.ts.map +1 -0
- package/dist/command/target-governance-discovery.js +390 -0
- package/dist/command/target-governance-discovery.js.map +1 -0
- package/dist/command/target-governance-usage.d.ts +22 -0
- package/dist/command/target-governance-usage.d.ts.map +1 -0
- package/dist/command/target-governance-usage.js +116 -0
- package/dist/command/target-governance-usage.js.map +1 -0
- package/dist/command/usage.d.ts +2 -0
- package/dist/command/usage.d.ts.map +1 -1
- package/dist/command/usage.js +44 -26
- package/dist/command/usage.js.map +1 -1
- package/dist/conversion/mermaid-import.d.ts.map +1 -1
- package/dist/conversion/mermaid-import.js +3 -2
- package/dist/conversion/mermaid-import.js.map +1 -1
- package/dist/conversion/mermaid.d.ts.map +1 -1
- package/dist/conversion/mermaid.js +27 -0
- package/dist/conversion/mermaid.js.map +1 -1
- package/dist/formatter/source-formatter.d.ts +12 -0
- package/dist/formatter/source-formatter.d.ts.map +1 -1
- package/dist/formatter/source-formatter.js +59 -6
- package/dist/formatter/source-formatter.js.map +1 -1
- package/dist/formatter/target-source-formatter.d.ts +9 -0
- package/dist/formatter/target-source-formatter.d.ts.map +1 -0
- package/dist/formatter/target-source-formatter.js +52 -0
- package/dist/formatter/target-source-formatter.js.map +1 -0
- package/dist/governance/authority.d.ts +21 -0
- package/dist/governance/authority.d.ts.map +1 -0
- package/dist/governance/authority.js +206 -0
- package/dist/governance/authority.js.map +1 -0
- package/dist/governance/guidance.d.ts +2 -0
- package/dist/governance/guidance.d.ts.map +1 -0
- package/dist/governance/guidance.js +2 -0
- package/dist/governance/guidance.js.map +1 -0
- package/dist/governance/source.d.ts +37 -0
- package/dist/governance/source.d.ts.map +1 -0
- package/dist/governance/source.js +103 -0
- package/dist/governance/source.js.map +1 -0
- package/dist/governance/types.d.ts +41 -0
- package/dist/governance/types.d.ts.map +1 -0
- package/dist/governance/types.js +2 -0
- package/dist/governance/types.js.map +1 -0
- package/dist/help/guide.d.ts +8 -5
- package/dist/help/guide.d.ts.map +1 -1
- package/dist/help/guide.js +1 -1
- package/dist/help/guide.js.map +1 -1
- package/dist/help/registry.d.ts.map +1 -1
- package/dist/help/registry.js +124 -13
- package/dist/help/registry.js.map +1 -1
- package/dist/help/target-governance-guide.d.ts +10 -0
- package/dist/help/target-governance-guide.d.ts.map +1 -0
- package/dist/help/target-governance-guide.js +57 -0
- package/dist/help/target-governance-guide.js.map +1 -0
- package/dist/index.d.ts +25 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/io/safe-write.d.ts +11 -0
- package/dist/io/safe-write.d.ts.map +1 -1
- package/dist/io/safe-write.js +40 -10
- package/dist/io/safe-write.js.map +1 -1
- package/dist/io/target-safe-write.d.ts +10 -0
- package/dist/io/target-safe-write.d.ts.map +1 -0
- package/dist/io/target-safe-write.js +51 -0
- package/dist/io/target-safe-write.js.map +1 -0
- package/dist/migration/conversion.d.ts +40 -0
- package/dist/migration/conversion.d.ts.map +1 -0
- package/dist/migration/conversion.js +106 -0
- package/dist/migration/conversion.js.map +1 -0
- package/dist/migration/grammar-boundary.d.ts +20 -0
- package/dist/migration/grammar-boundary.d.ts.map +1 -0
- package/dist/migration/grammar-boundary.js +95 -0
- package/dist/migration/grammar-boundary.js.map +1 -0
- package/dist/migration/request.d.ts +79 -0
- package/dist/migration/request.d.ts.map +1 -0
- package/dist/migration/request.js +308 -0
- package/dist/migration/request.js.map +1 -0
- package/dist/model/calendar-arithmetic.d.ts +46 -0
- package/dist/model/calendar-arithmetic.d.ts.map +1 -0
- package/dist/model/calendar-arithmetic.js +236 -0
- package/dist/model/calendar-arithmetic.js.map +1 -0
- package/dist/model/calendar.d.ts +22 -0
- package/dist/model/calendar.d.ts.map +1 -0
- package/dist/model/calendar.js +83 -0
- package/dist/model/calendar.js.map +1 -0
- package/dist/model/declaration-fields.d.ts +22 -0
- package/dist/model/declaration-fields.d.ts.map +1 -0
- package/dist/model/declaration-fields.js +72 -0
- package/dist/model/declaration-fields.js.map +1 -0
- package/dist/model/exact-duration-source.d.ts +10 -0
- package/dist/model/exact-duration-source.d.ts.map +1 -0
- package/dist/model/exact-duration-source.js +69 -0
- package/dist/model/exact-duration-source.js.map +1 -0
- package/dist/model/rational.d.ts +2 -2
- package/dist/model/rational.d.ts.map +1 -1
- package/dist/model/rational.js +3 -1
- package/dist/model/rational.js.map +1 -1
- package/dist/model/syntax.d.ts +9 -2
- package/dist/model/syntax.d.ts.map +1 -1
- package/dist/model/syntax.js +20 -4
- package/dist/model/syntax.js.map +1 -1
- package/dist/model/target-calendar.d.ts +25 -0
- package/dist/model/target-calendar.d.ts.map +1 -0
- package/dist/model/target-calendar.js +56 -0
- package/dist/model/target-calendar.js.map +1 -0
- package/dist/mutation/advance.d.ts +11 -0
- package/dist/mutation/advance.d.ts.map +1 -1
- package/dist/mutation/advance.js +37 -7
- package/dist/mutation/advance.js.map +1 -1
- package/dist/mutation/milestone.d.ts +10 -1
- package/dist/mutation/milestone.d.ts.map +1 -1
- package/dist/mutation/milestone.js +77 -21
- package/dist/mutation/milestone.js.map +1 -1
- package/dist/mutation/project.d.ts +11 -1
- package/dist/mutation/project.d.ts.map +1 -1
- package/dist/mutation/project.js +117 -11
- package/dist/mutation/project.js.map +1 -1
- package/dist/mutation/target-types.d.ts +59 -0
- package/dist/mutation/target-types.d.ts.map +1 -0
- package/dist/mutation/target-types.js +2 -0
- package/dist/mutation/target-types.js.map +1 -0
- package/dist/mutation/task.d.ts +12 -1
- package/dist/mutation/task.d.ts.map +1 -1
- package/dist/mutation/task.js +108 -49
- package/dist/mutation/task.js.map +1 -1
- package/dist/mutation/types.d.ts +16 -3
- package/dist/mutation/types.d.ts.map +1 -1
- package/dist/parser/document-parser.d.ts +21 -0
- package/dist/parser/document-parser.d.ts.map +1 -1
- package/dist/parser/document-parser.js +197 -38
- package/dist/parser/document-parser.js.map +1 -1
- package/dist/recommendation/override-types.d.ts +2 -2
- package/dist/recommendation/override.d.ts +2 -2
- package/dist/recommendation/override.d.ts.map +1 -1
- package/dist/recommendation/override.js +49 -12
- package/dist/recommendation/override.js.map +1 -1
- package/dist/semantic/target-validator.d.ts +46 -0
- package/dist/semantic/target-validator.d.ts.map +1 -0
- package/dist/semantic/target-validator.js +130 -0
- package/dist/semantic/target-validator.js.map +1 -0
- package/dist/semantic/validator.d.ts +3 -0
- package/dist/semantic/validator.d.ts.map +1 -1
- package/dist/semantic/validator.js +78 -5
- package/dist/semantic/validator.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,20 +2,23 @@
|
|
|
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 } from "./application/
|
|
5
|
+
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 {
|
|
10
|
-
import { selectNextTasks } from "./application/next.js";
|
|
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 {
|
|
17
|
+
import { getTargetGovernanceGuide, renderTargetGovernanceGuideResult, serializeTargetGovernanceGuideResult, } from "./help/target-governance-guide.js";
|
|
16
18
|
import { commandOptionSets, } from "./command/registry.js";
|
|
17
|
-
import {
|
|
18
|
-
import { handlerCommandUsageError,
|
|
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 {
|
|
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 =
|
|
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
|
}
|
|
@@ -182,6 +185,18 @@ async function readStdin() {
|
|
|
182
185
|
function writeJson(value) {
|
|
183
186
|
process.stdout.write(`${JSON.stringify(value)}\n`);
|
|
184
187
|
}
|
|
188
|
+
function snakeJson(value) {
|
|
189
|
+
if (typeof value === "bigint")
|
|
190
|
+
return value.toString();
|
|
191
|
+
if (Array.isArray(value))
|
|
192
|
+
return value.map(snakeJson);
|
|
193
|
+
if (value === null || typeof value !== "object")
|
|
194
|
+
return value;
|
|
195
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [
|
|
196
|
+
key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase(),
|
|
197
|
+
snakeJson(item),
|
|
198
|
+
]));
|
|
199
|
+
}
|
|
185
200
|
function cliError(error, exitCode, operation, json) {
|
|
186
201
|
const code = error instanceof UsageError
|
|
187
202
|
? error.code
|
|
@@ -205,7 +220,7 @@ function cliError(error, exitCode, operation, json) {
|
|
|
205
220
|
if (json) {
|
|
206
221
|
writeJson({
|
|
207
222
|
schema_version: "Perttool.CliError.v1",
|
|
208
|
-
cli_contract_version:
|
|
223
|
+
cli_contract_version: 5,
|
|
209
224
|
tool_version: TOOL_VERSION,
|
|
210
225
|
operation,
|
|
211
226
|
ok: false,
|
|
@@ -240,8 +255,8 @@ async function runCheck(args) {
|
|
|
240
255
|
const ok = result.ok && !warningFailure;
|
|
241
256
|
if (format === "json") {
|
|
242
257
|
writeJson({
|
|
243
|
-
schema_version: "Perttool.CheckResult.
|
|
244
|
-
cli_contract_version:
|
|
258
|
+
schema_version: "Perttool.CheckResult.v2",
|
|
259
|
+
cli_contract_version: 5,
|
|
245
260
|
tool_version: TOOL_VERSION,
|
|
246
261
|
operation: "document.check",
|
|
247
262
|
ok,
|
|
@@ -252,11 +267,12 @@ async function runCheck(args) {
|
|
|
252
267
|
diagnostics_truncated: result.diagnosticsTruncated,
|
|
253
268
|
grammar_version: result.grammarVersion,
|
|
254
269
|
summary: result.summary,
|
|
270
|
+
temporal_inputs: snakeJson(result.temporalInputs),
|
|
255
271
|
});
|
|
256
272
|
}
|
|
257
273
|
else {
|
|
258
274
|
if (ok) {
|
|
259
|
-
process.stdout.write(`OK ${source} project=${result.documentId ?? "-"} milestones=${result.summary.milestones} tasks=${result.summary.tasks} gates=${result.summary.gates} resources=${result.summary.resources}\n`);
|
|
275
|
+
process.stdout.write(`OK ${source} project=${result.documentId ?? "-"} milestones=${result.summary.milestones} tasks=${result.summary.tasks} gates=${result.summary.gates} resources=${result.summary.resources} temporal=milestone_deadlines:${result.temporalInputs?.milestoneDeadlines.length ?? 0},task_not_before:${result.temporalInputs?.taskConstraints.filter(({ notBefore }) => notBefore !== null).length ?? 0},task_deadlines:${result.temporalInputs?.taskConstraints.filter(({ deadline }) => deadline !== null).length ?? 0}\n`);
|
|
260
276
|
}
|
|
261
277
|
for (const diagnostic of result.diagnostics) {
|
|
262
278
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
@@ -267,36 +283,6 @@ async function runCheck(args) {
|
|
|
267
283
|
}
|
|
268
284
|
return ok ? 0 : 1;
|
|
269
285
|
}
|
|
270
|
-
function projectJson(project) {
|
|
271
|
-
return {
|
|
272
|
-
id: project.id,
|
|
273
|
-
version: project.version,
|
|
274
|
-
title: project.title,
|
|
275
|
-
description: project.description,
|
|
276
|
-
as_of: project.asOf,
|
|
277
|
-
duration_unit: project.durationUnit,
|
|
278
|
-
velocity: project.velocity,
|
|
279
|
-
finish: project.finish,
|
|
280
|
-
critical_epsilon: project.criticalEpsilon,
|
|
281
|
-
target_duration: project.targetDuration,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
function renderProjectText(project) {
|
|
285
|
-
const optional = (value) => value ?? "-";
|
|
286
|
-
return [
|
|
287
|
-
`PROJECT ${project.id}`,
|
|
288
|
-
`VERSION ${project.version}`,
|
|
289
|
-
`TITLE ${JSON.stringify(project.title)}`,
|
|
290
|
-
`DESCRIPTION ${project.description === null ? "-" : JSON.stringify(project.description)}`,
|
|
291
|
-
`AS_OF ${optional(project.asOf)}`,
|
|
292
|
-
`DURATION_UNIT ${project.durationUnit}`,
|
|
293
|
-
`VELOCITY ${optional(project.velocity)}`,
|
|
294
|
-
`FINISH ${project.finish}`,
|
|
295
|
-
`CRITICAL_EPSILON ${optional(project.criticalEpsilon)}`,
|
|
296
|
-
`TARGET_DURATION ${optional(project.targetDuration)}`,
|
|
297
|
-
"",
|
|
298
|
-
].join("\n");
|
|
299
|
-
}
|
|
300
286
|
async function runProjectShow(args) {
|
|
301
287
|
const parsed = parseCommandOptions("project.show", args);
|
|
302
288
|
if (parsed.positionals.length !== 1) {
|
|
@@ -320,24 +306,11 @@ async function runProjectShow(args) {
|
|
|
320
306
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
321
307
|
const ok = result.ok && !warningFailure;
|
|
322
308
|
if (format === "json") {
|
|
323
|
-
writeJson(
|
|
324
|
-
schema_version: "Perttool.ProjectResult.v1",
|
|
325
|
-
cli_contract_version: 3,
|
|
326
|
-
tool_version: TOOL_VERSION,
|
|
327
|
-
operation: "project.show",
|
|
328
|
-
ok,
|
|
329
|
-
document_id: result.documentId,
|
|
330
|
-
source,
|
|
331
|
-
source_digest: input.digest,
|
|
332
|
-
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
333
|
-
diagnostics_truncated: result.diagnosticsTruncated,
|
|
334
|
-
grammar_version: result.grammarVersion,
|
|
335
|
-
project: result.project === null ? null : projectJson(result.project),
|
|
336
|
-
});
|
|
309
|
+
writeJson(targetGovernanceProjectResultToJson(result, source, input.digest, ok));
|
|
337
310
|
}
|
|
338
311
|
else {
|
|
339
312
|
if (ok && result.project !== null) {
|
|
340
|
-
process.stdout.write(
|
|
313
|
+
process.stdout.write(renderTargetGovernanceProjectText(result.project));
|
|
341
314
|
}
|
|
342
315
|
for (const diagnostic of result.diagnostics) {
|
|
343
316
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
@@ -368,6 +341,27 @@ async function runProjectInit(args) {
|
|
|
368
341
|
...(parsed.values.get("velocity") === undefined
|
|
369
342
|
? {}
|
|
370
343
|
: { velocity: parsed.values.get("velocity") }),
|
|
344
|
+
...(parsed.values.get("initial-milestone-deadline") === undefined
|
|
345
|
+
? {}
|
|
346
|
+
: {
|
|
347
|
+
initialMilestoneDeadline: parsed.values.get("initial-milestone-deadline"),
|
|
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
|
+
}),
|
|
371
365
|
});
|
|
372
366
|
let writeResult = null;
|
|
373
367
|
const output = parsed.values.get("out");
|
|
@@ -471,6 +465,39 @@ function editingWriteRequest(parsed, sourceOperand, check = false) {
|
|
|
471
465
|
return { mode: "out", target: out };
|
|
472
466
|
return { mode: "preview", target: null };
|
|
473
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
|
+
}
|
|
474
501
|
function assertExpectedDigest(request, initialDigest) {
|
|
475
502
|
if (request.mode === "in_place" &&
|
|
476
503
|
request.expectedDigest !== undefined &&
|
|
@@ -503,6 +530,9 @@ function writeFailureExit(error, operation, json) {
|
|
|
503
530
|
function renderWriteSummary(operation, result) {
|
|
504
531
|
return `WRITE ${operation} mode=${result.mode} target=${result.target} digest=${result.digest} written=${result.written}\n`;
|
|
505
532
|
}
|
|
533
|
+
function renderGovernanceWriteSummary(operation, result, digest) {
|
|
534
|
+
return `WRITE ${operation} mode=${result.mode} target=${result.target ?? "-"} digest=${digest ?? "-"} written=${result.written}\n`;
|
|
535
|
+
}
|
|
506
536
|
async function runFormat(args) {
|
|
507
537
|
const parsed = parseCommandOptions("document.format", args);
|
|
508
538
|
if (parsed.positionals.length !== 1) {
|
|
@@ -546,7 +576,7 @@ async function runFormat(args) {
|
|
|
546
576
|
if (format === "json") {
|
|
547
577
|
writeJson({
|
|
548
578
|
schema_version: "Perttool.FormatResult.v1",
|
|
549
|
-
cli_contract_version:
|
|
579
|
+
cli_contract_version: 5,
|
|
550
580
|
tool_version: TOOL_VERSION,
|
|
551
581
|
operation: "document.format",
|
|
552
582
|
ok,
|
|
@@ -614,6 +644,12 @@ function uniqueRepeated(parsed, option) {
|
|
|
614
644
|
}
|
|
615
645
|
return values;
|
|
616
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
|
+
}
|
|
617
653
|
function enumRepeated(parsed, option, allowed) {
|
|
618
654
|
return uniqueRepeated(parsed, option).map((value) => {
|
|
619
655
|
if (!allowed.has(value)) {
|
|
@@ -700,6 +736,12 @@ function taskMutationFromOptions(action, parsed) {
|
|
|
700
736
|
...(parsed.values.get("description") === undefined
|
|
701
737
|
? {}
|
|
702
738
|
: { description: parsed.values.get("description") }),
|
|
739
|
+
...(parsed.values.get("not-before") === undefined
|
|
740
|
+
? {}
|
|
741
|
+
: { notBefore: parsed.values.get("not-before") }),
|
|
742
|
+
...(parsed.values.get("deadline") === undefined
|
|
743
|
+
? {}
|
|
744
|
+
: { deadline: parsed.values.get("deadline") }),
|
|
703
745
|
...(status === undefined ? {} : { status }),
|
|
704
746
|
...(priority === undefined ? {} : { priority }),
|
|
705
747
|
...(requirements.length === 0 ? {} : { requirements }),
|
|
@@ -720,7 +762,7 @@ function taskMutationFromOptions(action, parsed) {
|
|
|
720
762
|
}
|
|
721
763
|
const clear = enumRepeated(parsed, "clear", new Set([
|
|
722
764
|
"description", "status", "priority", "owner", "blocked_reason", "source",
|
|
723
|
-
"tags", "requires",
|
|
765
|
+
"tags", "requires", "not_before", "deadline",
|
|
724
766
|
]));
|
|
725
767
|
const addTags = uniqueRepeated(parsed, "add-tag");
|
|
726
768
|
const removeTags = uniqueRepeated(parsed, "remove-tag");
|
|
@@ -735,6 +777,12 @@ function taskMutationFromOptions(action, parsed) {
|
|
|
735
777
|
? {}
|
|
736
778
|
: { description: parsed.values.get("description") }),
|
|
737
779
|
...timing,
|
|
780
|
+
...(parsed.values.get("not-before") === undefined
|
|
781
|
+
? {}
|
|
782
|
+
: { notBefore: parsed.values.get("not-before") }),
|
|
783
|
+
...(parsed.values.get("deadline") === undefined
|
|
784
|
+
? {}
|
|
785
|
+
: { deadline: parsed.values.get("deadline") }),
|
|
738
786
|
...(status === undefined ? {} : { status }),
|
|
739
787
|
...(priority === undefined ? {} : { priority }),
|
|
740
788
|
...(parsed.values.get("owner") === undefined
|
|
@@ -749,6 +797,8 @@ function taskMutationFromOptions(action, parsed) {
|
|
|
749
797
|
};
|
|
750
798
|
const clearConflicts = new Map([
|
|
751
799
|
["description", parsed.values.has("description")],
|
|
800
|
+
["not_before", parsed.values.has("not-before")],
|
|
801
|
+
["deadline", parsed.values.has("deadline")],
|
|
752
802
|
["status", status !== undefined],
|
|
753
803
|
["priority", priority !== undefined],
|
|
754
804
|
["owner", parsed.values.has("owner")],
|
|
@@ -786,6 +836,10 @@ function projectMutationFromOptions(parsed) {
|
|
|
786
836
|
"velocity",
|
|
787
837
|
"critical_epsilon",
|
|
788
838
|
"target_duration",
|
|
839
|
+
"goal_owner",
|
|
840
|
+
"goal_delegates",
|
|
841
|
+
"dag_owner",
|
|
842
|
+
"dag_delegates",
|
|
789
843
|
]));
|
|
790
844
|
const conflicts = new Map([
|
|
791
845
|
["description", parsed.values.has("description")],
|
|
@@ -793,6 +847,10 @@ function projectMutationFromOptions(parsed) {
|
|
|
793
847
|
["velocity", parsed.values.has("velocity")],
|
|
794
848
|
["critical_epsilon", parsed.values.has("critical-epsilon")],
|
|
795
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")],
|
|
796
854
|
]);
|
|
797
855
|
const conflict = clear.find((field) => conflicts.get(field) === true);
|
|
798
856
|
if (conflict !== undefined) {
|
|
@@ -823,6 +881,22 @@ function projectMutationFromOptions(parsed) {
|
|
|
823
881
|
...(parsed.values.get("target-duration") === undefined
|
|
824
882
|
? {}
|
|
825
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
|
+
}),
|
|
826
900
|
};
|
|
827
901
|
return {
|
|
828
902
|
kind: "project.set",
|
|
@@ -848,18 +922,22 @@ function milestoneMutationFromOptions(action, parsed) {
|
|
|
848
922
|
? {}
|
|
849
923
|
: { description: parsed.values.get("description") }),
|
|
850
924
|
...(state === undefined ? {} : { state }),
|
|
925
|
+
...(parsed.values.get("deadline") === undefined
|
|
926
|
+
? {}
|
|
927
|
+
: { deadline: parsed.values.get("deadline") }),
|
|
851
928
|
...((parsed.repeatedValues.get("tag") ?? []).length === 0
|
|
852
929
|
? {}
|
|
853
930
|
: { tags: parsed.repeatedValues.get("tag") }),
|
|
854
931
|
},
|
|
855
932
|
};
|
|
856
933
|
}
|
|
857
|
-
const clear = enumRepeated(parsed, "clear", new Set(["description", "state", "tags"]));
|
|
934
|
+
const clear = enumRepeated(parsed, "clear", new Set(["description", "state", "deadline", "tags"]));
|
|
858
935
|
const addTags = uniqueRepeated(parsed, "add-tag");
|
|
859
936
|
const removeTags = uniqueRepeated(parsed, "remove-tag");
|
|
860
937
|
ensureDisjoint(addTags, "add-tag", removeTags, "remove-tag");
|
|
861
938
|
if (clear.some((field) => (field === "description" && parsed.values.has("description")) ||
|
|
862
939
|
(field === "state" && state !== undefined) ||
|
|
940
|
+
(field === "deadline" && parsed.values.has("deadline")) ||
|
|
863
941
|
(field === "tags" && (addTags.length > 0 || removeTags.length > 0)))) {
|
|
864
942
|
throw new UsageError("--clear conflicts with another milestone field option");
|
|
865
943
|
}
|
|
@@ -871,6 +949,9 @@ function milestoneMutationFromOptions(action, parsed) {
|
|
|
871
949
|
? {}
|
|
872
950
|
: { description: parsed.values.get("description") }),
|
|
873
951
|
...(state === undefined ? {} : { state }),
|
|
952
|
+
...(parsed.values.get("deadline") === undefined
|
|
953
|
+
? {}
|
|
954
|
+
: { deadline: parsed.values.get("deadline") }),
|
|
874
955
|
};
|
|
875
956
|
return {
|
|
876
957
|
kind: "milestone.set",
|
|
@@ -1040,20 +1121,24 @@ async function runMutation(resource, action, args) {
|
|
|
1040
1121
|
maxDiagnostics,
|
|
1041
1122
|
originalLabel: source,
|
|
1042
1123
|
updatedLabel: "candidate",
|
|
1124
|
+
governance: governanceRequest(parsed, writeRequest),
|
|
1043
1125
|
};
|
|
1044
1126
|
const result = resource === "batch"
|
|
1045
|
-
?
|
|
1046
|
-
:
|
|
1127
|
+
? planTargetGovernanceBatchMutation(input.text, mutation, TARGET_GRAMMAR_4_CAPABILITY, mutationOptions)
|
|
1128
|
+
: planTargetGovernanceMutation(input.text, mutation, TARGET_GRAMMAR_4_CAPABILITY, mutationOptions);
|
|
1047
1129
|
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1048
1130
|
(result.diagnosticsTruncated ||
|
|
1049
1131
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
1050
1132
|
const ok = result.ok && !warningFailure;
|
|
1051
|
-
let writeResult =
|
|
1133
|
+
let writeResult = Object.freeze({
|
|
1134
|
+
mode: writeRequest.mode,
|
|
1135
|
+
target: writeRequest.target,
|
|
1136
|
+
written: false,
|
|
1137
|
+
});
|
|
1052
1138
|
if (result.ok) {
|
|
1053
1139
|
try {
|
|
1054
|
-
assertExpectedDigest(writeRequest, input.digest);
|
|
1055
1140
|
if (ok && writeRequest.mode !== "preview") {
|
|
1056
|
-
writeResult = await
|
|
1141
|
+
writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
|
|
1057
1142
|
}
|
|
1058
1143
|
}
|
|
1059
1144
|
catch (error) {
|
|
@@ -1061,24 +1146,12 @@ async function runMutation(resource, action, args) {
|
|
|
1061
1146
|
}
|
|
1062
1147
|
}
|
|
1063
1148
|
if (format === "json") {
|
|
1064
|
-
writeJson({
|
|
1065
|
-
schema_version: "Perttool.MutationResult.v1",
|
|
1066
|
-
cli_contract_version: 3,
|
|
1067
|
-
tool_version: TOOL_VERSION,
|
|
1068
|
-
operation,
|
|
1069
|
-
ok,
|
|
1070
|
-
document_id: result.documentId,
|
|
1071
|
-
source,
|
|
1072
|
-
source_digest: input.digest,
|
|
1073
|
-
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
1074
|
-
diagnostics_truncated: result.diagnosticsTruncated,
|
|
1075
|
-
...previewResultJson(result, result.ok, writeRequest, writeResult),
|
|
1076
|
-
});
|
|
1149
|
+
writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
|
|
1077
1150
|
}
|
|
1078
1151
|
else {
|
|
1079
1152
|
if (ok) {
|
|
1080
|
-
if (
|
|
1081
|
-
process.stderr.write(
|
|
1153
|
+
if (writeRequest.mode !== "preview") {
|
|
1154
|
+
process.stderr.write(renderGovernanceWriteSummary(operation, writeResult, result.updatedDigest));
|
|
1082
1155
|
}
|
|
1083
1156
|
else {
|
|
1084
1157
|
process.stdout.write(parsed.flags.has("diff") ? (result.diff ?? "") : (result.updatedText ?? ""));
|
|
@@ -1087,6 +1160,9 @@ async function runMutation(resource, action, args) {
|
|
|
1087
1160
|
}
|
|
1088
1161
|
}
|
|
1089
1162
|
}
|
|
1163
|
+
if (result.governance !== null) {
|
|
1164
|
+
process.stderr.write(renderTargetGovernanceDecision(result.governance));
|
|
1165
|
+
}
|
|
1090
1166
|
for (const diagnostic of result.diagnostics) {
|
|
1091
1167
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
1092
1168
|
}
|
|
@@ -1096,18 +1172,141 @@ async function runMutation(resource, action, args) {
|
|
|
1096
1172
|
}
|
|
1097
1173
|
return ok ? 0 : 1;
|
|
1098
1174
|
}
|
|
1099
|
-
function
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
:
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1175
|
+
function unitMigrationJson(result, source, sourceDigest, ok) {
|
|
1176
|
+
const exact = (value) => ({
|
|
1177
|
+
numerator: value.numerator.toString(),
|
|
1178
|
+
denominator: value.denominator.toString(),
|
|
1179
|
+
unit: value.unit,
|
|
1180
|
+
});
|
|
1181
|
+
return {
|
|
1182
|
+
schema_version: result.schemaVersion,
|
|
1183
|
+
cli_contract_version: 5,
|
|
1184
|
+
tool_version: TOOL_VERSION,
|
|
1185
|
+
operation: "project.migrate-unit",
|
|
1186
|
+
ok,
|
|
1187
|
+
document_id: result.documentId,
|
|
1188
|
+
source,
|
|
1189
|
+
source_digest: sourceDigest,
|
|
1190
|
+
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
1191
|
+
diagnostics_truncated: result.diagnosticsTruncated,
|
|
1192
|
+
unit_migration: result.unitMigration,
|
|
1193
|
+
source_grammar_version: result.sourceGrammarVersion,
|
|
1194
|
+
target_grammar_version: result.targetGrammarVersion,
|
|
1195
|
+
grammar_disposition: result.grammarDisposition,
|
|
1196
|
+
source_unit: result.sourceUnit,
|
|
1197
|
+
target_unit: result.targetUnit,
|
|
1198
|
+
effective_velocity: result.effectiveVelocity === null
|
|
1199
|
+
? null
|
|
1200
|
+
: {
|
|
1201
|
+
points: exact(result.effectiveVelocity.points),
|
|
1202
|
+
period: exact(result.effectiveVelocity.period),
|
|
1203
|
+
},
|
|
1204
|
+
velocity_disposition: result.velocityDisposition,
|
|
1205
|
+
changed: result.changed,
|
|
1206
|
+
converted_fields: result.convertedFields.map((field) => ({
|
|
1207
|
+
entity_kind: field.entityKind,
|
|
1208
|
+
entity_id: field.entityId,
|
|
1209
|
+
field_path: field.fieldPath,
|
|
1210
|
+
original: exact(field.original),
|
|
1211
|
+
converted: exact(field.converted),
|
|
1212
|
+
canonical_token: field.canonicalToken,
|
|
1213
|
+
})),
|
|
1214
|
+
reversibility: result.reversibility,
|
|
1215
|
+
qualifications: result.qualifications,
|
|
1216
|
+
unavailable_causes: result.unavailableCauses.map((cause) => ({
|
|
1217
|
+
cause: cause.cause,
|
|
1218
|
+
diagnostic_code: cause.diagnosticCode,
|
|
1219
|
+
field_paths: cause.fieldPaths,
|
|
1220
|
+
})),
|
|
1221
|
+
original_digest: result.originalDigest,
|
|
1222
|
+
updated_digest: result.updatedDigest,
|
|
1223
|
+
updated_text: result.updatedText,
|
|
1224
|
+
diff: result.diff,
|
|
1225
|
+
edits: result.edits.map((edit) => ({
|
|
1226
|
+
start_offset: edit.startOffset,
|
|
1227
|
+
end_offset: edit.endOffset,
|
|
1228
|
+
replacement: edit.replacement,
|
|
1229
|
+
})),
|
|
1230
|
+
write: {
|
|
1231
|
+
mode: result.write.mode,
|
|
1232
|
+
target: result.write.target,
|
|
1233
|
+
written: result.write.written,
|
|
1234
|
+
},
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
async function runUnitMigration(args) {
|
|
1238
|
+
const parsed = parseCommandOptions("project.migrate-unit", args);
|
|
1239
|
+
if (parsed.positionals.length !== 1) {
|
|
1240
|
+
throw new UsageError("project migrate-unit requires exactly one <file>");
|
|
1241
|
+
}
|
|
1242
|
+
const format = outputFormat(parsed.values.get("format"));
|
|
1243
|
+
const color = colorMode(parsed.values.get("color"), format);
|
|
1244
|
+
const targetUnit = enumOption(requiredOption(parsed, "to-unit"), "to-unit", new Set(["day", "hour", "point"]));
|
|
1245
|
+
const maxDiagnostics = boundedInteger(parsed.values.get("max-diagnostics"), "max-diagnostics", 100, 1, 1000);
|
|
1246
|
+
const sourceOperand = parsed.positionals[0];
|
|
1247
|
+
const writeRequest = editingWriteRequest(parsed, sourceOperand);
|
|
1248
|
+
const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
|
|
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, "project.migrate-unit", format === "json");
|
|
1255
|
+
}
|
|
1256
|
+
let result = planUnitMigration(input.text, {
|
|
1257
|
+
targetUnit,
|
|
1258
|
+
...(parsed.values.get("replacement-velocity") === undefined
|
|
1259
|
+
? {}
|
|
1260
|
+
: {
|
|
1261
|
+
replacementVelocity: parsed.values.get("replacement-velocity"),
|
|
1262
|
+
}),
|
|
1263
|
+
}, {
|
|
1264
|
+
maxDiagnostics,
|
|
1265
|
+
originalLabel: source,
|
|
1266
|
+
updatedLabel: "candidate",
|
|
1267
|
+
});
|
|
1268
|
+
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1269
|
+
(result.diagnosticsTruncated ||
|
|
1270
|
+
result.diagnostics.some(({ severity }) => severity === "warning"));
|
|
1271
|
+
const ok = result.ok && !warningFailure;
|
|
1272
|
+
let writeResult = null;
|
|
1273
|
+
if (result.ok) {
|
|
1274
|
+
try {
|
|
1275
|
+
assertExpectedDigest(writeRequest, input.digest);
|
|
1276
|
+
if (ok && writeRequest.mode !== "preview") {
|
|
1277
|
+
writeResult = await commitCandidate(writeRequest, result.updatedText, input.digest);
|
|
1278
|
+
result = withUnitMigrationWrite(result, writeResult);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
catch (error) {
|
|
1282
|
+
return writeFailureExit(error, "project.migrate-unit", format === "json");
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
if (format === "json") {
|
|
1286
|
+
writeJson(unitMigrationJson(result, source, input.digest, ok));
|
|
1287
|
+
}
|
|
1288
|
+
else {
|
|
1289
|
+
if (ok) {
|
|
1290
|
+
if (writeResult !== null) {
|
|
1291
|
+
process.stderr.write(renderWriteSummary("project.migrate-unit", writeResult));
|
|
1292
|
+
}
|
|
1293
|
+
else {
|
|
1294
|
+
process.stdout.write(parsed.flags.has("diff")
|
|
1295
|
+
? (result.diff ?? "")
|
|
1296
|
+
: (result.updatedText ?? ""));
|
|
1297
|
+
if (!parsed.flags.has("diff")) {
|
|
1298
|
+
process.stderr.write(`PREVIEW project.migrate-unit changed=${result.changed} source_unit=${result.sourceUnit ?? "-"} target_unit=${result.targetUnit} original_digest=${result.originalDigest} updated_digest=${result.updatedDigest ?? "-"}\n`);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
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;
|
|
1111
1310
|
}
|
|
1112
1311
|
function renderAdvanceSummary(details) {
|
|
1113
1312
|
const list = (ids) => ids.join(",") || "-";
|
|
@@ -1135,21 +1334,25 @@ async function runAdvance(args) {
|
|
|
1135
1334
|
catch (error) {
|
|
1136
1335
|
return cliError(error instanceof Error ? error : new Error(String(error)), 3, "dag.advance", format === "json");
|
|
1137
1336
|
}
|
|
1138
|
-
const result =
|
|
1337
|
+
const result = planTargetGovernanceAdvance(input.text, TARGET_GRAMMAR_4_CAPABILITY, {
|
|
1139
1338
|
maxDiagnostics,
|
|
1140
1339
|
originalLabel: source,
|
|
1141
1340
|
updatedLabel: "candidate",
|
|
1341
|
+
governance: governanceRequest(parsed, writeRequest),
|
|
1142
1342
|
});
|
|
1143
1343
|
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1144
1344
|
(result.diagnosticsTruncated ||
|
|
1145
1345
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
1146
1346
|
const ok = result.ok && !warningFailure;
|
|
1147
|
-
let writeResult =
|
|
1347
|
+
let writeResult = Object.freeze({
|
|
1348
|
+
mode: writeRequest.mode,
|
|
1349
|
+
target: writeRequest.target,
|
|
1350
|
+
written: false,
|
|
1351
|
+
});
|
|
1148
1352
|
if (result.ok) {
|
|
1149
1353
|
try {
|
|
1150
|
-
assertExpectedDigest(writeRequest, input.digest);
|
|
1151
1354
|
if (ok && writeRequest.mode !== "preview") {
|
|
1152
|
-
writeResult = await
|
|
1355
|
+
writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
|
|
1153
1356
|
}
|
|
1154
1357
|
}
|
|
1155
1358
|
catch (error) {
|
|
@@ -1157,25 +1360,12 @@ async function runAdvance(args) {
|
|
|
1157
1360
|
}
|
|
1158
1361
|
}
|
|
1159
1362
|
if (format === "json") {
|
|
1160
|
-
writeJson({
|
|
1161
|
-
schema_version: "Perttool.MutationResult.v1",
|
|
1162
|
-
cli_contract_version: 3,
|
|
1163
|
-
tool_version: TOOL_VERSION,
|
|
1164
|
-
operation: "dag.advance",
|
|
1165
|
-
ok,
|
|
1166
|
-
document_id: result.documentId,
|
|
1167
|
-
source,
|
|
1168
|
-
source_digest: input.digest,
|
|
1169
|
-
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
1170
|
-
diagnostics_truncated: result.diagnosticsTruncated,
|
|
1171
|
-
...previewResultJson(result, result.ok, writeRequest, writeResult),
|
|
1172
|
-
advance: advanceResultJson(result.advance),
|
|
1173
|
-
});
|
|
1363
|
+
writeJson(targetGovernanceMutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
|
|
1174
1364
|
}
|
|
1175
1365
|
else {
|
|
1176
1366
|
if (ok && result.advance !== null) {
|
|
1177
|
-
if (
|
|
1178
|
-
process.stderr.write(
|
|
1367
|
+
if (writeRequest.mode !== "preview") {
|
|
1368
|
+
process.stderr.write(renderGovernanceWriteSummary("dag.advance", writeResult, result.updatedDigest));
|
|
1179
1369
|
}
|
|
1180
1370
|
else {
|
|
1181
1371
|
process.stdout.write(parsed.flags.has("diff") ? (result.diff ?? "") : (result.updatedText ?? ""));
|
|
@@ -1185,6 +1375,9 @@ async function runAdvance(args) {
|
|
|
1185
1375
|
}
|
|
1186
1376
|
process.stderr.write(renderAdvanceSummary(result.advance));
|
|
1187
1377
|
}
|
|
1378
|
+
if (result.governance !== null) {
|
|
1379
|
+
process.stderr.write(renderTargetGovernanceDecision(result.governance));
|
|
1380
|
+
}
|
|
1188
1381
|
for (const diagnostic of result.diagnostics) {
|
|
1189
1382
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
1190
1383
|
}
|
|
@@ -1437,6 +1630,41 @@ function renderAnalysisText(result) {
|
|
|
1437
1630
|
if (resource.resources.length === 0)
|
|
1438
1631
|
lines.push("-");
|
|
1439
1632
|
}
|
|
1633
|
+
if (result.temporal !== null) {
|
|
1634
|
+
const temporalPoint = (point) => {
|
|
1635
|
+
const causes = point.unavailableCauses
|
|
1636
|
+
.map(({ cause }) => cause)
|
|
1637
|
+
.join(",") || "-";
|
|
1638
|
+
return [
|
|
1639
|
+
`state=${point.state}`,
|
|
1640
|
+
`relative=${point.relative === null ? "-" : `${point.relative.numerator}/${point.relative.denominator}${durationSuffix(point.relative.unit)}`}`,
|
|
1641
|
+
`calendar=${point.calendar?.sourceText ?? "-"}`,
|
|
1642
|
+
`causes=${causes}`,
|
|
1643
|
+
].join(" ");
|
|
1644
|
+
};
|
|
1645
|
+
for (const [title, projection] of [
|
|
1646
|
+
["TEMPORAL PRECEDENCE", result.temporal.precedence],
|
|
1647
|
+
["TEMPORAL RESOURCE", result.temporal.resource],
|
|
1648
|
+
]) {
|
|
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(",") || "-"}`);
|
|
1650
|
+
for (const task of projection.tasks) {
|
|
1651
|
+
lines.push(`${task.taskId} START ${temporalPoint(task.start)} FINISH ${temporalPoint(task.finish)}`);
|
|
1652
|
+
}
|
|
1653
|
+
if (projection.tasks.length === 0)
|
|
1654
|
+
lines.push("-");
|
|
1655
|
+
}
|
|
1656
|
+
lines.push("", "DEADLINES");
|
|
1657
|
+
for (const evaluation of result.temporal.deadlineEvaluations) {
|
|
1658
|
+
const causes = [
|
|
1659
|
+
...evaluation.current.unavailableCauses,
|
|
1660
|
+
...evaluation.precedence.unavailableCauses,
|
|
1661
|
+
...evaluation.resource.unavailableCauses,
|
|
1662
|
+
].map(({ cause }) => cause).join(",") || "-";
|
|
1663
|
+
lines.push(`${evaluation.subject.kind}:${evaluation.subject.id} assessment=${evaluation.combinedAssessment} precedence=${evaluation.precedence.assessment ?? evaluation.precedence.state} resource=${evaluation.resource.assessment ?? evaluation.resource.state} conditional=${evaluation.conditionalOnBlocksResolved} causes=${causes}`);
|
|
1664
|
+
}
|
|
1665
|
+
if (result.temporal.deadlineEvaluations.length === 0)
|
|
1666
|
+
lines.push("-");
|
|
1667
|
+
}
|
|
1440
1668
|
return `${lines.join("\n")}\n`;
|
|
1441
1669
|
}
|
|
1442
1670
|
async function runAnalyze(args) {
|
|
@@ -1473,8 +1701,8 @@ async function runAnalyze(args) {
|
|
|
1473
1701
|
const ok = result.ok && !warningFailure;
|
|
1474
1702
|
if (format === "json") {
|
|
1475
1703
|
writeJson({
|
|
1476
|
-
schema_version: "Perttool.AnalysisResult.
|
|
1477
|
-
cli_contract_version:
|
|
1704
|
+
schema_version: "Perttool.AnalysisResult.v3",
|
|
1705
|
+
cli_contract_version: 5,
|
|
1478
1706
|
tool_version: TOOL_VERSION,
|
|
1479
1707
|
operation: "dag.analyze",
|
|
1480
1708
|
ok,
|
|
@@ -1483,6 +1711,7 @@ async function runAnalyze(args) {
|
|
|
1483
1711
|
source_digest: input.digest,
|
|
1484
1712
|
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
1485
1713
|
diagnostics_truncated: result.diagnosticsTruncated,
|
|
1714
|
+
grammar_version: result.grammarVersion,
|
|
1486
1715
|
mode: result.mode,
|
|
1487
1716
|
precision: result.precision,
|
|
1488
1717
|
...(result.durationUnit === null
|
|
@@ -1499,6 +1728,7 @@ async function runAnalyze(args) {
|
|
|
1499
1728
|
resource: result.resource === null || result.durationUnit === null
|
|
1500
1729
|
? null
|
|
1501
1730
|
: resourceJson(result.resource, result.durationUnit, result.precision),
|
|
1731
|
+
temporal: snakeJson(result.temporal),
|
|
1502
1732
|
});
|
|
1503
1733
|
}
|
|
1504
1734
|
else {
|
|
@@ -1586,7 +1816,7 @@ async function runRender(args) {
|
|
|
1586
1816
|
if (format === "json") {
|
|
1587
1817
|
writeJson({
|
|
1588
1818
|
schema_version: "Perttool.ExportResult.v1",
|
|
1589
|
-
cli_contract_version:
|
|
1819
|
+
cli_contract_version: 5,
|
|
1590
1820
|
tool_version: TOOL_VERSION,
|
|
1591
1821
|
operation: "dag.render",
|
|
1592
1822
|
ok,
|
|
@@ -1678,7 +1908,7 @@ async function runImport(args) {
|
|
|
1678
1908
|
if (format === "json") {
|
|
1679
1909
|
writeJson({
|
|
1680
1910
|
schema_version: "Perttool.ImportResult.v1",
|
|
1681
|
-
cli_contract_version:
|
|
1911
|
+
cli_contract_version: 5,
|
|
1682
1912
|
tool_version: TOOL_VERSION,
|
|
1683
1913
|
operation: "dag.import",
|
|
1684
1914
|
ok,
|
|
@@ -1895,7 +2125,15 @@ function renderExplanation(node, indent) {
|
|
|
1895
2125
|
function renderNextText(result) {
|
|
1896
2126
|
const unit = result.durationUnit;
|
|
1897
2127
|
const taskById = new Map(result.tasks.map((task) => [task.id, task]));
|
|
2128
|
+
const authority = result.temporal.authority;
|
|
1898
2129
|
const lines = [
|
|
2130
|
+
"START AUTHORITY",
|
|
2131
|
+
`POLICY ${authority.policy}`,
|
|
2132
|
+
`STARTABLE RECOMMENDED ${authority.startableRecommendedTaskIds.join(",") || "-"}`,
|
|
2133
|
+
`DELAYED RECOMMENDED ${authority.delayedRecommendedTaskIds.join(",") || "-"}`,
|
|
2134
|
+
`UNAVAILABLE RECOMMENDED ${authority.unavailableRecommendedTaskIds.join(",") || "-"}`,
|
|
2135
|
+
"DEADLINE FACTS INFORMATIONAL FOR RANKING v1",
|
|
2136
|
+
"",
|
|
1899
2137
|
`PERTTOOL NEXT ${result.documentId ?? "-"}`,
|
|
1900
2138
|
`VELOCITY ${result.velocity === null ? "-" : velocityText(result.velocity, result.precision)}`,
|
|
1901
2139
|
`VELOCITY_FORECAST_UNIT ${result.velocityForecast?.targetUnit ?? "-"}`,
|
|
@@ -1934,6 +2172,15 @@ function renderNextText(result) {
|
|
|
1934
2172
|
section("READY / WAITING RESOURCE", result.groups.ready.filter((id) => !result.groups.runnableNow.includes(id)), "rejection");
|
|
1935
2173
|
section("BLOCKED NOW", result.groups.blockedNow, "blocked");
|
|
1936
2174
|
section("UPCOMING", result.groups.upcoming, "explanation");
|
|
2175
|
+
lines.push("", "TEMPORAL CONTEXT");
|
|
2176
|
+
for (const temporal of result.temporal.tasks) {
|
|
2177
|
+
const causes = temporal.timeEligibility.unavailableCauses
|
|
2178
|
+
.map(({ cause }) => cause)
|
|
2179
|
+
.join(",") || "-";
|
|
2180
|
+
lines.push(`${temporal.taskId} eligibility=${temporal.timeEligibility.state} release=${temporal.timeEligibility.releaseBound === null ? "-" : `${temporal.timeEligibility.releaseBound.numerator}/${temporal.timeEligibility.releaseBound.denominator}${durationSuffix(temporal.timeEligibility.releaseBound.unit)}`} task_deadline=${temporal.taskDeadline?.sourceText ?? "-"} destination=${temporal.destinationMilestoneId} destination_deadline=${temporal.destinationDeadline?.sourceText ?? "-"} causes=${causes}`);
|
|
2181
|
+
}
|
|
2182
|
+
if (result.temporal.tasks.length === 0)
|
|
2183
|
+
lines.push("-");
|
|
1937
2184
|
return `${lines.join("\n")}\n`;
|
|
1938
2185
|
}
|
|
1939
2186
|
async function runNext(args) {
|
|
@@ -1968,7 +2215,7 @@ async function runNext(args) {
|
|
|
1968
2215
|
if (format === "json") {
|
|
1969
2216
|
writeJson({
|
|
1970
2217
|
schema_version: "Perttool.CliError.v1",
|
|
1971
|
-
cli_contract_version:
|
|
2218
|
+
cli_contract_version: 5,
|
|
1972
2219
|
tool_version: TOOL_VERSION,
|
|
1973
2220
|
operation: "dag.next",
|
|
1974
2221
|
ok: false,
|
|
@@ -1988,8 +2235,8 @@ async function runNext(args) {
|
|
|
1988
2235
|
const ok = result.ok && !warningFailure;
|
|
1989
2236
|
if (format === "json") {
|
|
1990
2237
|
writeJson({
|
|
1991
|
-
schema_version: "Perttool.NextResult.
|
|
1992
|
-
cli_contract_version:
|
|
2238
|
+
schema_version: "Perttool.NextResult.v4",
|
|
2239
|
+
cli_contract_version: 5,
|
|
1993
2240
|
recommendation_interface_version: 1,
|
|
1994
2241
|
tool_version: TOOL_VERSION,
|
|
1995
2242
|
operation: "dag.next",
|
|
@@ -1999,7 +2246,9 @@ async function runNext(args) {
|
|
|
1999
2246
|
source_digest: input.digest,
|
|
2000
2247
|
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
2001
2248
|
diagnostics_truncated: result.diagnosticsTruncated,
|
|
2249
|
+
grammar_version: result.grammarVersion,
|
|
2002
2250
|
...(result.durationUnit === null ? {} : nextJson(result)),
|
|
2251
|
+
temporal: snakeJson(result.temporal),
|
|
2003
2252
|
});
|
|
2004
2253
|
}
|
|
2005
2254
|
else {
|
|
@@ -2023,12 +2272,12 @@ function runGuide(args) {
|
|
|
2023
2272
|
colorMode(parsed.values.get("color"), format);
|
|
2024
2273
|
const topicId = parsed.positionals.length === 0 ? null : parsed.positionals.join(".");
|
|
2025
2274
|
const level = helpLevel(parsed.values.get("level"), topicId !== null);
|
|
2026
|
-
const result =
|
|
2275
|
+
const result = getTargetGovernanceGuide(topicId, level);
|
|
2027
2276
|
if (format === "json") {
|
|
2028
|
-
process.stdout.write(
|
|
2277
|
+
process.stdout.write(serializeTargetGovernanceGuideResult(result));
|
|
2029
2278
|
}
|
|
2030
2279
|
else {
|
|
2031
|
-
const rendered =
|
|
2280
|
+
const rendered = renderTargetGovernanceGuideResult(result);
|
|
2032
2281
|
if (result.ok) {
|
|
2033
2282
|
process.stdout.write(rendered);
|
|
2034
2283
|
}
|
|
@@ -2044,15 +2293,15 @@ function runCommandHelp(args) {
|
|
|
2044
2293
|
throw new UsageError("help accepts at most <resource> <action>");
|
|
2045
2294
|
}
|
|
2046
2295
|
const format = outputFormat(parsed.values.get("format"));
|
|
2047
|
-
const result =
|
|
2296
|
+
const result = getTargetGovernanceCommandDiscovery({
|
|
2048
2297
|
resource: parsed.positionals[0] ?? null,
|
|
2049
2298
|
action: parsed.positionals[1] ?? null,
|
|
2050
2299
|
});
|
|
2051
2300
|
if (format === "json") {
|
|
2052
|
-
process.stdout.write(
|
|
2301
|
+
process.stdout.write(serializeTargetGovernanceCommandHelpResult(result));
|
|
2053
2302
|
}
|
|
2054
2303
|
else {
|
|
2055
|
-
const rendered =
|
|
2304
|
+
const rendered = renderTargetGovernanceCommandHelpResult(result);
|
|
2056
2305
|
if (result.ok) {
|
|
2057
2306
|
process.stdout.write(rendered);
|
|
2058
2307
|
}
|
|
@@ -2082,7 +2331,7 @@ function runAgentHelp(args) {
|
|
|
2082
2331
|
const { schema_version: schemaVersion, ...payload } = projected;
|
|
2083
2332
|
writeJson({
|
|
2084
2333
|
schema_version: schemaVersion,
|
|
2085
|
-
cli_contract_version:
|
|
2334
|
+
cli_contract_version: 5,
|
|
2086
2335
|
...payload,
|
|
2087
2336
|
});
|
|
2088
2337
|
}
|
|
@@ -2120,6 +2369,8 @@ async function dispatchCommand(descriptor, args) {
|
|
|
2120
2369
|
return runProjectInit(args);
|
|
2121
2370
|
case "project.show":
|
|
2122
2371
|
return runProjectShow(args);
|
|
2372
|
+
case "project.migrate-unit":
|
|
2373
|
+
return runUnitMigration(args);
|
|
2123
2374
|
case "dag.analyze":
|
|
2124
2375
|
return runAnalyze(args);
|
|
2125
2376
|
case "dag.next":
|
|
@@ -2138,14 +2389,14 @@ async function dispatchCommand(descriptor, args) {
|
|
|
2138
2389
|
const [resource, action] = descriptor.path;
|
|
2139
2390
|
return runMutation(resource, action, args);
|
|
2140
2391
|
}
|
|
2141
|
-
throw new Error(`no Contract
|
|
2392
|
+
throw new Error(`no Contract 5 handler for ${descriptor.operation}`);
|
|
2142
2393
|
}
|
|
2143
2394
|
function emitCommandUsage(error, json) {
|
|
2144
2395
|
if (json) {
|
|
2145
|
-
process.stdout.write(
|
|
2396
|
+
process.stdout.write(serializeTargetGovernanceCommandUsageError(error));
|
|
2146
2397
|
}
|
|
2147
2398
|
else {
|
|
2148
|
-
process.stderr.write(
|
|
2399
|
+
process.stderr.write(renderTargetGovernanceCommandUsageError(error));
|
|
2149
2400
|
}
|
|
2150
2401
|
return 2;
|
|
2151
2402
|
}
|
|
@@ -2157,13 +2408,13 @@ async function main(argv) {
|
|
|
2157
2408
|
if (argv.length === 1 && argv[0] === "--help") {
|
|
2158
2409
|
return runCommandHelp([]);
|
|
2159
2410
|
}
|
|
2160
|
-
const validation =
|
|
2411
|
+
const validation = validateTargetGovernanceCommandInvocation(argv);
|
|
2161
2412
|
if (!validation.ok) {
|
|
2162
2413
|
if (jsonRequested(argv)) {
|
|
2163
|
-
process.stdout.write(
|
|
2414
|
+
process.stdout.write(serializeTargetGovernanceCommandUsageError(validation.error));
|
|
2164
2415
|
}
|
|
2165
2416
|
else {
|
|
2166
|
-
process.stderr.write(
|
|
2417
|
+
process.stderr.write(renderTargetGovernanceCommandUsageError(validation.error));
|
|
2167
2418
|
}
|
|
2168
2419
|
return 2;
|
|
2169
2420
|
}
|