@fitlab-ai/agent-infra 0.9.10 → 0.9.11
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/README.md +13 -3
- package/README.zh-CN.md +13 -3
- package/bin/cli.ts +17 -4
- package/dist/bin/cli.js +19 -4
- package/dist/bin/internal-cli.js +50 -4
- package/dist/lib/agent-client.js +0 -1
- package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
- package/dist/lib/agent-clients/adapters/traecli.js +7 -8
- package/dist/lib/agent-clients/config.js +14 -99
- package/dist/lib/agent-clients/reconcile.js +1 -11
- package/dist/lib/agent-clients/schema.js +5 -4
- package/dist/lib/agent-clients/tokens.js +5 -15
- package/dist/lib/decide.js +14 -30
- package/dist/lib/defaults.json +4 -0
- package/dist/lib/init.js +2 -2
- package/dist/lib/internal/release-workflow.js +0 -1
- package/dist/lib/internal/task-finalization.js +19 -9
- package/dist/lib/internal/task-ledger.js +8 -2
- package/dist/lib/internal/task-lifecycle.js +17 -93
- package/dist/lib/internal/task-orchestration.js +30 -216
- package/dist/lib/internal/task-validate.js +2 -1
- package/dist/lib/merge.js +205 -103
- package/dist/lib/process-data/normalize.js +2 -9
- package/dist/lib/run/host.js +46 -16
- package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
- package/dist/lib/sandbox/commands/create.js +3 -3
- package/dist/lib/sandbox/commands/enter.js +18 -4
- package/dist/lib/sandbox/config.js +3 -12
- package/dist/lib/sandbox/control/executor.js +131 -39
- package/dist/lib/sandbox/control/lifecycle.js +29 -20
- package/dist/lib/sandbox/control/server.js +18 -16
- package/dist/lib/sandbox/mounts.js +3 -2
- package/dist/lib/sandbox/recovery.js +123 -22
- package/dist/lib/sandbox/workspace-identity.js +14 -0
- package/dist/lib/sandbox/workspace-view.js +8 -9
- package/dist/lib/self-update.js +278 -0
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +4 -1
- package/dist/lib/task/artifact-lifecycle.js +4 -2
- package/dist/lib/task/codex-orchestration.js +1 -1
- package/dist/lib/task/command-options.js +1 -3
- package/dist/lib/task/commands/cat.js +0 -5
- package/dist/lib/task/commands/decisions.js +76 -92
- package/dist/lib/task/commands/files.js +6 -6
- package/dist/lib/task/commands/grep.js +25 -61
- package/dist/lib/task/commands/issue-body.js +6 -6
- package/dist/lib/task/commands/log.js +25 -10
- package/dist/lib/task/commands/show.js +5 -6
- package/dist/lib/task/commands/status.js +8 -8
- package/dist/lib/task/commit-operation.js +21 -25
- package/dist/lib/task/commit-policy.js +1 -1
- package/dist/lib/task/control-authority.js +431 -0
- package/dist/lib/task/create.js +6 -1
- package/dist/lib/task/current-contract.js +35 -0
- package/dist/lib/task/decision-details.js +263 -0
- package/dist/lib/task/decision-intents.js +5 -2
- package/dist/lib/task/events.js +11 -5
- package/dist/lib/task/index.js +19 -20
- package/dist/lib/task/ledger-intents.js +8 -9
- package/dist/lib/task/ledger.js +13 -6
- package/dist/lib/task/lifecycle.js +16 -0
- package/dist/lib/task/orchestration.js +50 -13
- package/dist/lib/task/review-artifacts.js +31 -12
- package/dist/lib/task/review-finalization.js +19 -6
- package/dist/lib/task/verification-engine.js +38 -15
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/task/workspace-snapshot.js +5 -11
- package/dist/lib/task/write.js +11 -1
- package/dist/lib/update.js +6 -37
- package/dist/lib/version.js +5 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +0 -1
- package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +7 -8
- package/lib/agent-clients/config.ts +14 -144
- package/lib/agent-clients/reconcile.ts +1 -12
- package/lib/agent-clients/schema.ts +5 -4
- package/lib/agent-clients/tokens.ts +5 -18
- package/lib/decide.ts +12 -22
- package/lib/defaults.json +4 -0
- package/lib/init.ts +2 -2
- package/lib/internal/release-workflow.ts +0 -1
- package/lib/internal/task-finalization.ts +27 -13
- package/lib/internal/task-ledger.ts +8 -2
- package/lib/internal/task-lifecycle.ts +33 -76
- package/lib/internal/task-orchestration.ts +33 -190
- package/lib/internal/task-validate.ts +3 -2
- package/lib/merge.ts +236 -120
- package/lib/process-data/normalize.ts +2 -8
- package/lib/run/host.ts +63 -14
- package/lib/sandbox/agent-client-reconciler.ts +5 -15
- package/lib/sandbox/commands/create.ts +4 -4
- package/lib/sandbox/commands/enter.ts +24 -4
- package/lib/sandbox/config.ts +2 -14
- package/lib/sandbox/control/container-identity.ts +2 -2
- package/lib/sandbox/control/executor.ts +148 -51
- package/lib/sandbox/control/lifecycle.ts +34 -28
- package/lib/sandbox/control/protocol.ts +1 -3
- package/lib/sandbox/control/server.ts +15 -12
- package/lib/sandbox/control/state.ts +7 -7
- package/lib/sandbox/mounts.ts +4 -3
- package/lib/sandbox/recovery.ts +162 -34
- package/lib/sandbox/tools.ts +1 -1
- package/lib/sandbox/workspace-identity.ts +28 -0
- package/lib/sandbox/workspace-view.ts +14 -10
- package/lib/self-update.ts +341 -0
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +6 -1
- package/lib/task/artifact-lifecycle.ts +5 -3
- package/lib/task/codex-orchestration.ts +2 -1
- package/lib/task/command-options.ts +1 -2
- package/lib/task/commands/cat.ts +0 -4
- package/lib/task/commands/decisions.ts +80 -75
- package/lib/task/commands/files.ts +6 -6
- package/lib/task/commands/grep.ts +23 -51
- package/lib/task/commands/issue-body.ts +6 -6
- package/lib/task/commands/log.ts +22 -10
- package/lib/task/commands/show.ts +5 -6
- package/lib/task/commands/status.ts +8 -8
- package/lib/task/commit-operation.ts +25 -30
- package/lib/task/commit-policy.ts +1 -2
- package/lib/task/control-authority.ts +563 -0
- package/lib/task/create.ts +6 -1
- package/lib/task/current-contract.ts +49 -0
- package/lib/task/decision-details.ts +340 -0
- package/lib/task/decision-intents.ts +7 -2
- package/lib/task/events.ts +10 -5
- package/lib/task/index.ts +19 -20
- package/lib/task/ledger-intents.ts +6 -8
- package/lib/task/ledger.ts +17 -7
- package/lib/task/lifecycle.ts +20 -0
- package/lib/task/orchestration.ts +40 -15
- package/lib/task/review-artifacts.ts +53 -15
- package/lib/task/review-finalization.ts +33 -7
- package/lib/task/verification-engine.ts +33 -18
- package/lib/task/verification-review.ts +1 -1
- package/lib/task/workspace-snapshot.ts +4 -13
- package/lib/task/write.ts +20 -1
- package/lib/update.ts +6 -40
- package/lib/version.ts +6 -1
- package/package.json +1 -1
- package/templates/.agents/README.en.md +5 -3
- package/templates/.agents/README.zh-CN.md +5 -3
- package/templates/.agents/rules/compatibility-policy.en.md +5 -4
- package/templates/.agents/rules/compatibility-policy.zh-CN.md +5 -4
- package/templates/.agents/rules/create-issue.github.en.md +1 -1
- package/templates/.agents/rules/create-issue.github.zh-CN.md +1 -1
- package/templates/.agents/rules/human-decision-context.en.md +9 -7
- package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
- package/templates/.agents/rules/issue-fields.github.en.md +1 -1
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.github.en.md +1 -1
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +2 -2
- package/templates/.agents/rules/milestone-inference.github.en.md +1 -1
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +3 -3
- package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
- package/templates/.agents/rules/pr-sync.en.md +1 -1
- package/templates/.agents/rules/pr-sync.github.en.md +1 -1
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +1 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/release-commands.github.en.md +6 -0
- package/templates/.agents/rules/release-commands.github.zh-CN.md +6 -0
- package/templates/.agents/rules/review-handshake.en.md +1 -1
- package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
- package/templates/.agents/rules/task-management.en.md +1 -2
- package/templates/.agents/rules/task-management.zh-CN.md +1 -2
- package/templates/.agents/skills/analyze-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/SKILL.en.md +27 -7
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -5
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/create-pr/SKILL.en.md +5 -7
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +5 -7
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +9 -4
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +9 -4
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
- package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
- package/templates/.agents/skills/create-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/plan-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +2 -1
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +2 -1
- package/templates/.agents/skills/review-plan/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +4 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +4 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +4 -0
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +4 -0
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +140 -109
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.claude/commands/analyze-task.en.md +1 -1
- package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.claude/commands/block-task.en.md +1 -1
- package/templates/.claude/commands/block-task.zh-CN.md +1 -1
- package/templates/.claude/commands/cancel-task.en.md +1 -1
- package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
- package/templates/.claude/commands/check-task.en.md +1 -1
- package/templates/.claude/commands/check-task.zh-CN.md +1 -1
- package/templates/.claude/commands/code-task.en.md +1 -1
- package/templates/.claude/commands/code-task.zh-CN.md +1 -1
- package/templates/.claude/commands/commit.en.md +1 -1
- package/templates/.claude/commands/commit.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-task.en.md +1 -1
- package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
- package/templates/.claude/commands/create-pr.en.md +1 -1
- package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
- package/templates/.claude/commands/plan-task.en.md +1 -1
- package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
- package/templates/.claude/commands/review-analysis.en.md +1 -1
- package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.claude/commands/review-code.en.md +1 -1
- package/templates/.claude/commands/review-code.zh-CN.md +1 -1
- package/templates/.claude/commands/review-plan.en.md +1 -1
- package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/run-task.en.md +1 -1
- package/templates/.claude/commands/run-task.zh-CN.md +1 -1
- package/templates/.claude/commands/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.en.md +0 -1
- package/templates/{.trae/skills → .traecli/commands}/update-agent-infra.zh-CN.md +0 -1
- package/dist/lib/builtin-tuis.js +0 -40
- package/lib/builtin-tuis.ts +0 -56
|
@@ -3,19 +3,18 @@ import path from 'node:path';
|
|
|
3
3
|
import { formatTable } from '../../table.js';
|
|
4
4
|
import { parseTaskScope } from '../command-options.js';
|
|
5
5
|
import { resolveTaskContext } from '../resolve-ref.js';
|
|
6
|
-
import { isReviewStage,
|
|
6
|
+
import { isReviewStage, parseLedgerDocument } from '../ledger.js';
|
|
7
7
|
import { listDecisionItems, selectDecisionItem } from '../decision-items.js';
|
|
8
|
-
import {
|
|
8
|
+
import { normalizeDecisionDetailForDisplay, parseDecisionEvidence, resolveDecisionDetail } from '../decision-details.js';
|
|
9
9
|
const USAGE = `Usage: ai task decisions [--task <ref> | -t <ref>] [--item <selector> | -i <selector>] [options]
|
|
10
|
-
ai task decisions <ref> [selector] [options]
|
|
11
10
|
|
|
12
11
|
Shows what still needs a maintainer's decision. Without a selector, it lists
|
|
13
12
|
the choices. With a selector, it shows the explanation and how to respond.
|
|
14
13
|
Read-only.
|
|
15
14
|
|
|
16
|
-
Omit
|
|
17
|
-
<ref>
|
|
18
|
-
|
|
15
|
+
Omit the scope Resolve the unique active task for the current branch.
|
|
16
|
+
--task/-t <ref> Select a task explicitly.
|
|
17
|
+
--item/-i <s> Ordinal (1-based) or ledger id (e.g. 'PL-3') to show one item's detail.
|
|
19
18
|
|
|
20
19
|
Options:
|
|
21
20
|
-i, --item <s> Select an item when task scope is implicit or flag-based.
|
|
@@ -53,15 +52,8 @@ function parseArgs(args) {
|
|
|
53
52
|
i += 1;
|
|
54
53
|
}
|
|
55
54
|
else if (a.startsWith('--item=')) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return null;
|
|
59
|
-
}
|
|
60
|
-
out.item = a.slice('--item='.length);
|
|
61
|
-
if (out.item === '') {
|
|
62
|
-
fail('--item requires a value');
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
55
|
+
fail("--item=... is not supported; use --item <selector> or -i <selector>");
|
|
56
|
+
return null;
|
|
65
57
|
}
|
|
66
58
|
else if (a === '--stage') {
|
|
67
59
|
const v = args[i + 1];
|
|
@@ -97,48 +89,26 @@ function parseArgs(args) {
|
|
|
97
89
|
}
|
|
98
90
|
return out;
|
|
99
91
|
}
|
|
100
|
-
// Parse `<file>.md#anchor` evidence into its filename, when present.
|
|
101
|
-
function evidenceFile(evidence) {
|
|
102
|
-
const m = /([\w.-]+\.md)#/.exec(evidence);
|
|
103
|
-
return m ? m[1] : null;
|
|
104
|
-
}
|
|
105
|
-
function roundOf(file) {
|
|
106
|
-
const m = /-r(\d+)\.md$/.exec(file);
|
|
107
|
-
return m ? Number.parseInt(m[1], 10) : 1;
|
|
108
|
-
}
|
|
109
|
-
// Locate the `### {ledger-id}` detail block for a row. Prefer the artifact named by the
|
|
110
|
-
// row's evidence anchor; otherwise scan analysis/plan/code artifacts and return
|
|
111
|
-
// the block from the highest-round file that contains it. Returns '' when none
|
|
112
|
-
// is found (caller degrades gracefully — plan B3).
|
|
113
92
|
function findDetailBlock(row, taskDir) {
|
|
114
|
-
const
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
let best = '';
|
|
124
|
-
let bestRound = -1;
|
|
125
|
-
let entries;
|
|
93
|
+
const evidence = parseDecisionEvidence(row.evidence);
|
|
94
|
+
if (!evidence.ok)
|
|
95
|
+
return { status: 'invalid', reason: `invalid evidence '${row.evidence}'` };
|
|
96
|
+
const artifactPath = path.join(taskDir, evidence.artifact);
|
|
97
|
+
if (!fs.existsSync(artifactPath))
|
|
98
|
+
return { status: 'missing', reason: `artifact '${evidence.artifact}' is missing` };
|
|
99
|
+
let artifactContent;
|
|
126
100
|
try {
|
|
127
|
-
|
|
101
|
+
artifactContent = fs.readFileSync(artifactPath, 'utf8');
|
|
128
102
|
}
|
|
129
103
|
catch {
|
|
130
|
-
return '';
|
|
104
|
+
return { status: 'missing', reason: `artifact '${evidence.artifact}' cannot be read` };
|
|
131
105
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
bestRound = roundOf(file);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return best;
|
|
106
|
+
const resolved = resolveDecisionDetail(artifactContent, row.id, evidence.anchor);
|
|
107
|
+
if (resolved.status === 'found')
|
|
108
|
+
return { status: 'found', content: normalizeDecisionDetailForDisplay(resolved.block) };
|
|
109
|
+
if (resolved.status === 'ambiguous')
|
|
110
|
+
return { status: 'ambiguous', reason: resolved.reason };
|
|
111
|
+
return { status: 'missing', reason: resolved.reason };
|
|
142
112
|
}
|
|
143
113
|
// Pull the `## 人工裁决` record lines that mention this ledger id, so a decided item
|
|
144
114
|
// shows the human's recorded ruling alongside its detail block.
|
|
@@ -160,9 +130,9 @@ function findDecisionRecord(id, content) {
|
|
|
160
130
|
return out;
|
|
161
131
|
}
|
|
162
132
|
function titleOf(row, taskDir) {
|
|
163
|
-
const
|
|
164
|
-
if (
|
|
165
|
-
const title =
|
|
133
|
+
const detail = findDetailBlock(row, taskDir);
|
|
134
|
+
if (detail.status === 'found') {
|
|
135
|
+
const title = detail.content
|
|
166
136
|
.split('\n')[0]
|
|
167
137
|
.replace(/^###\s+/, '')
|
|
168
138
|
.replace(/\s*\[needs-human-decision\]\s*$/, '')
|
|
@@ -174,7 +144,7 @@ function titleOf(row, taskDir) {
|
|
|
174
144
|
function trackingOf(row) {
|
|
175
145
|
return `stage=${row.stage} · severity=${row.severity} · status=${row.status} · evidence=${row.evidence}`;
|
|
176
146
|
}
|
|
177
|
-
function renderList(rows, format, taskDir) {
|
|
147
|
+
function renderList(rows, format, taskDir, taskId) {
|
|
178
148
|
if (rows.length === 0) {
|
|
179
149
|
process.stdout.write('No pending decisions.\n');
|
|
180
150
|
return;
|
|
@@ -193,10 +163,10 @@ function renderList(rows, format, taskDir) {
|
|
|
193
163
|
`| ${sep.join(' | ')} |`,
|
|
194
164
|
...data.map((row) => `| ${row.join(' | ')} |`)
|
|
195
165
|
];
|
|
196
|
-
process.stdout.write(`${md.join('\n')}\n\nView one item: ai task decisions
|
|
166
|
+
process.stdout.write(`${md.join('\n')}\n\nView one item: ai task decisions --task ${taskId} --item <ordinal|ledger-id>\n`);
|
|
197
167
|
return;
|
|
198
168
|
}
|
|
199
|
-
process.stdout.write(`${formatTable(headers, data).join('\n')}\n\nView one item: ai task decisions
|
|
169
|
+
process.stdout.write(`${formatTable(headers, data).join('\n')}\n\nView one item: ai task decisions --task ${taskId} --item <ordinal|ledger-id>\n`);
|
|
200
170
|
}
|
|
201
171
|
function renderTracking(row, format) {
|
|
202
172
|
if (format === 'markdown') {
|
|
@@ -216,29 +186,31 @@ function renderTracking(row, format) {
|
|
|
216
186
|
`evidence: ${row.evidence}`
|
|
217
187
|
];
|
|
218
188
|
}
|
|
219
|
-
function renderDetail(rows, selector, format, taskDir, content) {
|
|
189
|
+
function renderDetail(rows, selector, format, taskDir, content, taskId) {
|
|
220
190
|
const selected = selectDecisionItem(rows, selector);
|
|
221
191
|
if (!selected.ok) {
|
|
222
192
|
fail(selected.message);
|
|
223
193
|
return;
|
|
224
194
|
}
|
|
225
195
|
const r = selected.row;
|
|
226
|
-
const
|
|
227
|
-
|
|
196
|
+
const detail = findDetailBlock(r, taskDir);
|
|
197
|
+
if (detail.status === 'invalid' || detail.status === 'ambiguous') {
|
|
198
|
+
fail(`cannot resolve ${r.id}: ${detail.reason}`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const block = detail.status === 'found' ? detail.content : '';
|
|
202
|
+
const title = block
|
|
203
|
+
? block.split('\n')[0].replace(/^###\s+/, '').replace(/\s*\[needs-human-decision\]\s*$/, '').trim()
|
|
204
|
+
.replace(new RegExp(`^${r.id}\\s*[::]\\s*`, 'i'), '').trim()
|
|
205
|
+
: '(explanation unavailable)';
|
|
228
206
|
const lines = [];
|
|
229
207
|
const decided = r.status === 'human-decided';
|
|
230
208
|
if (format === 'markdown') {
|
|
231
209
|
lines.push(`## ${decided ? 'Decision already recorded' : 'Decision needed'}: ${title}`, '');
|
|
232
|
-
if (!decided) {
|
|
233
|
-
lines.push('**How to record your choice**', `\`ai decide <task-ref> ${r.id} <your choice and rationale>\``, '');
|
|
234
|
-
}
|
|
235
210
|
lines.push('**Original context**', '');
|
|
236
211
|
}
|
|
237
212
|
else {
|
|
238
213
|
lines.push(`${decided ? 'Decision already recorded' : 'Decision needed'}: ${title}`, '');
|
|
239
|
-
if (!decided) {
|
|
240
|
-
lines.push('How to record your choice:', `ai decide <task-ref> ${r.id} <your choice and rationale>`, '');
|
|
241
|
-
}
|
|
242
214
|
lines.push('Original context:');
|
|
243
215
|
}
|
|
244
216
|
if (block) {
|
|
@@ -252,6 +224,15 @@ function renderDetail(rows, selector, format, taskDir, content) {
|
|
|
252
224
|
lines.push('', format === 'markdown' ? '**Recorded choice**' : 'Recorded choice:');
|
|
253
225
|
lines.push(...(record.length ? record : ['No separate ruling record was found.']));
|
|
254
226
|
}
|
|
227
|
+
if (!decided) {
|
|
228
|
+
lines.push('');
|
|
229
|
+
if (format === 'markdown') {
|
|
230
|
+
lines.push('**How to record your choice**', `\`ai decide --task ${taskId} --item ${r.id} <your choice and rationale>\``);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
lines.push('How to record your choice:', `ai decide --task ${taskId} --item ${r.id} <your choice and rationale>`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
255
236
|
lines.push('', ...renderTracking(r, format));
|
|
256
237
|
process.stdout.write(`${lines.join('\n')}\n`);
|
|
257
238
|
}
|
|
@@ -279,43 +260,46 @@ function decisions(args = []) {
|
|
|
279
260
|
fail(`invalid --format '${parsed.format}' (expected text|markdown)`);
|
|
280
261
|
return;
|
|
281
262
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
if (parsed.
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
else if (scope.explicit) {
|
|
291
|
-
if (parsed.positionals.length > 0) {
|
|
292
|
-
fail('positional task ref/selector cannot be combined with --task');
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
else {
|
|
297
|
-
if (parsed.positionals.length > 2) {
|
|
298
|
-
fail('too many positional arguments');
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
taskRef = parsed.positionals[0];
|
|
302
|
-
selector = parsed.positionals[1];
|
|
263
|
+
const taskRef = scope.taskRef;
|
|
264
|
+
const selector = parsed.item;
|
|
265
|
+
if (parsed.positionals.length > 0) {
|
|
266
|
+
fail('positional task ref/selector is not supported; use --task <ref> or -t <ref>, and --item <selector> or -i <selector>');
|
|
267
|
+
return;
|
|
303
268
|
}
|
|
304
269
|
const resolved = resolveTaskContext(taskRef);
|
|
305
270
|
if (!resolved.ok) {
|
|
306
271
|
fail(resolved.message);
|
|
307
272
|
return;
|
|
308
273
|
}
|
|
309
|
-
|
|
310
|
-
|
|
274
|
+
let content;
|
|
275
|
+
let ledger;
|
|
276
|
+
try {
|
|
277
|
+
content = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
278
|
+
ledger = parseLedgerDocument(content);
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
fail(`ledger unavailable [LEDGER_DOCUMENT_INVALID]: ${error instanceof Error ? error.message : String(error)}`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!ledger.present) {
|
|
285
|
+
fail('ledger unavailable [LEDGER_SECTION_MISSING]: review disagreement ledger section is missing');
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const rows = listDecisionItems(ledger.rows, {
|
|
311
289
|
includeDecided: parsed.all,
|
|
312
290
|
stage: parsed.stage
|
|
313
291
|
});
|
|
314
292
|
if (selector === undefined) {
|
|
315
|
-
renderList(rows, parsed.format, resolved.taskDir);
|
|
293
|
+
renderList(rows, parsed.format, resolved.taskDir, resolved.taskId);
|
|
316
294
|
}
|
|
317
295
|
else {
|
|
318
|
-
|
|
296
|
+
const selectionRows = /^[A-Za-z]+-\d+$/.test(selector)
|
|
297
|
+
? listDecisionItems(ledger.rows, {
|
|
298
|
+
includeDecided: true,
|
|
299
|
+
stage: parsed.stage
|
|
300
|
+
})
|
|
301
|
+
: rows;
|
|
302
|
+
renderDetail(selectionRows, selector, parsed.format, resolved.taskDir, content, resolved.taskId);
|
|
319
303
|
}
|
|
320
304
|
}
|
|
321
305
|
export { decisions };
|
|
@@ -2,11 +2,11 @@ import { formatTable } from '../../table.js';
|
|
|
2
2
|
import { parseTaskScope } from '../command-options.js';
|
|
3
3
|
import { resolveTaskContext } from '../resolve-ref.js';
|
|
4
4
|
import { enumerateArtifacts } from '../artifacts.js';
|
|
5
|
-
const USAGE = `Usage: ai task files [
|
|
5
|
+
const USAGE = `Usage: ai task files [--task <ref> | -t <ref>]
|
|
6
6
|
|
|
7
7
|
Lists the artifacts in a task directory with stable numbers.
|
|
8
|
-
Omit
|
|
9
|
-
<ref>
|
|
8
|
+
Omit the scope Resolve the unique active task for the current branch.
|
|
9
|
+
--task/-t <ref> Bare numeric short id, or a full TASK-YYYYMMDD-HHMMSS id.
|
|
10
10
|
|
|
11
11
|
Columns: # (artifact number, usable with 'ai task cat') / NAME / SIZE (bytes) / MTIME
|
|
12
12
|
`;
|
|
@@ -33,12 +33,12 @@ function files(args = []) {
|
|
|
33
33
|
process.exitCode = 1;
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
|
-
if (scope.positionals.length >
|
|
37
|
-
process.stderr.write('ai task files: task ref
|
|
36
|
+
if (scope.positionals.length > 0) {
|
|
37
|
+
process.stderr.write('ai task files: positional task ref is not supported; use --task <ref> or -t <ref>\n');
|
|
38
38
|
process.exitCode = 1;
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
const resolved = resolveTaskContext(scope.taskRef
|
|
41
|
+
const resolved = resolveTaskContext(scope.taskRef);
|
|
42
42
|
if (!resolved.ok) {
|
|
43
43
|
process.stderr.write(`ai task files: ${resolved.message}\n`);
|
|
44
44
|
process.exitCode = 1;
|
|
@@ -1,24 +1,19 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { resolveTaskContext, resolveTaskRef
|
|
3
|
+
import { resolveTaskContext, resolveTaskRef } from '../resolve-ref.js';
|
|
4
4
|
import { enumerateArtifacts, resolveArtifact } from '../artifacts.js';
|
|
5
5
|
import { loadShortIdByTaskId } from '../short-id.js';
|
|
6
|
-
const USAGE = `Usage: ai task grep <
|
|
7
|
-
ai task grep <pattern> (--current | --task <ref> | -t <ref>) [artifact | N]
|
|
6
|
+
const USAGE = `Usage: ai task grep [--current | --task <ref> | -t <ref>] <pattern> [artifact | N]
|
|
8
7
|
|
|
9
8
|
Literal (non-regex) line search across task artifacts.
|
|
10
9
|
<pattern> Literal substring to match (NOT a regex). Case-sensitive by default.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
(a TASK-id ref can also resolve an archived task).
|
|
15
|
-
[artifact | N] Only valid with <ref>. Artifact filename (with or without '.md')
|
|
10
|
+
--current Limit search to the unique active task for the current branch.
|
|
11
|
+
-t, --task <ref> Limit search to an explicit task (bare short id or TASK-id).
|
|
12
|
+
[artifact | N] Artifact filename (with or without '.md')
|
|
16
13
|
or the number from 'ai task files'. Narrows to a single artifact.
|
|
17
14
|
|
|
18
15
|
Options:
|
|
19
16
|
-i, --ignore-case Case-insensitive matching.
|
|
20
|
-
--current Limit search to the current task context.
|
|
21
|
-
-t, --task <ref> Limit search to an explicit task.
|
|
22
17
|
-- Treat the rest as positional (use for patterns starting with '-').
|
|
23
18
|
|
|
24
19
|
Output: '{taskId} [#short] {fileStem}:{line}: {matched-line}' (short id only for active tasks).
|
|
@@ -92,17 +87,9 @@ function grep(args = []) {
|
|
|
92
87
|
continue;
|
|
93
88
|
}
|
|
94
89
|
if (!optsEnded && a.startsWith('--task=')) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
taskRef = a.slice('--task='.length);
|
|
101
|
-
if (taskRef === '') {
|
|
102
|
-
process.stderr.write('ai task grep: --task requires a value\n');
|
|
103
|
-
process.exitCode = 1;
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
90
|
+
process.stderr.write('ai task grep: --task=... is not supported; use --task <ref> or -t <ref>\n');
|
|
91
|
+
process.exitCode = 1;
|
|
92
|
+
return;
|
|
106
93
|
continue;
|
|
107
94
|
}
|
|
108
95
|
if (!optsEnded && a.startsWith('-') && a !== '-') {
|
|
@@ -122,63 +109,40 @@ function grep(args = []) {
|
|
|
122
109
|
process.exitCode = 1;
|
|
123
110
|
return;
|
|
124
111
|
}
|
|
125
|
-
if (positional.length >
|
|
112
|
+
if (positional.length > 2) {
|
|
126
113
|
process.stderr.write('ai task grep: too many arguments\n');
|
|
127
114
|
process.exitCode = 1;
|
|
128
115
|
return;
|
|
129
116
|
}
|
|
130
|
-
|
|
131
|
-
if (current || taskRef !== undefined) {
|
|
132
|
-
artifactOrN = ref;
|
|
133
|
-
ref = taskRef;
|
|
134
|
-
}
|
|
117
|
+
const [pattern, artifactOrN] = positional;
|
|
135
118
|
const matcher = makeMatcher(pattern, ignoreCase);
|
|
136
119
|
const chunks = [];
|
|
137
120
|
const emit = (line) => chunks.push(line);
|
|
138
121
|
let total = 0;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
122
|
+
const resolved = current || taskRef === undefined
|
|
123
|
+
? resolveTaskContext()
|
|
124
|
+
: resolveTaskRef(taskRef);
|
|
125
|
+
if (!resolved.ok) {
|
|
126
|
+
process.stderr.write(`ai task grep: ${resolved.message}\n`);
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const shortToken = loadShortIdByTaskId(resolved.repoRoot).get(resolved.taskId);
|
|
131
|
+
if (artifactOrN !== undefined) {
|
|
132
|
+
let artifactPath;
|
|
142
133
|
try {
|
|
143
|
-
|
|
134
|
+
artifactPath = resolveArtifact(resolved.taskDir, artifactOrN);
|
|
144
135
|
}
|
|
145
136
|
catch (e) {
|
|
146
137
|
process.stderr.write(`ai task grep: ${e.message}\n`);
|
|
147
138
|
process.exitCode = 1;
|
|
148
139
|
return;
|
|
149
140
|
}
|
|
150
|
-
|
|
151
|
-
for (const { taskId, taskDir } of enumerateTaskDirs(repoRoot)) {
|
|
152
|
-
const shortToken = shortMap.get(taskId);
|
|
153
|
-
for (const a of enumerateArtifacts(taskDir)) {
|
|
154
|
-
total += scanArtifact(taskId, shortToken, a.path, matcher, emit);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
141
|
+
total += scanArtifact(resolved.taskId, shortToken, artifactPath, matcher, emit);
|
|
157
142
|
}
|
|
158
143
|
else {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
process.stderr.write(`ai task grep: ${resolved.message}\n`);
|
|
162
|
-
process.exitCode = 1;
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
const shortToken = loadShortIdByTaskId(resolved.repoRoot).get(resolved.taskId);
|
|
166
|
-
if (artifactOrN !== undefined) {
|
|
167
|
-
let artifactPath;
|
|
168
|
-
try {
|
|
169
|
-
artifactPath = resolveArtifact(resolved.taskDir, artifactOrN);
|
|
170
|
-
}
|
|
171
|
-
catch (e) {
|
|
172
|
-
process.stderr.write(`ai task grep: ${e.message}\n`);
|
|
173
|
-
process.exitCode = 1;
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
total += scanArtifact(resolved.taskId, shortToken, artifactPath, matcher, emit);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
for (const a of enumerateArtifacts(resolved.taskDir)) {
|
|
180
|
-
total += scanArtifact(resolved.taskId, shortToken, a.path, matcher, emit);
|
|
181
|
-
}
|
|
144
|
+
for (const a of enumerateArtifacts(resolved.taskDir)) {
|
|
145
|
+
total += scanArtifact(resolved.taskId, shortToken, a.path, matcher, emit);
|
|
182
146
|
}
|
|
183
147
|
}
|
|
184
148
|
if (total === 0) {
|
|
@@ -4,11 +4,11 @@ import { resolveTaskContext } from '../resolve-ref.js';
|
|
|
4
4
|
import { extractTitle } from '../frontmatter.js';
|
|
5
5
|
import { extractSection, findSectionHeading } from '../sections.js';
|
|
6
6
|
import { renderTemplateBody, PLACEHOLDER } from '../issue-form.js';
|
|
7
|
-
const USAGE = `Usage: ai task issue-body [
|
|
7
|
+
const USAGE = `Usage: ai task issue-body [--task <ref> | -t <ref>] [--template <path>]
|
|
8
8
|
|
|
9
9
|
Print a deterministic Issue body extracted from a task's task.md.
|
|
10
|
-
Omit
|
|
11
|
-
<ref>
|
|
10
|
+
Omit the scope Resolve the unique active task for the current branch.
|
|
11
|
+
--task/-t <ref> Bare numeric short id, or a full TASK-YYYYMMDD-HHMMSS id.
|
|
12
12
|
--template <path> Render the final body for the given GitHub Issue Form (scenario A);
|
|
13
13
|
without it, print the default '任务输入 + 描述 + 需求' body (scenario B).
|
|
14
14
|
|
|
@@ -71,12 +71,12 @@ function issueBody(args = []) {
|
|
|
71
71
|
process.exitCode = 1;
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
if (scope.positionals.length >
|
|
75
|
-
process.stderr.write('ai task issue-body: task ref
|
|
74
|
+
if (scope.positionals.length > 0) {
|
|
75
|
+
process.stderr.write('ai task issue-body: positional task ref is not supported; use --task <ref> or -t <ref>\n');
|
|
76
76
|
process.exitCode = 1;
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
const resolved = resolveTaskContext(scope.taskRef
|
|
79
|
+
const resolved = resolveTaskContext(scope.taskRef);
|
|
80
80
|
if (!resolved.ok) {
|
|
81
81
|
process.stderr.write(`ai task issue-body: ${resolved.message}\n`);
|
|
82
82
|
process.exitCode = 1;
|
|
@@ -3,15 +3,15 @@ import { classifyAgent } from '../../agent-clients/tokens.js';
|
|
|
3
3
|
import { formatTable } from '../../table.js';
|
|
4
4
|
import { parseTaskScope } from '../command-options.js';
|
|
5
5
|
import { resolveTaskContext } from '../resolve-ref.js';
|
|
6
|
-
import { isReviewStage,
|
|
6
|
+
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, isReviewStage, parseLedgerDocument } from '../ledger.js';
|
|
7
7
|
import { parseActivityLog, pairEntries } from '../activity-log.js';
|
|
8
|
-
const USAGE = `Usage: ai task log [
|
|
8
|
+
const USAGE = `Usage: ai task log [--task <ref> | -t <ref>]
|
|
9
9
|
|
|
10
10
|
Renders a task's activity log as a per-step status table. A step's start and
|
|
11
11
|
completion are paired onto one row: STARTED holds the start time, DONE the
|
|
12
12
|
completion time (or '(in progress)' while still running).
|
|
13
|
-
Omit
|
|
14
|
-
<ref>
|
|
13
|
+
Omit the scope Resolve the unique active task for the current branch.
|
|
14
|
+
--task/-t <ref> Bare numeric short id, or a full TASK-YYYYMMDD-HHMMSS id.
|
|
15
15
|
|
|
16
16
|
Columns: # (row) / STEP / AGENT / STARTED / DONE / NOTE
|
|
17
17
|
A human-executed step shows AGENT as 'human' and, when it has no start marker,
|
|
@@ -85,8 +85,8 @@ function isHumanCountField(field) {
|
|
|
85
85
|
return fieldNumber(field, 'manual-validation') !== undefined || fieldNumber(field, 'human-decision') !== undefined;
|
|
86
86
|
}
|
|
87
87
|
// A step is human-executed when its agent token is not a known AI token.
|
|
88
|
-
// Known long names
|
|
89
|
-
//
|
|
88
|
+
// Known long names classify as AI; empty or unknown tokens classify as non-AI
|
|
89
|
+
// (human).
|
|
90
90
|
export function isHumanAgent(agent) {
|
|
91
91
|
return classifyAgent(agent).status !== 'ai';
|
|
92
92
|
}
|
|
@@ -118,12 +118,12 @@ function log(args = []) {
|
|
|
118
118
|
process.exitCode = 1;
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
|
-
if (scope.positionals.length >
|
|
122
|
-
process.stderr.write('ai task log: task ref
|
|
121
|
+
if (scope.positionals.length > 0) {
|
|
122
|
+
process.stderr.write('ai task log: positional task ref is not supported; use --task <ref> or -t <ref>\n');
|
|
123
123
|
process.exitCode = 1;
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
|
-
const resolved = resolveTaskContext(scope.taskRef
|
|
126
|
+
const resolved = resolveTaskContext(scope.taskRef);
|
|
127
127
|
if (!resolved.ok) {
|
|
128
128
|
process.stderr.write(`ai task log: ${resolved.message}\n`);
|
|
129
129
|
process.exitCode = 1;
|
|
@@ -142,7 +142,18 @@ function log(args = []) {
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
const steps = pairEntries(entries);
|
|
145
|
-
|
|
145
|
+
let humanDecisionCounts = new Map();
|
|
146
|
+
let ledgerDiagnostic = null;
|
|
147
|
+
try {
|
|
148
|
+
const ledger = parseLedgerDocument(content);
|
|
149
|
+
if (ledger.present)
|
|
150
|
+
humanDecisionCounts = countHumanDecisionsByStage(ledger.rows);
|
|
151
|
+
else
|
|
152
|
+
ledgerDiagnostic = `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`;
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
ledgerDiagnostic = `LEDGER_DOCUMENT_INVALID: ${error instanceof Error ? error.message : String(error)}`;
|
|
156
|
+
}
|
|
146
157
|
const rows = steps.map((s, idx) => {
|
|
147
158
|
const stage = reviewStageForStep(s.step);
|
|
148
159
|
const note = stage
|
|
@@ -157,6 +168,10 @@ function log(args = []) {
|
|
|
157
168
|
for (const line of formatTable(TABLE_HEADERS, rows, { zebra: Boolean(process.stdout.isTTY) })) {
|
|
158
169
|
process.stdout.write(`${line}\n`);
|
|
159
170
|
}
|
|
171
|
+
if (ledgerDiagnostic) {
|
|
172
|
+
process.stdout.write(`Ledger: unavailable [${ledgerDiagnostic}]\n`);
|
|
173
|
+
process.exitCode = 1;
|
|
174
|
+
}
|
|
160
175
|
process.stdout.write(`Total: ${steps.length} steps\n`);
|
|
161
176
|
}
|
|
162
177
|
export { log };
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import { parseTaskScope } from '../command-options.js';
|
|
3
3
|
import { resolveTaskContext } from '../resolve-ref.js';
|
|
4
|
-
const USAGE = `Usage: ai task show [
|
|
4
|
+
const USAGE = `Usage: ai task show [--task <ref> | -t <ref>]
|
|
5
5
|
|
|
6
6
|
Prints the task.md content for the matching task.
|
|
7
7
|
Omit the ref Resolve the unique active task for the current branch.
|
|
8
|
-
|
|
9
|
-
TASK-YYYYMMDD-HHMMSS Locates a task in active / blocked / completed / archive.
|
|
8
|
+
--task/-t <ref> Bare numeric short id, or a full TASK-YYYYMMDD-HHMMSS id.
|
|
10
9
|
`;
|
|
11
10
|
function show(args = []) {
|
|
12
11
|
if (args[0] === '--help' || args[0] === '-h') {
|
|
@@ -22,12 +21,12 @@ function show(args = []) {
|
|
|
22
21
|
process.exitCode = 1;
|
|
23
22
|
return;
|
|
24
23
|
}
|
|
25
|
-
if (scope.positionals.length >
|
|
26
|
-
process.stderr.write('ai task show: task ref
|
|
24
|
+
if (scope.positionals.length > 0) {
|
|
25
|
+
process.stderr.write('ai task show: positional task ref is not supported; use --task <ref> or -t <ref>\n');
|
|
27
26
|
process.exitCode = 1;
|
|
28
27
|
return;
|
|
29
28
|
}
|
|
30
|
-
const resolved = resolveTaskContext(scope.taskRef
|
|
29
|
+
const resolved = resolveTaskContext(scope.taskRef);
|
|
31
30
|
if (!resolved.ok) {
|
|
32
31
|
process.stderr.write(`ai task show: ${resolved.message}\n`);
|
|
33
32
|
process.exitCode = 1;
|
|
@@ -8,15 +8,15 @@ import { enumerateArtifacts } from '../artifacts.js';
|
|
|
8
8
|
import { parseTaskFrontmatter, extractTitle } from '../frontmatter.js';
|
|
9
9
|
import { loadShortIdByTaskId } from '../short-id.js';
|
|
10
10
|
import { getOpenWorkflowWarnings, formatWorkflowWarningSummary } from '../workflow-warnings.js';
|
|
11
|
-
import { parseActivityLog, pairEntries } from '../activity-log.js';
|
|
11
|
+
import { parseActivityLog, pairEntries, startedBackedRows } from '../activity-log.js';
|
|
12
12
|
import { readRun } from '../orchestration.js';
|
|
13
13
|
import { statusCard } from '../../server/display.js';
|
|
14
|
-
const USAGE = `Usage: ai task status [
|
|
14
|
+
const USAGE = `Usage: ai task status [--task <ref> | -t <ref>]
|
|
15
15
|
|
|
16
16
|
Prints an aggregated "health check" view for a task: header, metadata,
|
|
17
17
|
artifacts, workflow/runtime execution state, and git branch state.
|
|
18
|
-
Omit
|
|
19
|
-
<ref>
|
|
18
|
+
Omit the scope Resolve the unique active task for the current branch.
|
|
19
|
+
--task/-t <ref> Bare numeric short id, or a full TASK-YYYYMMDD-HHMMSS id.
|
|
20
20
|
|
|
21
21
|
Git rows are best-effort: a failed git call degrades that row to '-' without
|
|
22
22
|
failing the command.
|
|
@@ -155,7 +155,7 @@ function collectWorkflow(content, now = new Date()) {
|
|
|
155
155
|
if (!parsed.sectionFound || parsed.entries.length === 0) {
|
|
156
156
|
return { state: 'unknown', step: DASH, agent: DASH, startedAt: DASH, doneAt: DASH, stale: DASH };
|
|
157
157
|
}
|
|
158
|
-
const rows = pairEntries(parsed.entries);
|
|
158
|
+
const rows = startedBackedRows(pairEntries(parsed.entries));
|
|
159
159
|
const latest = rows.at(-1);
|
|
160
160
|
if (!latest) {
|
|
161
161
|
return { state: 'unknown', step: DASH, agent: DASH, startedAt: DASH, doneAt: DASH, stale: DASH };
|
|
@@ -431,10 +431,10 @@ function status(args = []) {
|
|
|
431
431
|
let model;
|
|
432
432
|
try {
|
|
433
433
|
const scope = parseTaskScope(args);
|
|
434
|
-
if (scope.positionals.length >
|
|
435
|
-
throw new Error('task ref
|
|
434
|
+
if (scope.positionals.length > 0) {
|
|
435
|
+
throw new Error('positional task ref is not supported; use --task <ref> or -t <ref>');
|
|
436
436
|
}
|
|
437
|
-
const resolved = resolveTaskContext(scope.taskRef
|
|
437
|
+
const resolved = resolveTaskContext(scope.taskRef);
|
|
438
438
|
if (!resolved.ok)
|
|
439
439
|
throw new Error(resolved.message);
|
|
440
440
|
model = buildFromResolved({
|