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