perttool 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -1
- package/README.md +134 -24
- package/dist/actuals/lifecycle.d.ts +101 -0
- package/dist/actuals/lifecycle.d.ts.map +1 -0
- package/dist/actuals/lifecycle.js +329 -0
- package/dist/actuals/lifecycle.js.map +1 -0
- package/dist/actuals/source.d.ts +36 -0
- package/dist/actuals/source.d.ts.map +1 -0
- package/dist/actuals/source.js +119 -0
- package/dist/actuals/source.js.map +1 -0
- package/dist/analysis/temporal-deadline.d.ts +2 -2
- package/dist/analysis/temporal-deadline.d.ts.map +1 -1
- package/dist/analysis/temporal-deadline.js.map +1 -1
- package/dist/analysis/temporal-precedence.d.ts +2 -2
- package/dist/analysis/temporal-precedence.d.ts.map +1 -1
- package/dist/analysis/temporal-precedence.js +2 -0
- package/dist/analysis/temporal-precedence.js.map +1 -1
- package/dist/analysis/temporal-resource.d.ts +2 -2
- package/dist/analysis/temporal-resource.d.ts.map +1 -1
- package/dist/analysis/temporal-resource.js +2 -0
- package/dist/analysis/temporal-resource.js.map +1 -1
- package/dist/application/analyze.d.ts +1 -0
- package/dist/application/analyze.d.ts.map +1 -1
- package/dist/application/analyze.js +38 -29
- package/dist/application/analyze.js.map +1 -1
- package/dist/application/check.d.ts +3 -0
- package/dist/application/check.d.ts.map +1 -1
- package/dist/application/check.js +17 -1
- package/dist/application/check.js.map +1 -1
- package/dist/application/contract4.js +3 -3
- 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/contract6-actuals.d.ts +24 -0
- package/dist/application/contract6-actuals.d.ts.map +1 -0
- package/dist/application/contract6-actuals.js +51 -0
- package/dist/application/contract6-actuals.js.map +1 -0
- package/dist/application/contract6-mutation.d.ts +18 -0
- package/dist/application/contract6-mutation.d.ts.map +1 -0
- package/dist/application/contract6-mutation.js +173 -0
- package/dist/application/contract6-mutation.js.map +1 -0
- package/dist/application/contract6-projection.d.ts +9 -0
- package/dist/application/contract6-projection.d.ts.map +1 -0
- package/dist/application/contract6-projection.js +105 -0
- package/dist/application/contract6-projection.js.map +1 -0
- package/dist/application/init.d.ts +3 -12
- package/dist/application/init.d.ts.map +1 -1
- package/dist/application/init.js +16 -138
- package/dist/application/init.js.map +1 -1
- package/dist/application/project.d.ts +4 -24
- package/dist/application/project.d.ts.map +1 -1
- package/dist/application/project.js +3 -52
- package/dist/application/project.js.map +1 -1
- package/dist/application/target-actuals-advance.d.ts +12 -0
- package/dist/application/target-actuals-advance.d.ts.map +1 -0
- package/dist/application/target-actuals-advance.js +113 -0
- package/dist/application/target-actuals-advance.js.map +1 -0
- package/dist/application/target-actuals-analysis.d.ts +76 -0
- package/dist/application/target-actuals-analysis.d.ts.map +1 -0
- package/dist/application/target-actuals-analysis.js +250 -0
- package/dist/application/target-actuals-analysis.js.map +1 -0
- package/dist/application/target-actuals-mutation.d.ts +28 -0
- package/dist/application/target-actuals-mutation.d.ts.map +1 -0
- package/dist/application/target-actuals-mutation.js +404 -0
- package/dist/application/target-actuals-mutation.js.map +1 -0
- package/dist/application/target-actuals-write.d.ts +7 -0
- package/dist/application/target-actuals-write.d.ts.map +1 -0
- package/dist/application/target-actuals-write.js +37 -0
- package/dist/application/target-actuals-write.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 +195 -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 +82 -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 +25 -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-mutate.d.ts +6 -2
- package/dist/application/target-mutate.d.ts.map +1 -1
- package/dist/application/target-mutate.js +59 -2
- package/dist/application/target-mutate.js.map +1 -1
- package/dist/application/target-project-history.d.ts +18 -0
- package/dist/application/target-project-history.d.ts.map +1 -0
- package/dist/application/target-project-history.js +279 -0
- package/dist/application/target-project-history.js.map +1 -0
- package/dist/application/target-temporal-analysis.d.ts +13 -5
- package/dist/application/target-temporal-analysis.d.ts.map +1 -1
- package/dist/application/target-temporal-analysis.js +18 -11
- package/dist/application/target-temporal-analysis.js.map +1 -1
- package/dist/application/target-temporal-input.d.ts +8 -6
- package/dist/application/target-temporal-input.d.ts.map +1 -1
- package/dist/application/target-temporal-input.js +14 -3
- package/dist/application/target-temporal-input.js.map +1 -1
- package/dist/application/target-unit-migration-candidate.d.ts +2 -2
- package/dist/application/target-unit-migration-candidate.d.ts.map +1 -1
- package/dist/application/target-unit-migration-candidate.js +21 -6
- package/dist/application/target-unit-migration-candidate.js.map +1 -1
- package/dist/application/target-unit-migration-request.d.ts +4 -4
- package/dist/application/target-unit-migration-request.d.ts.map +1 -1
- package/dist/application/target-unit-migration-request.js +6 -2
- package/dist/application/target-unit-migration-request.js.map +1 -1
- package/dist/application/target-unit-migration-result.d.ts +5 -5
- package/dist/application/target-unit-migration-result.d.ts.map +1 -1
- package/dist/application/target-unit-migration-result.js +1 -1
- package/dist/application/target-unit-migration-result.js.map +1 -1
- package/dist/application/target-velocity-observation.d.ts +11 -0
- package/dist/application/target-velocity-observation.d.ts.map +1 -0
- package/dist/application/target-velocity-observation.js +201 -0
- package/dist/application/target-velocity-observation.js.map +1 -0
- package/dist/application/unit-migration.d.ts +4 -1
- package/dist/application/unit-migration.d.ts.map +1 -1
- package/dist/application/unit-migration.js +5 -3
- package/dist/application/unit-migration.js.map +1 -1
- package/dist/cli.js +390 -137
- package/dist/cli.js.map +1 -1
- package/dist/command/actuals-discovery.d.ts +26 -0
- package/dist/command/actuals-discovery.d.ts.map +1 -0
- package/dist/command/actuals-discovery.js +271 -0
- package/dist/command/actuals-discovery.js.map +1 -0
- package/dist/command/actuals-usage.d.ts +22 -0
- package/dist/command/actuals-usage.d.ts.map +1 -0
- package/dist/command/actuals-usage.js +122 -0
- package/dist/command/actuals-usage.js.map +1 -0
- package/dist/command/registry.d.ts +7 -1
- package/dist/command/registry.d.ts.map +1 -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 +43 -25
- 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 +3 -3
- package/dist/formatter/source-formatter.d.ts.map +1 -1
- package/dist/formatter/source-formatter.js +64 -5
- package/dist/formatter/source-formatter.js.map +1 -1
- package/dist/formatter/target-source-formatter.d.ts +3 -1
- package/dist/formatter/target-source-formatter.d.ts.map +1 -1
- package/dist/formatter/target-source-formatter.js +34 -2
- package/dist/formatter/target-source-formatter.js.map +1 -1
- package/dist/governance/authority.d.ts +25 -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/actuals-guide.d.ts +10 -0
- package/dist/help/actuals-guide.d.ts.map +1 -0
- package/dist/help/actuals-guide.js +23 -0
- package/dist/help/actuals-guide.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.map +1 -1
- package/dist/help/registry.d.ts.map +1 -1
- package/dist/help/registry.js +98 -8
- 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/history/git-probe.d.ts +52 -0
- package/dist/history/git-probe.d.ts.map +1 -0
- package/dist/history/git-probe.js +565 -0
- package/dist/history/git-probe.js.map +1 -0
- package/dist/history/project-history.d.ts +112 -0
- package/dist/history/project-history.d.ts.map +1 -0
- package/dist/history/project-history.js +786 -0
- package/dist/history/project-history.js.map +1 -0
- package/dist/history/velocity-observation.d.ts +69 -0
- package/dist/history/velocity-observation.d.ts.map +1 -0
- package/dist/history/velocity-observation.js +604 -0
- package/dist/history/velocity-observation.js.map +1 -0
- package/dist/index.d.ts +28 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -7
- package/dist/index.js.map +1 -1
- package/dist/io/safe-write.d.ts +4 -0
- package/dist/io/safe-write.d.ts.map +1 -1
- package/dist/io/safe-write.js +22 -1
- package/dist/io/safe-write.js.map +1 -1
- package/dist/io/target-safe-write.d.ts +8 -2
- package/dist/io/target-safe-write.d.ts.map +1 -1
- package/dist/io/target-safe-write.js +38 -2
- package/dist/io/target-safe-write.js.map +1 -1
- package/dist/migration/conversion.d.ts +1 -1
- package/dist/migration/conversion.d.ts.map +1 -1
- package/dist/migration/grammar-boundary.d.ts +1 -1
- package/dist/migration/grammar-boundary.d.ts.map +1 -1
- package/dist/migration/grammar-boundary.js +15 -4
- package/dist/migration/grammar-boundary.js.map +1 -1
- package/dist/migration/request.d.ts +5 -5
- package/dist/migration/request.d.ts.map +1 -1
- package/dist/migration/request.js +15 -2
- package/dist/migration/request.js.map +1 -1
- package/dist/model/calendar.d.ts +2 -0
- package/dist/model/calendar.d.ts.map +1 -1
- package/dist/model/calendar.js +19 -0
- package/dist/model/calendar.js.map +1 -1
- package/dist/model/declaration-fields.d.ts +15 -0
- package/dist/model/declaration-fields.d.ts.map +1 -1
- package/dist/model/declaration-fields.js +31 -0
- package/dist/model/declaration-fields.js.map +1 -1
- package/dist/model/exact-person-hours-source.d.ts +2 -0
- package/dist/model/exact-person-hours-source.d.ts.map +1 -0
- package/dist/model/exact-person-hours-source.js +10 -0
- package/dist/model/exact-person-hours-source.js.map +1 -0
- package/dist/model/syntax.d.ts +23 -8
- package/dist/model/syntax.d.ts.map +1 -1
- package/dist/model/syntax.js.map +1 -1
- package/dist/mutation/actuals.d.ts +17 -0
- package/dist/mutation/actuals.d.ts.map +1 -0
- package/dist/mutation/actuals.js +90 -0
- package/dist/mutation/actuals.js.map +1 -0
- package/dist/mutation/advance.d.ts +17 -0
- package/dist/mutation/advance.d.ts.map +1 -1
- package/dist/mutation/advance.js +56 -14
- package/dist/mutation/advance.js.map +1 -1
- package/dist/mutation/entity-editor.d.ts +2 -2
- package/dist/mutation/entity-editor.d.ts.map +1 -1
- package/dist/mutation/entity-editor.js.map +1 -1
- package/dist/mutation/project.d.ts +7 -1
- package/dist/mutation/project.d.ts.map +1 -1
- package/dist/mutation/project.js +108 -6
- package/dist/mutation/project.js.map +1 -1
- package/dist/mutation/source.d.ts +3 -3
- package/dist/mutation/source.d.ts.map +1 -1
- package/dist/mutation/source.js.map +1 -1
- package/dist/mutation/target-types.d.ts +18 -1
- package/dist/mutation/target-types.d.ts.map +1 -1
- package/dist/mutation/types.d.ts +8 -1
- package/dist/mutation/types.d.ts.map +1 -1
- package/dist/parser/document-parser.d.ts +15 -1
- package/dist/parser/document-parser.d.ts.map +1 -1
- package/dist/parser/document-parser.js +205 -22
- 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 +2 -2
- package/dist/recommendation/override.js.map +1 -1
- package/dist/semantic/target-validator.d.ts +23 -2
- package/dist/semantic/target-validator.d.ts.map +1 -1
- package/dist/semantic/target-validator.js +89 -2
- package/dist/semantic/target-validator.js.map +1 -1
- package/dist/semantic/validator.d.ts +5 -1
- package/dist/semantic/validator.d.ts.map +1 -1
- package/dist/semantic/validator.js +180 -6
- package/dist/semantic/validator.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -2,20 +2,26 @@
|
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import process from "node:process";
|
|
4
4
|
import { TextDecoder } from "node:util";
|
|
5
|
-
import { analyzeDocument, selectNextTasks, } from "./application/
|
|
5
|
+
import { analyzeDocument, selectNextTasks, } from "./application/contract6-actuals.js";
|
|
6
6
|
import { checkDocument } from "./application/check.js";
|
|
7
7
|
import { planFormat } from "./application/format.js";
|
|
8
8
|
import { planProjectInit, projectInitResultToJson, renderProjectInitResult, withProjectInitOutput, } from "./application/init.js";
|
|
9
|
-
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 { planAdvance, planBatchMutation, planFinishActuals, planLifecycle, planMutation, } from "./application/contract6-mutation.js";
|
|
12
|
+
import { renderTargetGovernanceDecision, renderTargetGovernanceProjectText, } from "./application/target-governance-projection.js";
|
|
13
|
+
import { contract6MutationResultToJson, contract6ProjectResultToJson, contract6WorkEventToJson, } from "./application/contract6-projection.js";
|
|
14
|
+
import { persistTargetActualsResult, } from "./application/target-actuals-write.js";
|
|
15
|
+
import { inspectTargetProjectHistoryFile, renderTargetProjectHistoryText, targetProjectHistoryResultToJson, } from "./application/target-project-history.js";
|
|
16
|
+
import { observeTargetProjectVelocity, renderTargetVelocityObservationText, targetVelocityObservationResultToJson, } from "./application/target-velocity-observation.js";
|
|
12
17
|
import { getAgentHelp } from "./application/agent-help.js";
|
|
13
18
|
import { exportMermaid, } from "./conversion/mermaid.js";
|
|
14
19
|
import { importMermaid } from "./conversion/mermaid-import.js";
|
|
15
|
-
import {
|
|
20
|
+
import { getActualsGuide, renderActualsGuideResult, serializeActualsGuideResult, } from "./help/actuals-guide.js";
|
|
16
21
|
import { commandOptionSets, } from "./command/registry.js";
|
|
17
|
-
import {
|
|
18
|
-
import { handlerCommandUsageError,
|
|
22
|
+
import { ACTUALS_COMMAND_REGISTRY, getActualsCommandDiscovery, renderActualsCommandHelpResult, serializeActualsCommandHelpResult, } from "./command/actuals-discovery.js";
|
|
23
|
+
import { handlerCommandUsageError, } from "./command/usage.js";
|
|
24
|
+
import { renderActualsCommandUsageError, serializeActualsCommandUsageError, validateActualsCommandInvocation, } from "./command/actuals-usage.js";
|
|
19
25
|
import { agentGuidanceResultToJson } from "./guidance/projection.js";
|
|
20
26
|
import { agentGuidanceExitCode, renderAgentGuidanceText, } from "./guidance/text.js";
|
|
21
27
|
import { documentContentFromBytes, readDocumentFile, } from "./io/document-file.js";
|
|
@@ -24,7 +30,7 @@ import { formatDecimal } from "./model/rational.js";
|
|
|
24
30
|
import { convertWithVelocity, durationSuffix } from "./model/units.js";
|
|
25
31
|
import { recommendationInvariantExitCode } from "./recommendation/failure.js";
|
|
26
32
|
import { recommendationAnalysisToJson } from "./recommendation/json.js";
|
|
27
|
-
import {
|
|
33
|
+
import { TARGET_GRAMMAR_5_CAPABILITY, } from "./parser/document-parser.js";
|
|
28
34
|
import { TOOL_VERSION } from "./version.js";
|
|
29
35
|
class UsageError extends Error {
|
|
30
36
|
code = "PTCLI-001";
|
|
@@ -79,7 +85,7 @@ function parseOptions(args, valueOptions, flagOptions, repeatableOptions = new S
|
|
|
79
85
|
return { positionals, values, repeatedValues, flags };
|
|
80
86
|
}
|
|
81
87
|
function parseCommandOptions(operation, args) {
|
|
82
|
-
const descriptor =
|
|
88
|
+
const descriptor = ACTUALS_COMMAND_REGISTRY.find((candidate) => candidate.operation === operation);
|
|
83
89
|
if (descriptor === undefined) {
|
|
84
90
|
throw new Error(`command descriptor is missing for ${operation}`);
|
|
85
91
|
}
|
|
@@ -217,7 +223,7 @@ function cliError(error, exitCode, operation, json) {
|
|
|
217
223
|
if (json) {
|
|
218
224
|
writeJson({
|
|
219
225
|
schema_version: "Perttool.CliError.v1",
|
|
220
|
-
cli_contract_version:
|
|
226
|
+
cli_contract_version: 6,
|
|
221
227
|
tool_version: TOOL_VERSION,
|
|
222
228
|
operation,
|
|
223
229
|
ok: false,
|
|
@@ -252,8 +258,8 @@ async function runCheck(args) {
|
|
|
252
258
|
const ok = result.ok && !warningFailure;
|
|
253
259
|
if (format === "json") {
|
|
254
260
|
writeJson({
|
|
255
|
-
schema_version:
|
|
256
|
-
cli_contract_version:
|
|
261
|
+
schema_version: result.schemaVersion,
|
|
262
|
+
cli_contract_version: 6,
|
|
257
263
|
tool_version: TOOL_VERSION,
|
|
258
264
|
operation: "document.check",
|
|
259
265
|
ok,
|
|
@@ -265,6 +271,12 @@ async function runCheck(args) {
|
|
|
265
271
|
grammar_version: result.grammarVersion,
|
|
266
272
|
summary: result.summary,
|
|
267
273
|
temporal_inputs: snakeJson(result.temporalInputs),
|
|
274
|
+
actuals_inputs: result.actualsInputs === null
|
|
275
|
+
? null
|
|
276
|
+
: {
|
|
277
|
+
model_version: result.actualsInputs.modelVersion,
|
|
278
|
+
events: result.actualsInputs.events.map(contract6WorkEventToJson),
|
|
279
|
+
},
|
|
268
280
|
});
|
|
269
281
|
}
|
|
270
282
|
else {
|
|
@@ -280,41 +292,6 @@ async function runCheck(args) {
|
|
|
280
292
|
}
|
|
281
293
|
return ok ? 0 : 1;
|
|
282
294
|
}
|
|
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
295
|
async function runProjectShow(args) {
|
|
319
296
|
const parsed = parseCommandOptions("project.show", args);
|
|
320
297
|
if (parsed.positionals.length !== 1) {
|
|
@@ -338,24 +315,11 @@ async function runProjectShow(args) {
|
|
|
338
315
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
339
316
|
const ok = result.ok && !warningFailure;
|
|
340
317
|
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
|
-
});
|
|
318
|
+
writeJson(contract6ProjectResultToJson(result, source, input.digest, ok));
|
|
355
319
|
}
|
|
356
320
|
else {
|
|
357
321
|
if (ok && result.project !== null) {
|
|
358
|
-
process.stdout.write(
|
|
322
|
+
process.stdout.write(renderTargetGovernanceProjectText(result.project));
|
|
359
323
|
}
|
|
360
324
|
for (const diagnostic of result.diagnostics) {
|
|
361
325
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
@@ -391,6 +355,22 @@ async function runProjectInit(args) {
|
|
|
391
355
|
: {
|
|
392
356
|
initialMilestoneDeadline: parsed.values.get("initial-milestone-deadline"),
|
|
393
357
|
}),
|
|
358
|
+
...(parsed.values.get("goal-owner") === undefined
|
|
359
|
+
? {}
|
|
360
|
+
: { goalOwner: parsed.values.get("goal-owner") }),
|
|
361
|
+
...(parsed.values.get("goal-delegates") === undefined
|
|
362
|
+
? {}
|
|
363
|
+
: {
|
|
364
|
+
goalDelegates: principalListOption(parsed.values.get("goal-delegates")),
|
|
365
|
+
}),
|
|
366
|
+
...(parsed.values.get("dag-owner") === undefined
|
|
367
|
+
? {}
|
|
368
|
+
: { dagOwner: parsed.values.get("dag-owner") }),
|
|
369
|
+
...(parsed.values.get("dag-delegates") === undefined
|
|
370
|
+
? {}
|
|
371
|
+
: {
|
|
372
|
+
dagDelegates: principalListOption(parsed.values.get("dag-delegates")),
|
|
373
|
+
}),
|
|
394
374
|
});
|
|
395
375
|
let writeResult = null;
|
|
396
376
|
const output = parsed.values.get("out");
|
|
@@ -494,6 +474,39 @@ function editingWriteRequest(parsed, sourceOperand, check = false) {
|
|
|
494
474
|
return { mode: "out", target: out };
|
|
495
475
|
return { mode: "preview", target: null };
|
|
496
476
|
}
|
|
477
|
+
function governanceRequest(parsed, writeRequest) {
|
|
478
|
+
return Object.freeze({
|
|
479
|
+
intent: writeRequest.mode === "preview"
|
|
480
|
+
? "preview"
|
|
481
|
+
: "persist",
|
|
482
|
+
actor: parsed.values.get("actor") ?? null,
|
|
483
|
+
acceptedByOwner: Object.freeze([
|
|
484
|
+
...(parsed.repeatedValues.get("accepted-by-owner") ?? []),
|
|
485
|
+
]),
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
async function persistGovernedResult(result, request, sourceOperand) {
|
|
489
|
+
if (request.mode === "preview") {
|
|
490
|
+
return Object.freeze({
|
|
491
|
+
mode: "preview",
|
|
492
|
+
target: null,
|
|
493
|
+
written: false,
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
return persistTargetActualsResult(result, TARGET_GRAMMAR_5_CAPABILITY, request.mode === "in_place"
|
|
497
|
+
? {
|
|
498
|
+
mode: "in_place",
|
|
499
|
+
target: request.target,
|
|
500
|
+
...(request.expectedDigest === undefined
|
|
501
|
+
? {}
|
|
502
|
+
: { expectedDigest: request.expectedDigest }),
|
|
503
|
+
}
|
|
504
|
+
: {
|
|
505
|
+
mode: "out",
|
|
506
|
+
source: sourceOperand,
|
|
507
|
+
target: request.target,
|
|
508
|
+
});
|
|
509
|
+
}
|
|
497
510
|
function assertExpectedDigest(request, initialDigest) {
|
|
498
511
|
if (request.mode === "in_place" &&
|
|
499
512
|
request.expectedDigest !== undefined &&
|
|
@@ -526,6 +539,9 @@ function writeFailureExit(error, operation, json) {
|
|
|
526
539
|
function renderWriteSummary(operation, result) {
|
|
527
540
|
return `WRITE ${operation} mode=${result.mode} target=${result.target} digest=${result.digest} written=${result.written}\n`;
|
|
528
541
|
}
|
|
542
|
+
function renderGovernanceWriteSummary(operation, result, digest) {
|
|
543
|
+
return `WRITE ${operation} mode=${result.mode} target=${result.target ?? "-"} digest=${digest ?? "-"} written=${result.written}\n`;
|
|
544
|
+
}
|
|
529
545
|
async function runFormat(args) {
|
|
530
546
|
const parsed = parseCommandOptions("document.format", args);
|
|
531
547
|
if (parsed.positionals.length !== 1) {
|
|
@@ -569,7 +585,7 @@ async function runFormat(args) {
|
|
|
569
585
|
if (format === "json") {
|
|
570
586
|
writeJson({
|
|
571
587
|
schema_version: "Perttool.FormatResult.v1",
|
|
572
|
-
cli_contract_version:
|
|
588
|
+
cli_contract_version: 6,
|
|
573
589
|
tool_version: TOOL_VERSION,
|
|
574
590
|
operation: "document.format",
|
|
575
591
|
ok,
|
|
@@ -613,6 +629,11 @@ function requiredOption(parsed, name) {
|
|
|
613
629
|
throw new UsageError(`option --${name} is required`);
|
|
614
630
|
return value;
|
|
615
631
|
}
|
|
632
|
+
function exactMeasurementToken(value, suffix) {
|
|
633
|
+
return /^(?:[0-9]+(?:\.[0-9]+)?|[0-9]+\/[1-9][0-9]*)$/.test(value)
|
|
634
|
+
? `${value}${suffix}`
|
|
635
|
+
: value;
|
|
636
|
+
}
|
|
616
637
|
function optionalInteger(parsed, name, minimum, maximum) {
|
|
617
638
|
const raw = parsed.values.get(name);
|
|
618
639
|
return raw === undefined
|
|
@@ -637,6 +658,12 @@ function uniqueRepeated(parsed, option) {
|
|
|
637
658
|
}
|
|
638
659
|
return values;
|
|
639
660
|
}
|
|
661
|
+
function principalListOption(value) {
|
|
662
|
+
const interior = value.slice(1, -1).trim();
|
|
663
|
+
return interior === ""
|
|
664
|
+
? Object.freeze([])
|
|
665
|
+
: Object.freeze(interior.split(",").map((item) => item.trim()));
|
|
666
|
+
}
|
|
640
667
|
function enumRepeated(parsed, option, allowed) {
|
|
641
668
|
return uniqueRepeated(parsed, option).map((value) => {
|
|
642
669
|
if (!allowed.has(value)) {
|
|
@@ -823,6 +850,10 @@ function projectMutationFromOptions(parsed) {
|
|
|
823
850
|
"velocity",
|
|
824
851
|
"critical_epsilon",
|
|
825
852
|
"target_duration",
|
|
853
|
+
"goal_owner",
|
|
854
|
+
"goal_delegates",
|
|
855
|
+
"dag_owner",
|
|
856
|
+
"dag_delegates",
|
|
826
857
|
]));
|
|
827
858
|
const conflicts = new Map([
|
|
828
859
|
["description", parsed.values.has("description")],
|
|
@@ -830,6 +861,10 @@ function projectMutationFromOptions(parsed) {
|
|
|
830
861
|
["velocity", parsed.values.has("velocity")],
|
|
831
862
|
["critical_epsilon", parsed.values.has("critical-epsilon")],
|
|
832
863
|
["target_duration", parsed.values.has("target-duration")],
|
|
864
|
+
["goal_owner", parsed.values.has("goal-owner")],
|
|
865
|
+
["goal_delegates", parsed.values.has("goal-delegates")],
|
|
866
|
+
["dag_owner", parsed.values.has("dag-owner")],
|
|
867
|
+
["dag_delegates", parsed.values.has("dag-delegates")],
|
|
833
868
|
]);
|
|
834
869
|
const conflict = clear.find((field) => conflicts.get(field) === true);
|
|
835
870
|
if (conflict !== undefined) {
|
|
@@ -860,6 +895,22 @@ function projectMutationFromOptions(parsed) {
|
|
|
860
895
|
...(parsed.values.get("target-duration") === undefined
|
|
861
896
|
? {}
|
|
862
897
|
: { targetDuration: parsed.values.get("target-duration") }),
|
|
898
|
+
...(parsed.values.get("goal-owner") === undefined
|
|
899
|
+
? {}
|
|
900
|
+
: { goalOwner: parsed.values.get("goal-owner") }),
|
|
901
|
+
...(parsed.values.get("goal-delegates") === undefined
|
|
902
|
+
? {}
|
|
903
|
+
: {
|
|
904
|
+
goalDelegates: principalListOption(parsed.values.get("goal-delegates")),
|
|
905
|
+
}),
|
|
906
|
+
...(parsed.values.get("dag-owner") === undefined
|
|
907
|
+
? {}
|
|
908
|
+
: { dagOwner: parsed.values.get("dag-owner") }),
|
|
909
|
+
...(parsed.values.get("dag-delegates") === undefined
|
|
910
|
+
? {}
|
|
911
|
+
: {
|
|
912
|
+
dagDelegates: principalListOption(parsed.values.get("dag-delegates")),
|
|
913
|
+
}),
|
|
863
914
|
};
|
|
864
915
|
return {
|
|
865
916
|
kind: "project.set",
|
|
@@ -1037,6 +1088,7 @@ async function runMutation(resource, action, args) {
|
|
|
1037
1088
|
let sourceOperand;
|
|
1038
1089
|
let writeRequest;
|
|
1039
1090
|
let mutation;
|
|
1091
|
+
let lifecycleMutation = null;
|
|
1040
1092
|
if (resource === "batch") {
|
|
1041
1093
|
if (parsed.positionals.length !== 1) {
|
|
1042
1094
|
throw new UsageError("batch apply requires exactly one <file>");
|
|
@@ -1071,6 +1123,37 @@ async function runMutation(resource, action, args) {
|
|
|
1071
1123
|
: resourceMutationFromOptions(action, parsed);
|
|
1072
1124
|
sourceOperand = parsed.positionals[0];
|
|
1073
1125
|
writeRequest = editingWriteRequest(parsed, sourceOperand);
|
|
1126
|
+
if (resource === "task" &&
|
|
1127
|
+
action === "finish" &&
|
|
1128
|
+
parsed.values.has("at")) {
|
|
1129
|
+
lifecycleMutation = {
|
|
1130
|
+
kind: "task.finish.actual",
|
|
1131
|
+
taskId: parsed.positionals[1],
|
|
1132
|
+
event: {
|
|
1133
|
+
occurredAt: parsed.values.get("at"),
|
|
1134
|
+
...(parsed.values.get("event-id") === undefined
|
|
1135
|
+
? {}
|
|
1136
|
+
: { id: parsed.values.get("event-id") }),
|
|
1137
|
+
...(parsed.values.get("active-time") === undefined
|
|
1138
|
+
? {}
|
|
1139
|
+
: {
|
|
1140
|
+
activeTime: exactMeasurementToken(parsed.values.get("active-time"), "h"),
|
|
1141
|
+
}),
|
|
1142
|
+
...(parsed.values.get("effort") === undefined
|
|
1143
|
+
? {}
|
|
1144
|
+
: {
|
|
1145
|
+
effort: exactMeasurementToken(parsed.values.get("effort"), "ph"),
|
|
1146
|
+
}),
|
|
1147
|
+
},
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
else if (resource === "task" &&
|
|
1151
|
+
action === "finish" &&
|
|
1152
|
+
(parsed.values.has("event-id") ||
|
|
1153
|
+
parsed.values.has("active-time") ||
|
|
1154
|
+
parsed.values.has("effort"))) {
|
|
1155
|
+
throw new UsageError("--event-id, --active-time, and --effort require --at");
|
|
1156
|
+
}
|
|
1074
1157
|
}
|
|
1075
1158
|
const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
|
|
1076
1159
|
let input;
|
|
@@ -1084,20 +1167,26 @@ async function runMutation(resource, action, args) {
|
|
|
1084
1167
|
maxDiagnostics,
|
|
1085
1168
|
originalLabel: source,
|
|
1086
1169
|
updatedLabel: "candidate",
|
|
1170
|
+
governance: governanceRequest(parsed, writeRequest),
|
|
1087
1171
|
};
|
|
1088
|
-
const result =
|
|
1089
|
-
?
|
|
1090
|
-
:
|
|
1172
|
+
const result = lifecycleMutation !== null
|
|
1173
|
+
? planFinishActuals(input.text, lifecycleMutation, mutationOptions)
|
|
1174
|
+
: resource === "batch"
|
|
1175
|
+
? planBatchMutation(input.text, mutation, mutationOptions)
|
|
1176
|
+
: planMutation(input.text, mutation, mutationOptions);
|
|
1091
1177
|
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1092
1178
|
(result.diagnosticsTruncated ||
|
|
1093
1179
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
1094
1180
|
const ok = result.ok && !warningFailure;
|
|
1095
|
-
let writeResult =
|
|
1181
|
+
let writeResult = Object.freeze({
|
|
1182
|
+
mode: writeRequest.mode,
|
|
1183
|
+
target: writeRequest.target,
|
|
1184
|
+
written: false,
|
|
1185
|
+
});
|
|
1096
1186
|
if (result.ok) {
|
|
1097
1187
|
try {
|
|
1098
|
-
assertExpectedDigest(writeRequest, input.digest);
|
|
1099
1188
|
if (ok && writeRequest.mode !== "preview") {
|
|
1100
|
-
writeResult = await
|
|
1189
|
+
writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
|
|
1101
1190
|
}
|
|
1102
1191
|
}
|
|
1103
1192
|
catch (error) {
|
|
@@ -1105,24 +1194,12 @@ async function runMutation(resource, action, args) {
|
|
|
1105
1194
|
}
|
|
1106
1195
|
}
|
|
1107
1196
|
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
|
-
});
|
|
1197
|
+
writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
|
|
1121
1198
|
}
|
|
1122
1199
|
else {
|
|
1123
1200
|
if (ok) {
|
|
1124
|
-
if (
|
|
1125
|
-
process.stderr.write(
|
|
1201
|
+
if (writeRequest.mode !== "preview") {
|
|
1202
|
+
process.stderr.write(renderGovernanceWriteSummary(operation, writeResult, result.updatedDigest));
|
|
1126
1203
|
}
|
|
1127
1204
|
else {
|
|
1128
1205
|
process.stdout.write(parsed.flags.has("diff") ? (result.diff ?? "") : (result.updatedText ?? ""));
|
|
@@ -1131,6 +1208,97 @@ async function runMutation(resource, action, args) {
|
|
|
1131
1208
|
}
|
|
1132
1209
|
}
|
|
1133
1210
|
}
|
|
1211
|
+
if (result.governance !== null) {
|
|
1212
|
+
process.stderr.write(renderTargetGovernanceDecision(result.governance));
|
|
1213
|
+
}
|
|
1214
|
+
for (const diagnostic of result.diagnostics) {
|
|
1215
|
+
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
1216
|
+
}
|
|
1217
|
+
if (result.diagnosticsTruncated) {
|
|
1218
|
+
process.stderr.write(`DIAGNOSTICS_TRUNCATED true limit=${maxDiagnostics}\n`);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
return ok ? 0 : 1;
|
|
1222
|
+
}
|
|
1223
|
+
async function runLifecycleMutation(action, args) {
|
|
1224
|
+
const operation = `task.${action}`;
|
|
1225
|
+
const parsed = parseCommandOptions(operation, args);
|
|
1226
|
+
if (parsed.positionals.length !== 2) {
|
|
1227
|
+
throw new UsageError(`task ${action} requires <file> <task-id>`);
|
|
1228
|
+
}
|
|
1229
|
+
const format = outputFormat(parsed.values.get("format"));
|
|
1230
|
+
const color = colorMode(parsed.values.get("color"), format);
|
|
1231
|
+
const maxDiagnostics = boundedInteger(parsed.values.get("max-diagnostics"), "max-diagnostics", 100, 1, 1000);
|
|
1232
|
+
const sourceOperand = parsed.positionals[0];
|
|
1233
|
+
const source = sourceOperand === "-" ? "<stdin>" : sourceOperand;
|
|
1234
|
+
const writeRequest = editingWriteRequest(parsed, sourceOperand);
|
|
1235
|
+
const event = {
|
|
1236
|
+
occurredAt: requiredOption(parsed, "at"),
|
|
1237
|
+
...(parsed.values.get("event-id") === undefined
|
|
1238
|
+
? {}
|
|
1239
|
+
: { id: parsed.values.get("event-id") }),
|
|
1240
|
+
...(action !== "suspend" || parsed.values.get("reason") === undefined
|
|
1241
|
+
? {}
|
|
1242
|
+
: { reason: parsed.values.get("reason") }),
|
|
1243
|
+
};
|
|
1244
|
+
const mutation = action === "start"
|
|
1245
|
+
? { kind: "task.start", taskId: parsed.positionals[1], event }
|
|
1246
|
+
: action === "suspend"
|
|
1247
|
+
? { kind: "task.suspend", taskId: parsed.positionals[1], event }
|
|
1248
|
+
: { kind: "task.resume", taskId: parsed.positionals[1], event };
|
|
1249
|
+
let input;
|
|
1250
|
+
try {
|
|
1251
|
+
input = await readDocument(sourceOperand);
|
|
1252
|
+
}
|
|
1253
|
+
catch (error) {
|
|
1254
|
+
return cliError(error instanceof Error ? error : new Error(String(error)), 3, operation, format === "json");
|
|
1255
|
+
}
|
|
1256
|
+
const result = planLifecycle(input.text, mutation, {
|
|
1257
|
+
maxDiagnostics,
|
|
1258
|
+
originalLabel: source,
|
|
1259
|
+
updatedLabel: "candidate",
|
|
1260
|
+
governance: governanceRequest(parsed, writeRequest),
|
|
1261
|
+
});
|
|
1262
|
+
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1263
|
+
(result.diagnosticsTruncated ||
|
|
1264
|
+
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
1265
|
+
const ok = result.ok && !warningFailure;
|
|
1266
|
+
let writeResult = Object.freeze({
|
|
1267
|
+
mode: writeRequest.mode,
|
|
1268
|
+
target: writeRequest.target,
|
|
1269
|
+
written: false,
|
|
1270
|
+
});
|
|
1271
|
+
if (result.ok && ok && writeRequest.mode !== "preview") {
|
|
1272
|
+
try {
|
|
1273
|
+
writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
|
|
1274
|
+
}
|
|
1275
|
+
catch (error) {
|
|
1276
|
+
return writeFailureExit(error, operation, format === "json");
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
if (format === "json") {
|
|
1280
|
+
writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), operation, source, writeResult));
|
|
1281
|
+
}
|
|
1282
|
+
else {
|
|
1283
|
+
if (ok) {
|
|
1284
|
+
if (writeRequest.mode !== "preview") {
|
|
1285
|
+
process.stderr.write(renderGovernanceWriteSummary(operation, writeResult, result.updatedDigest));
|
|
1286
|
+
}
|
|
1287
|
+
else {
|
|
1288
|
+
process.stdout.write(parsed.flags.has("diff")
|
|
1289
|
+
? (result.diff ?? "")
|
|
1290
|
+
: (result.updatedText ?? ""));
|
|
1291
|
+
if (!parsed.flags.has("diff")) {
|
|
1292
|
+
process.stderr.write(`PREVIEW ${operation} changed=${result.changed} original_digest=${result.originalDigest} updated_digest=${result.updatedDigest}\n`);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
if (result.lifecycle !== null) {
|
|
1297
|
+
process.stderr.write(`LIFECYCLE task=${result.lifecycle.taskId} from=${result.lifecycle.fromState} to=${result.lifecycle.toState} event=${result.lifecycle.event.id} coverage=${result.lifecycle.coverage}\n`);
|
|
1298
|
+
}
|
|
1299
|
+
if (result.governance !== null) {
|
|
1300
|
+
process.stderr.write(renderTargetGovernanceDecision(result.governance));
|
|
1301
|
+
}
|
|
1134
1302
|
for (const diagnostic of result.diagnostics) {
|
|
1135
1303
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
1136
1304
|
}
|
|
@@ -1148,7 +1316,7 @@ function unitMigrationJson(result, source, sourceDigest, ok) {
|
|
|
1148
1316
|
});
|
|
1149
1317
|
return {
|
|
1150
1318
|
schema_version: result.schemaVersion,
|
|
1151
|
-
cli_contract_version:
|
|
1319
|
+
cli_contract_version: 6,
|
|
1152
1320
|
tool_version: TOOL_VERSION,
|
|
1153
1321
|
operation: "project.migrate-unit",
|
|
1154
1322
|
ok,
|
|
@@ -1276,23 +1444,90 @@ async function runUnitMigration(args) {
|
|
|
1276
1444
|
}
|
|
1277
1445
|
return ok ? 0 : 1;
|
|
1278
1446
|
}
|
|
1279
|
-
function
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1447
|
+
async function readHistoryForCommand(operation, parsed, format) {
|
|
1448
|
+
if (parsed.positionals.length !== 1) {
|
|
1449
|
+
throw new UsageError(`${operation.replace(".", " ")} requires exactly one <file>`);
|
|
1450
|
+
}
|
|
1451
|
+
const source = parsed.positionals[0];
|
|
1452
|
+
if (source === "-") {
|
|
1453
|
+
throw new UsageError(`${operation.replace(".", " ")} requires an on-disk file`);
|
|
1454
|
+
}
|
|
1455
|
+
try {
|
|
1456
|
+
return await inspectTargetProjectHistoryFile({
|
|
1457
|
+
targetPath: source,
|
|
1458
|
+
...(parsed.values.get("rev") === undefined
|
|
1459
|
+
? {}
|
|
1460
|
+
: { revision: parsed.values.get("rev") }),
|
|
1461
|
+
...(parsed.repeatedValues.get("task") === undefined
|
|
1462
|
+
? {}
|
|
1463
|
+
: { taskIds: parsed.repeatedValues.get("task") }),
|
|
1464
|
+
}, TARGET_GRAMMAR_5_CAPABILITY);
|
|
1465
|
+
}
|
|
1466
|
+
catch (error) {
|
|
1467
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
async function runProjectHistory(args) {
|
|
1471
|
+
const parsed = parseCommandOptions("project.history", args);
|
|
1472
|
+
const format = outputFormat(parsed.values.get("format"));
|
|
1473
|
+
const color = colorMode(parsed.values.get("color"), format);
|
|
1474
|
+
const result = await readHistoryForCommand("project.history", parsed, format);
|
|
1475
|
+
if (result instanceof Error) {
|
|
1476
|
+
return cliError(result, 3, "project.history", format === "json");
|
|
1477
|
+
}
|
|
1478
|
+
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1479
|
+
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
|
|
1480
|
+
const ok = result.ok && !warningFailure;
|
|
1481
|
+
if (format === "json") {
|
|
1482
|
+
writeJson(targetProjectHistoryResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), parsed.positionals[0]));
|
|
1483
|
+
}
|
|
1484
|
+
else {
|
|
1485
|
+
if (ok)
|
|
1486
|
+
process.stdout.write(renderTargetProjectHistoryText(result));
|
|
1487
|
+
for (const diagnostic of result.diagnostics) {
|
|
1488
|
+
process.stderr.write(`${renderDiagnostic(diagnostic, parsed.positionals[0], color)}\n`);
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
return ok ? 0 : 1;
|
|
1492
|
+
}
|
|
1493
|
+
async function runProjectVelocityObservation(args) {
|
|
1494
|
+
const parsed = parseCommandOptions("project.observe-velocity", args);
|
|
1495
|
+
const format = outputFormat(parsed.values.get("format"));
|
|
1496
|
+
const color = colorMode(parsed.values.get("color"), format);
|
|
1497
|
+
const history = await readHistoryForCommand("project.observe-velocity", parsed, format);
|
|
1498
|
+
if (history instanceof Error) {
|
|
1499
|
+
return cliError(history, 3, "project.observe-velocity", format === "json");
|
|
1500
|
+
}
|
|
1501
|
+
const evidenceValue = parsed.values.get("evidence") ?? "declared";
|
|
1502
|
+
const evidence = evidenceValue === "git-recorded"
|
|
1503
|
+
? "git_recorded"
|
|
1504
|
+
: evidenceValue;
|
|
1505
|
+
const result = observeTargetProjectVelocity(history, {
|
|
1506
|
+
...(parsed.repeatedValues.get("task") === undefined
|
|
1507
|
+
? {}
|
|
1508
|
+
: { taskIds: parsed.repeatedValues.get("task") }),
|
|
1509
|
+
evidence,
|
|
1510
|
+
});
|
|
1511
|
+
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1512
|
+
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning");
|
|
1513
|
+
const ok = result.ok && !warningFailure;
|
|
1514
|
+
if (format === "json") {
|
|
1515
|
+
writeJson(targetVelocityObservationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), parsed.positionals[0]));
|
|
1516
|
+
}
|
|
1517
|
+
else {
|
|
1518
|
+
if (ok) {
|
|
1519
|
+
process.stdout.write(renderTargetVelocityObservationText(result));
|
|
1520
|
+
}
|
|
1521
|
+
for (const diagnostic of result.diagnostics) {
|
|
1522
|
+
process.stderr.write(`${renderDiagnostic(diagnostic, parsed.positionals[0], color)}\n`);
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
return ok ? 0 : 1;
|
|
1291
1526
|
}
|
|
1292
1527
|
function renderAdvanceSummary(details) {
|
|
1293
1528
|
const list = (ids) => ids.join(",") || "-";
|
|
1294
1529
|
return [
|
|
1295
|
-
`ADVANCE removed_tasks=${list(details.removedTaskIds)} removed_gates=${list(details.removedGateIds)} removed_milestones=${list(details.removedMilestoneIds)}`,
|
|
1530
|
+
`ADVANCE removed_tasks=${list(details.removedTaskIds)} removed_gates=${list(details.removedGateIds)} removed_milestones=${list(details.removedMilestoneIds)} removed_work_events=${list("removedWorkEventIds" in details ? details.removedWorkEventIds : [])}`,
|
|
1296
1531
|
`ADVANCE frontier_before=${list(details.frontierBefore)} frontier_after=${list(details.frontierAfter)} ready_before=${list(details.readyBefore)} ready_after=${list(details.readyAfter)}`,
|
|
1297
1532
|
"",
|
|
1298
1533
|
].join("\n");
|
|
@@ -1319,17 +1554,21 @@ async function runAdvance(args) {
|
|
|
1319
1554
|
maxDiagnostics,
|
|
1320
1555
|
originalLabel: source,
|
|
1321
1556
|
updatedLabel: "candidate",
|
|
1557
|
+
governance: governanceRequest(parsed, writeRequest),
|
|
1322
1558
|
});
|
|
1323
1559
|
const warningFailure = parsed.flags.has("warnings-as-errors") &&
|
|
1324
1560
|
(result.diagnosticsTruncated ||
|
|
1325
1561
|
result.diagnostics.some((diagnostic) => diagnostic.severity === "warning"));
|
|
1326
1562
|
const ok = result.ok && !warningFailure;
|
|
1327
|
-
let writeResult =
|
|
1563
|
+
let writeResult = Object.freeze({
|
|
1564
|
+
mode: writeRequest.mode,
|
|
1565
|
+
target: writeRequest.target,
|
|
1566
|
+
written: false,
|
|
1567
|
+
});
|
|
1328
1568
|
if (result.ok) {
|
|
1329
1569
|
try {
|
|
1330
|
-
assertExpectedDigest(writeRequest, input.digest);
|
|
1331
1570
|
if (ok && writeRequest.mode !== "preview") {
|
|
1332
|
-
writeResult = await
|
|
1571
|
+
writeResult = await persistGovernedResult(result, writeRequest, sourceOperand);
|
|
1333
1572
|
}
|
|
1334
1573
|
}
|
|
1335
1574
|
catch (error) {
|
|
@@ -1337,25 +1576,12 @@ async function runAdvance(args) {
|
|
|
1337
1576
|
}
|
|
1338
1577
|
}
|
|
1339
1578
|
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
|
-
});
|
|
1579
|
+
writeJson(contract6MutationResultToJson(ok ? result : Object.freeze({ ...result, ok: false }), "dag.advance", source, writeResult));
|
|
1354
1580
|
}
|
|
1355
1581
|
else {
|
|
1356
1582
|
if (ok && result.advance !== null) {
|
|
1357
|
-
if (
|
|
1358
|
-
process.stderr.write(
|
|
1583
|
+
if (writeRequest.mode !== "preview") {
|
|
1584
|
+
process.stderr.write(renderGovernanceWriteSummary("dag.advance", writeResult, result.updatedDigest));
|
|
1359
1585
|
}
|
|
1360
1586
|
else {
|
|
1361
1587
|
process.stdout.write(parsed.flags.has("diff") ? (result.diff ?? "") : (result.updatedText ?? ""));
|
|
@@ -1365,6 +1591,9 @@ async function runAdvance(args) {
|
|
|
1365
1591
|
}
|
|
1366
1592
|
process.stderr.write(renderAdvanceSummary(result.advance));
|
|
1367
1593
|
}
|
|
1594
|
+
if (result.governance !== null) {
|
|
1595
|
+
process.stderr.write(renderTargetGovernanceDecision(result.governance));
|
|
1596
|
+
}
|
|
1368
1597
|
for (const diagnostic of result.diagnostics) {
|
|
1369
1598
|
process.stderr.write(`${renderDiagnostic(diagnostic, source, color)}\n`);
|
|
1370
1599
|
}
|
|
@@ -1394,6 +1623,8 @@ function precedenceJson(result, unit, precision) {
|
|
|
1394
1623
|
makespan: rationalJson(result.makespan, unit, precision),
|
|
1395
1624
|
conditional_on_blocks_resolved: result.conditionalOnBlocksResolved,
|
|
1396
1625
|
blocked_task_ids: result.blockedTaskIds,
|
|
1626
|
+
conditional_on_suspensions_resumed: result.conditionalOnSuspensionsResumed,
|
|
1627
|
+
suspended_task_ids: result.suspendedTaskIds,
|
|
1397
1628
|
milestones: result.milestones.map((milestone) => ({
|
|
1398
1629
|
id: milestone.id,
|
|
1399
1630
|
earliest: rationalJson(milestone.earliest, unit, precision),
|
|
@@ -1445,6 +1676,8 @@ function resourceJson(result, unit, precision) {
|
|
|
1445
1676
|
algorithm: result.algorithm,
|
|
1446
1677
|
conditional_on_blocks_resolved: result.conditionalOnBlocksResolved,
|
|
1447
1678
|
blocked_task_ids: result.blockedTaskIds,
|
|
1679
|
+
conditional_on_suspensions_resumed: result.conditionalOnSuspensionsResumed,
|
|
1680
|
+
suspended_task_ids: result.suspendedTaskIds,
|
|
1448
1681
|
capacities: result.capacities.map((capacity) => ({
|
|
1449
1682
|
id: capacity.id,
|
|
1450
1683
|
declared: capacity.declared,
|
|
@@ -1553,11 +1786,14 @@ function renderAnalysisText(result) {
|
|
|
1553
1786
|
const conditional = result.precedence?.conditionalOnBlocksResolved === true ||
|
|
1554
1787
|
result.resource?.conditionalOnBlocksResolved === true;
|
|
1555
1788
|
const blockedTaskIds = result.precedence?.blockedTaskIds ?? result.resource?.blockedTaskIds ?? [];
|
|
1789
|
+
const suspendedTaskIds = result.precedence?.suspendedTaskIds ??
|
|
1790
|
+
result.resource?.suspendedTaskIds ??
|
|
1791
|
+
[];
|
|
1556
1792
|
const pathsTruncated = result.precedence?.critical.pathsTruncated === true ||
|
|
1557
1793
|
result.resource?.scheduleCritical.pathsTruncated === true;
|
|
1558
1794
|
const overrides = [...result.capacityOverrides]
|
|
1559
1795
|
.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));
|
|
1560
|
-
lines.push(`CONDITIONAL_ON_BLOCKS_RESOLVED ${conditional}`, `BLOCKED_TASKS ${blockedTaskIds.join(", ") || "-"}`, `PATHS_TRUNCATED ${pathsTruncated}`, `CAPACITY_OVERRIDES ${overrides.map(([id, capacity]) => `${id}=${capacity}`).join(", ") || "-"}`, `VELOCITY ${result.velocity === null ? "-" : velocityText(result.velocity, result.precision)}`, `VELOCITY_FORECAST_UNIT ${result.velocityForecast?.targetUnit ?? "-"}`);
|
|
1796
|
+
lines.push(`CONDITIONAL_ON_BLOCKS_RESOLVED ${conditional}`, `BLOCKED_TASKS ${blockedTaskIds.join(", ") || "-"}`, `CONDITIONAL_ON_SUSPENSIONS_RESUMED ${suspendedTaskIds.length > 0}`, `SUSPENDED_TASKS ${suspendedTaskIds.join(", ") || "-"}`, `PATHS_TRUNCATED ${pathsTruncated}`, `CAPACITY_OVERRIDES ${overrides.map(([id, capacity]) => `${id}=${capacity}`).join(", ") || "-"}`, `VELOCITY ${result.velocity === null ? "-" : velocityText(result.velocity, result.precision)}`, `VELOCITY_FORECAST_UNIT ${result.velocityForecast?.targetUnit ?? "-"}`);
|
|
1561
1797
|
if (result.precedence !== null) {
|
|
1562
1798
|
const precedence = result.precedence;
|
|
1563
1799
|
lines.push("", "PRECEDENCE", `MAKESPAN ${durationText(precedence.makespan, unit, result.precision)}`, ...(result.velocityForecast === null
|
|
@@ -1633,7 +1869,7 @@ function renderAnalysisText(result) {
|
|
|
1633
1869
|
["TEMPORAL PRECEDENCE", result.temporal.precedence],
|
|
1634
1870
|
["TEMPORAL RESOURCE", result.temporal.resource],
|
|
1635
1871
|
]) {
|
|
1636
|
-
lines.push("", title, `STATE ${projection.state}`, `ALGORITHM ${projection.algorithm === null ? "-" : `${projection.algorithm.id}@${projection.algorithm.version} optimal=${projection.algorithm.optimal}`}`, `CONDITIONAL_ON_BLOCKS_RESOLVED ${projection.conditionalOnBlocksResolved}`, `BLOCKED_TASKS ${projection.blockedTaskIds.join(",") || "-"}`);
|
|
1872
|
+
lines.push("", title, `STATE ${projection.state}`, `ALGORITHM ${projection.algorithm === null ? "-" : `${projection.algorithm.id}@${projection.algorithm.version} optimal=${projection.algorithm.optimal}`}`, `CONDITIONAL_ON_BLOCKS_RESOLVED ${projection.conditionalOnBlocksResolved}`, `BLOCKED_TASKS ${projection.blockedTaskIds.join(",") || "-"}`, `CONDITIONAL_ON_SUSPENSIONS_RESUMED ${projection.conditionalOnSuspensionsResumed}`, `SUSPENDED_TASKS ${projection.suspendedTaskIds.join(",") || "-"}`);
|
|
1637
1873
|
for (const task of projection.tasks) {
|
|
1638
1874
|
lines.push(`${task.taskId} START ${temporalPoint(task.start)} FINISH ${temporalPoint(task.finish)}`);
|
|
1639
1875
|
}
|
|
@@ -1688,8 +1924,8 @@ async function runAnalyze(args) {
|
|
|
1688
1924
|
const ok = result.ok && !warningFailure;
|
|
1689
1925
|
if (format === "json") {
|
|
1690
1926
|
writeJson({
|
|
1691
|
-
schema_version: "Perttool.AnalysisResult.
|
|
1692
|
-
cli_contract_version:
|
|
1927
|
+
schema_version: "Perttool.AnalysisResult.v4",
|
|
1928
|
+
cli_contract_version: 6,
|
|
1693
1929
|
tool_version: TOOL_VERSION,
|
|
1694
1930
|
operation: "dag.analyze",
|
|
1695
1931
|
ok,
|
|
@@ -1699,6 +1935,11 @@ async function runAnalyze(args) {
|
|
|
1699
1935
|
diagnostics: result.diagnostics.map(jsonDiagnostic),
|
|
1700
1936
|
diagnostics_truncated: result.diagnosticsTruncated,
|
|
1701
1937
|
grammar_version: result.grammarVersion,
|
|
1938
|
+
task_actuals: result.taskActuals.map((actuals) => ({
|
|
1939
|
+
task_id: actuals.taskId,
|
|
1940
|
+
status: actuals.status,
|
|
1941
|
+
coverage: actuals.coverage,
|
|
1942
|
+
})),
|
|
1702
1943
|
mode: result.mode,
|
|
1703
1944
|
precision: result.precision,
|
|
1704
1945
|
...(result.durationUnit === null
|
|
@@ -1803,7 +2044,7 @@ async function runRender(args) {
|
|
|
1803
2044
|
if (format === "json") {
|
|
1804
2045
|
writeJson({
|
|
1805
2046
|
schema_version: "Perttool.ExportResult.v1",
|
|
1806
|
-
cli_contract_version:
|
|
2047
|
+
cli_contract_version: 6,
|
|
1807
2048
|
tool_version: TOOL_VERSION,
|
|
1808
2049
|
operation: "dag.render",
|
|
1809
2050
|
ok,
|
|
@@ -1895,7 +2136,7 @@ async function runImport(args) {
|
|
|
1895
2136
|
if (format === "json") {
|
|
1896
2137
|
writeJson({
|
|
1897
2138
|
schema_version: "Perttool.ImportResult.v1",
|
|
1898
|
-
cli_contract_version:
|
|
2139
|
+
cli_contract_version: 6,
|
|
1899
2140
|
tool_version: TOOL_VERSION,
|
|
1900
2141
|
operation: "dag.import",
|
|
1901
2142
|
ok,
|
|
@@ -1986,6 +2227,7 @@ function nextJson(result) {
|
|
|
1986
2227
|
runnable_now: result.groups.runnableNow,
|
|
1987
2228
|
blocked_now: result.groups.blockedNow,
|
|
1988
2229
|
upcoming: result.groups.upcoming,
|
|
2230
|
+
suspended: result.groups.suspended,
|
|
1989
2231
|
},
|
|
1990
2232
|
tasks: result.tasks.map((task) => ({
|
|
1991
2233
|
id: task.id,
|
|
@@ -2158,6 +2400,7 @@ function renderNextText(result) {
|
|
|
2158
2400
|
section("RUNNABLE NOW", result.groups.runnableNow);
|
|
2159
2401
|
section("READY / WAITING RESOURCE", result.groups.ready.filter((id) => !result.groups.runnableNow.includes(id)), "rejection");
|
|
2160
2402
|
section("BLOCKED NOW", result.groups.blockedNow, "blocked");
|
|
2403
|
+
section("SUSPENDED", result.groups.suspended);
|
|
2161
2404
|
section("UPCOMING", result.groups.upcoming, "explanation");
|
|
2162
2405
|
lines.push("", "TEMPORAL CONTEXT");
|
|
2163
2406
|
for (const temporal of result.temporal.tasks) {
|
|
@@ -2202,7 +2445,7 @@ async function runNext(args) {
|
|
|
2202
2445
|
if (format === "json") {
|
|
2203
2446
|
writeJson({
|
|
2204
2447
|
schema_version: "Perttool.CliError.v1",
|
|
2205
|
-
cli_contract_version:
|
|
2448
|
+
cli_contract_version: 6,
|
|
2206
2449
|
tool_version: TOOL_VERSION,
|
|
2207
2450
|
operation: "dag.next",
|
|
2208
2451
|
ok: false,
|
|
@@ -2222,8 +2465,8 @@ async function runNext(args) {
|
|
|
2222
2465
|
const ok = result.ok && !warningFailure;
|
|
2223
2466
|
if (format === "json") {
|
|
2224
2467
|
writeJson({
|
|
2225
|
-
schema_version: "Perttool.NextResult.
|
|
2226
|
-
cli_contract_version:
|
|
2468
|
+
schema_version: "Perttool.NextResult.v5",
|
|
2469
|
+
cli_contract_version: 6,
|
|
2227
2470
|
recommendation_interface_version: 1,
|
|
2228
2471
|
tool_version: TOOL_VERSION,
|
|
2229
2472
|
operation: "dag.next",
|
|
@@ -2259,12 +2502,12 @@ function runGuide(args) {
|
|
|
2259
2502
|
colorMode(parsed.values.get("color"), format);
|
|
2260
2503
|
const topicId = parsed.positionals.length === 0 ? null : parsed.positionals.join(".");
|
|
2261
2504
|
const level = helpLevel(parsed.values.get("level"), topicId !== null);
|
|
2262
|
-
const result =
|
|
2505
|
+
const result = getActualsGuide(topicId, level);
|
|
2263
2506
|
if (format === "json") {
|
|
2264
|
-
process.stdout.write(
|
|
2507
|
+
process.stdout.write(serializeActualsGuideResult(result));
|
|
2265
2508
|
}
|
|
2266
2509
|
else {
|
|
2267
|
-
const rendered =
|
|
2510
|
+
const rendered = renderActualsGuideResult(result);
|
|
2268
2511
|
if (result.ok) {
|
|
2269
2512
|
process.stdout.write(rendered);
|
|
2270
2513
|
}
|
|
@@ -2280,15 +2523,15 @@ function runCommandHelp(args) {
|
|
|
2280
2523
|
throw new UsageError("help accepts at most <resource> <action>");
|
|
2281
2524
|
}
|
|
2282
2525
|
const format = outputFormat(parsed.values.get("format"));
|
|
2283
|
-
const result =
|
|
2526
|
+
const result = getActualsCommandDiscovery({
|
|
2284
2527
|
resource: parsed.positionals[0] ?? null,
|
|
2285
2528
|
action: parsed.positionals[1] ?? null,
|
|
2286
2529
|
});
|
|
2287
2530
|
if (format === "json") {
|
|
2288
|
-
process.stdout.write(
|
|
2531
|
+
process.stdout.write(serializeActualsCommandHelpResult(result));
|
|
2289
2532
|
}
|
|
2290
2533
|
else {
|
|
2291
|
-
const rendered =
|
|
2534
|
+
const rendered = renderActualsCommandHelpResult(result);
|
|
2292
2535
|
if (result.ok) {
|
|
2293
2536
|
process.stdout.write(rendered);
|
|
2294
2537
|
}
|
|
@@ -2318,7 +2561,7 @@ function runAgentHelp(args) {
|
|
|
2318
2561
|
const { schema_version: schemaVersion, ...payload } = projected;
|
|
2319
2562
|
writeJson({
|
|
2320
2563
|
schema_version: schemaVersion,
|
|
2321
|
-
cli_contract_version:
|
|
2564
|
+
cli_contract_version: 6,
|
|
2322
2565
|
...payload,
|
|
2323
2566
|
});
|
|
2324
2567
|
}
|
|
@@ -2356,6 +2599,10 @@ async function dispatchCommand(descriptor, args) {
|
|
|
2356
2599
|
return runProjectInit(args);
|
|
2357
2600
|
case "project.show":
|
|
2358
2601
|
return runProjectShow(args);
|
|
2602
|
+
case "project.history":
|
|
2603
|
+
return runProjectHistory(args);
|
|
2604
|
+
case "project.observe-velocity":
|
|
2605
|
+
return runProjectVelocityObservation(args);
|
|
2359
2606
|
case "project.migrate-unit":
|
|
2360
2607
|
return runUnitMigration(args);
|
|
2361
2608
|
case "dag.analyze":
|
|
@@ -2368,6 +2615,12 @@ async function dispatchCommand(descriptor, args) {
|
|
|
2368
2615
|
return runRender(args);
|
|
2369
2616
|
case "dag.import":
|
|
2370
2617
|
return runImport(args);
|
|
2618
|
+
case "task.start":
|
|
2619
|
+
return runLifecycleMutation("start", args);
|
|
2620
|
+
case "task.suspend":
|
|
2621
|
+
return runLifecycleMutation("suspend", args);
|
|
2622
|
+
case "task.resume":
|
|
2623
|
+
return runLifecycleMutation("resume", args);
|
|
2371
2624
|
}
|
|
2372
2625
|
if (descriptor.path.length === 2
|
|
2373
2626
|
&& (descriptor.operation === "project.set"
|
|
@@ -2376,14 +2629,14 @@ async function dispatchCommand(descriptor, args) {
|
|
|
2376
2629
|
const [resource, action] = descriptor.path;
|
|
2377
2630
|
return runMutation(resource, action, args);
|
|
2378
2631
|
}
|
|
2379
|
-
throw new Error(`no Contract
|
|
2632
|
+
throw new Error(`no Contract 6 handler for ${descriptor.operation}`);
|
|
2380
2633
|
}
|
|
2381
2634
|
function emitCommandUsage(error, json) {
|
|
2382
2635
|
if (json) {
|
|
2383
|
-
process.stdout.write(
|
|
2636
|
+
process.stdout.write(serializeActualsCommandUsageError(error));
|
|
2384
2637
|
}
|
|
2385
2638
|
else {
|
|
2386
|
-
process.stderr.write(
|
|
2639
|
+
process.stderr.write(renderActualsCommandUsageError(error));
|
|
2387
2640
|
}
|
|
2388
2641
|
return 2;
|
|
2389
2642
|
}
|
|
@@ -2395,13 +2648,13 @@ async function main(argv) {
|
|
|
2395
2648
|
if (argv.length === 1 && argv[0] === "--help") {
|
|
2396
2649
|
return runCommandHelp([]);
|
|
2397
2650
|
}
|
|
2398
|
-
const validation =
|
|
2651
|
+
const validation = validateActualsCommandInvocation(argv);
|
|
2399
2652
|
if (!validation.ok) {
|
|
2400
2653
|
if (jsonRequested(argv)) {
|
|
2401
|
-
process.stdout.write(
|
|
2654
|
+
process.stdout.write(serializeActualsCommandUsageError(validation.error));
|
|
2402
2655
|
}
|
|
2403
2656
|
else {
|
|
2404
|
-
process.stderr.write(
|
|
2657
|
+
process.stderr.write(renderActualsCommandUsageError(validation.error));
|
|
2405
2658
|
}
|
|
2406
2659
|
return 2;
|
|
2407
2660
|
}
|