@fitlab-ai/agent-infra 0.8.5 → 0.9.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/bin/cli.ts +2 -2
- package/dist/bin/cli.js +2 -2
- package/dist/bin/internal-cli.js +98 -0
- package/dist/lib/decide.js +81 -90
- package/dist/lib/defaults.json +1 -0
- package/dist/lib/git/review-snapshot.js +79 -0
- package/dist/lib/git/workflow.js +101 -0
- package/dist/lib/internal/git-workflow.js +42 -0
- package/dist/lib/internal/platform-checks.js +119 -0
- package/dist/lib/internal/platform-comment.js +129 -0
- package/dist/lib/internal/platform-context.js +46 -0
- package/dist/lib/internal/platform-issue.js +142 -0
- package/dist/lib/internal/platform-pr.js +146 -0
- package/dist/lib/internal/release-workflow.js +217 -0
- package/dist/lib/internal/task-artifact.js +67 -0
- package/dist/lib/internal/task-context.js +43 -0
- package/dist/lib/internal/task-event.js +70 -0
- package/dist/lib/internal/task-ledger.js +114 -0
- package/dist/lib/internal/task-lifecycle.js +58 -0
- package/dist/lib/internal/task-short-id.js +83 -0
- package/dist/lib/internal/task-snapshot.js +47 -0
- package/dist/lib/internal/task-verify.js +50 -0
- package/dist/lib/internal/task-warning.js +74 -0
- package/dist/lib/platform/adapters.js +14 -0
- package/dist/lib/platform/context.js +146 -0
- package/dist/lib/platform/github-client.js +124 -0
- package/dist/lib/platform/issue-comments.js +409 -0
- package/dist/lib/platform/issue-metadata.js +183 -0
- package/dist/lib/platform/issues.js +617 -0
- package/dist/lib/platform/metadata-labels.js +28 -0
- package/dist/lib/platform/pr-checks.js +216 -0
- package/dist/lib/platform/pr-summary.js +88 -0
- package/dist/lib/platform/pull-request-metadata.js +38 -0
- package/dist/lib/platform/pull-requests.js +338 -0
- package/dist/lib/platform/releases.js +82 -0
- package/dist/lib/platform/types.js +22 -0
- package/dist/lib/platform/verification-required.js +78 -0
- package/dist/lib/platform/verification-sync.js +1014 -0
- package/dist/lib/platform/verification.js +6 -0
- package/dist/lib/release/channels.js +31 -0
- package/dist/lib/release/workflow.js +32 -0
- package/dist/lib/render.js +3 -2
- package/dist/lib/run/index.js +24 -7
- package/dist/lib/sandbox/capture.js +25 -3
- package/dist/lib/sandbox/commands/create.js +36 -22
- package/dist/lib/sandbox/commands/enter.js +34 -11
- package/dist/lib/sandbox/commands/list-running.js +10 -8
- package/dist/lib/sandbox/commands/show.js +2 -2
- package/dist/lib/sandbox/commands/start.js +53 -15
- package/dist/lib/sandbox/index.js +6 -6
- package/dist/lib/sandbox/mounts.js +36 -0
- package/dist/lib/sandbox/recovery.js +562 -0
- package/dist/lib/sandbox/task-resolver.js +5 -1
- package/dist/lib/sandbox/tools.js +19 -0
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +61 -0
- package/dist/lib/task/artifact-lifecycle.js +427 -0
- package/dist/lib/task/command-options.js +30 -0
- package/dist/lib/task/commands/cat.js +36 -6
- package/dist/lib/task/commands/decisions.js +80 -46
- package/dist/lib/task/commands/files.js +21 -7
- package/dist/lib/task/commands/grep.js +55 -7
- package/dist/lib/task/commands/issue-body.js +23 -14
- package/dist/lib/task/commands/log.js +27 -70
- package/dist/lib/task/commands/show.js +20 -7
- package/dist/lib/task/commands/status.js +18 -8
- package/dist/lib/task/decision-intents.js +154 -0
- package/dist/lib/task/decision-items.js +53 -0
- package/dist/lib/task/events.js +318 -0
- package/dist/lib/task/frontmatter.js +159 -1
- package/dist/lib/task/implementation-inputs.js +117 -0
- package/dist/lib/task/index.js +12 -9
- package/dist/lib/task/issue-form.js +19 -6
- package/dist/lib/task/ledger-intents.js +185 -0
- package/dist/lib/task/ledger.js +65 -35
- package/dist/lib/task/lifecycle.js +484 -0
- package/dist/lib/task/resolve-ref.js +152 -32
- package/dist/lib/task/review-artifacts.js +101 -0
- package/dist/lib/task/review-fingerprint.js +46 -0
- package/dist/lib/task/sections.js +358 -4
- package/dist/lib/task/short-id.js +292 -7
- package/dist/lib/task/snapshot.js +95 -0
- package/dist/lib/task/verification-checks.js +8 -0
- package/dist/lib/task/verification-config.js +14 -0
- package/dist/lib/task/verification-engine.js +906 -0
- package/dist/lib/task/verification-review.js +3 -0
- package/dist/lib/task/verification-types.js +2 -0
- package/dist/lib/task/verification.js +113 -0
- package/dist/lib/task/workflow-warning-intents.js +131 -0
- package/dist/lib/task/workflow-warnings.js +10 -78
- package/dist/lib/task/write.js +241 -0
- package/lib/decide.ts +57 -97
- package/lib/defaults.json +1 -0
- package/lib/git/review-snapshot.ts +73 -0
- package/lib/git/workflow.ts +101 -0
- package/lib/internal/git-workflow.ts +37 -0
- package/lib/internal/platform-checks.ts +101 -0
- package/lib/internal/platform-comment.ts +99 -0
- package/lib/internal/platform-context.ts +33 -0
- package/lib/internal/platform-issue.ts +116 -0
- package/lib/internal/platform-pr.ts +119 -0
- package/lib/internal/release-workflow.ts +186 -0
- package/lib/internal/task-artifact.ts +47 -0
- package/lib/internal/task-context.ts +35 -0
- package/lib/internal/task-event.ts +51 -0
- package/lib/internal/task-ledger.ts +86 -0
- package/lib/internal/task-lifecycle.ts +41 -0
- package/lib/internal/task-short-id.ts +55 -0
- package/lib/internal/task-snapshot.ts +32 -0
- package/lib/internal/task-verify.ts +33 -0
- package/lib/internal/task-warning.ts +50 -0
- package/lib/platform/adapters.ts +30 -0
- package/lib/platform/context.ts +164 -0
- package/lib/platform/github-client.ts +146 -0
- package/lib/platform/issue-comments.ts +479 -0
- package/lib/platform/issue-metadata.ts +250 -0
- package/lib/platform/issues.ts +691 -0
- package/lib/platform/metadata-labels.ts +33 -0
- package/lib/platform/pr-checks.ts +246 -0
- package/lib/platform/pr-summary.ts +90 -0
- package/lib/platform/pull-request-metadata.ts +69 -0
- package/lib/platform/pull-requests.ts +380 -0
- package/lib/platform/releases.ts +71 -0
- package/lib/platform/types.ts +74 -0
- package/lib/platform/verification-required.ts +83 -0
- package/{runtime/platform-adapters/platform-sync.github.js → lib/platform/verification-sync.ts} +198 -367
- package/lib/platform/verification.ts +11 -0
- package/lib/release/channels.ts +30 -0
- package/lib/release/workflow.ts +31 -0
- package/lib/render.ts +3 -2
- package/lib/run/index.ts +25 -7
- package/lib/sandbox/capture.ts +29 -3
- package/lib/sandbox/commands/create.ts +43 -25
- package/lib/sandbox/commands/enter.ts +38 -11
- package/lib/sandbox/commands/list-running.ts +10 -8
- package/lib/sandbox/commands/show.ts +2 -2
- package/lib/sandbox/commands/start.ts +50 -16
- package/lib/sandbox/index.ts +6 -6
- package/lib/sandbox/mounts.ts +55 -0
- package/lib/sandbox/recovery.ts +828 -0
- package/lib/sandbox/task-resolver.ts +5 -1
- package/lib/sandbox/tools.ts +31 -0
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +62 -0
- package/lib/task/artifact-lifecycle.ts +484 -0
- package/lib/task/command-options.ts +32 -0
- package/lib/task/commands/cat.ts +22 -9
- package/lib/task/commands/decisions.ts +49 -47
- package/lib/task/commands/files.ts +14 -6
- package/lib/task/commands/grep.ts +34 -7
- package/lib/task/commands/issue-body.ts +16 -16
- package/lib/task/commands/log.ts +17 -70
- package/lib/task/commands/show.ts +14 -6
- package/lib/task/commands/status.ts +17 -7
- package/lib/task/decision-intents.ts +163 -0
- package/lib/task/decision-items.ts +64 -0
- package/lib/task/events.ts +320 -0
- package/lib/task/frontmatter.ts +202 -2
- package/lib/task/implementation-inputs.ts +137 -0
- package/lib/task/index.ts +12 -9
- package/lib/task/issue-form.ts +20 -6
- package/lib/task/ledger-intents.ts +201 -0
- package/lib/task/ledger.ts +77 -31
- package/lib/task/lifecycle.ts +458 -0
- package/lib/task/resolve-ref.ts +197 -36
- package/{templates/.agents/scripts/lib/review-artifacts.js → lib/task/review-artifacts.ts} +11 -12
- package/{templates/.agents/scripts/lib/post-review-commit.js → lib/task/review-fingerprint.ts} +17 -12
- package/lib/task/sections.ts +486 -4
- package/lib/task/short-id.ts +403 -9
- package/lib/task/snapshot.ts +143 -0
- package/lib/task/verification-checks.ts +9 -0
- package/lib/task/verification-config.ts +20 -0
- package/{templates/.agents/scripts/validate-artifact.js → lib/task/verification-engine.ts} +199 -406
- package/lib/task/verification-review.ts +9 -0
- package/lib/task/verification-types.ts +29 -0
- package/lib/task/verification.ts +156 -0
- package/lib/task/workflow-warning-intents.ts +142 -0
- package/lib/task/workflow-warnings.ts +10 -78
- package/lib/task/write.ts +468 -0
- package/package.json +4 -2
- package/templates/.agents/README.en.md +4 -3
- package/templates/.agents/README.zh-CN.md +4 -3
- package/templates/.agents/rules/README.en.md +6 -5
- package/templates/.agents/rules/README.zh-CN.md +6 -5
- package/templates/.agents/rules/create-issue.en.md +1 -1
- package/templates/.agents/rules/create-issue.github.en.md +5 -184
- package/templates/.agents/rules/create-issue.github.zh-CN.md +12 -178
- package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
- package/templates/.agents/rules/human-decision-context.en.md +36 -0
- package/templates/.agents/rules/human-decision-context.zh-CN.md +36 -0
- package/templates/.agents/rules/issue-fields.github.en.md +4 -148
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +9 -144
- package/templates/.agents/rules/issue-pr-commands.en.md +43 -3
- package/templates/.agents/rules/issue-pr-commands.github.en.md +15 -220
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +23 -213
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +45 -3
- package/templates/.agents/rules/issue-sync.en.md +1 -1
- package/templates/.agents/rules/issue-sync.github.en.md +14 -301
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +36 -287
- package/templates/.agents/rules/issue-sync.zh-CN.md +1 -1
- package/templates/.agents/rules/milestone-inference.en.md +1 -1
- package/templates/.agents/rules/milestone-inference.github.en.md +7 -119
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +8 -108
- package/templates/.agents/rules/milestone-inference.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +12 -11
- package/templates/.agents/rules/next-step-output.zh-CN.md +12 -11
- package/templates/.agents/rules/no-mid-flow-questions.en.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +3 -3
- package/templates/.agents/rules/pr-checks-commands.en.md +16 -3
- package/templates/.agents/rules/pr-checks-commands.github.en.md +10 -54
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +19 -47
- package/templates/.agents/rules/pr-checks-commands.zh-CN.md +30 -3
- package/templates/.agents/rules/pr-sync.en.md +30 -3
- package/templates/.agents/rules/pr-sync.github.en.md +12 -115
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +26 -104
- package/templates/.agents/rules/pr-sync.zh-CN.md +43 -3
- package/templates/.agents/rules/review-handshake.en.md +8 -5
- package/templates/.agents/rules/review-handshake.zh-CN.md +8 -5
- package/templates/.agents/rules/task-management.en.md +11 -2
- package/templates/.agents/rules/task-management.zh-CN.md +11 -3
- package/templates/.agents/rules/task-short-id.en.md +25 -29
- package/templates/.agents/rules/task-short-id.zh-CN.md +20 -23
- package/templates/.agents/scripts/lib/agent-infra-package.js +1 -9
- package/templates/.agents/scripts/task-short-id.js +71 -533
- package/templates/.agents/skills/analyze-task/SKILL.en.md +22 -55
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +26 -59
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -3
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +21 -47
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +23 -47
- package/templates/.agents/skills/block-task/config/verify.json +1 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +16 -45
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +16 -45
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +6 -3
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/close-codescan/SKILL.en.md +6 -24
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +6 -24
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +6 -24
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +6 -24
- package/templates/.agents/skills/code-task/SKILL.en.md +22 -35
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +28 -44
- package/templates/.agents/skills/code-task/config/verify.en.json +3 -3
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +3 -3
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +13 -9
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +13 -9
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -1
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -1
- package/templates/.agents/skills/commit/SKILL.en.md +13 -11
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +13 -11
- package/templates/.agents/skills/commit/config/verify.json +1 -2
- package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -11
- package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -11
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +4 -8
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +4 -8
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +6 -18
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +5 -17
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +13 -0
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +13 -0
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +13 -36
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +13 -36
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -3
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +10 -54
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +10 -79
- package/templates/.agents/skills/complete-task/SKILL.en.md +59 -63
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +59 -63
- package/templates/.agents/skills/complete-task/config/verify.en.json +11 -7
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +11 -7
- package/templates/.agents/skills/create-pr/SKILL.en.md +19 -44
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +19 -43
- package/templates/.agents/skills/create-pr/config/verify.json +1 -2
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +8 -12
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +7 -11
- package/templates/.agents/skills/create-task/SKILL.en.md +12 -13
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +12 -13
- package/templates/.agents/skills/create-task/config/verify.json +1 -2
- package/templates/.agents/skills/import-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-codescan/config/verify.json +1 -2
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/import-dependabot/config/verify.json +1 -2
- package/templates/.agents/skills/import-issue/SKILL.en.md +9 -13
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +10 -14
- package/templates/.agents/skills/import-issue/config/verify.json +1 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +17 -42
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +22 -49
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -3
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -3
- package/templates/.agents/skills/post-release/SKILL.en.md +11 -81
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +8 -78
- package/templates/.agents/skills/refine-title/SKILL.en.md +1 -1
- package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/release/SKILL.en.md +16 -163
- package/templates/.agents/skills/release/SKILL.zh-CN.md +15 -162
- package/templates/.agents/skills/restore-task/SKILL.en.md +11 -29
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +11 -29
- package/templates/.agents/skills/restore-task/config/verify.json +1 -2
- package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -25
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +13 -33
- package/templates/.agents/skills/review-analysis/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +9 -12
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +9 -12
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +9 -2
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +9 -2
- package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +22 -36
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +23 -41
- package/templates/.agents/skills/review-code/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +56 -18
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +56 -18
- package/templates/.agents/skills/review-code/reference/report-template.en.md +11 -4
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +11 -4
- package/templates/.agents/skills/review-code/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +13 -25
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +13 -33
- package/templates/.agents/skills/review-plan/config/verify.en.json +3 -4
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +3 -4
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +9 -12
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +9 -12
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +9 -2
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +9 -2
- package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +7 -0
- package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +7 -0
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +3 -15
- package/templates/.agents/skills/watch-pr/SKILL.en.md +24 -14
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +25 -15
- package/templates/.agents/skills/watch-pr/config/verify.json +1 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +2 -2
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +2 -2
- package/templates/.agents/templates/task.en.md +6 -1
- package/templates/.agents/templates/task.zh-CN.md +6 -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 -0
- package/templates/.claude/commands/commit.zh-CN.md +1 -0
- 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/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/.gemini/commands/_project_/analyze-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/block-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/cancel-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/check-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/code-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/commit.en.toml +4 -0
- package/templates/.gemini/commands/_project_/commit.zh-CN.toml +4 -0
- package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/create-pr.en.toml +2 -0
- package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/plan-task.en.toml +2 -0
- package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-analysis.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-code.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/review-plan.en.toml +2 -0
- package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +2 -0
- package/templates/.gemini/commands/_project_/watch-pr.en.toml +2 -0
- package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +2 -0
- package/templates/.git-hooks/check-large-files.cjs +92 -0
- package/templates/.git-hooks/check-version-format.sh +5 -1
- package/templates/.git-hooks/pre-commit +1 -0
- package/templates/.opencode/commands/analyze-task.en.md +1 -1
- package/templates/.opencode/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/check-task.en.md +1 -1
- package/templates/.opencode/commands/check-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/code-task.en.md +1 -1
- package/templates/.opencode/commands/code-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/commit.en.md +2 -0
- package/templates/.opencode/commands/commit.zh-CN.md +2 -0
- package/templates/.opencode/commands/complete-task.en.md +1 -1
- package/templates/.opencode/commands/complete-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/plan-task.en.md +1 -1
- package/templates/.opencode/commands/plan-task.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-analysis.en.md +1 -1
- package/templates/.opencode/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-code.en.md +1 -1
- package/templates/.opencode/commands/review-code.zh-CN.md +1 -1
- package/templates/.opencode/commands/review-plan.en.md +1 -1
- package/templates/.opencode/commands/review-plan.zh-CN.md +1 -1
- package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +0 -40
- package/templates/.agents/scripts/platform-adapters/platform-sync.js +0 -13
- package/templates/.agents/scripts/review-diff-fingerprint.js +0 -170
- package/templates/.agents/scripts/workflow-warnings.js +0 -290
- package/templates/.agents/skills/code-task/scripts/detect-mode.js +0 -257
- package/templates/.agents/skills/release/scripts/manage-milestones.github.sh +0 -80
- package/templates/.agents/skills/release/scripts/manage-milestones.sh +0 -6
|
@@ -1,3 +1,58 @@
|
|
|
1
|
+
import { parse, stringify } from 'yaml';
|
|
2
|
+
class FrontmatterError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'FrontmatterError';
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function locateFrontmatter(content) {
|
|
11
|
+
const opening = /^---(\r?\n)/.exec(content);
|
|
12
|
+
if (!opening) {
|
|
13
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', 'task.md frontmatter is missing');
|
|
14
|
+
}
|
|
15
|
+
const eol = opening[1];
|
|
16
|
+
const bodyStart = opening[0].length;
|
|
17
|
+
const closing = /^---\r?$/gm;
|
|
18
|
+
closing.lastIndex = bodyStart;
|
|
19
|
+
const match = closing.exec(content);
|
|
20
|
+
if (!match) {
|
|
21
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', 'task.md frontmatter is unclosed');
|
|
22
|
+
}
|
|
23
|
+
return { eol, bodyStart, bodyEnd: match.index };
|
|
24
|
+
}
|
|
25
|
+
function parseFrontmatterLines(content, block) {
|
|
26
|
+
const body = content.slice(block.bodyStart, block.bodyEnd);
|
|
27
|
+
const lines = body.split(block.eol);
|
|
28
|
+
return lines.map((raw, index) => {
|
|
29
|
+
if (!raw.trim() || raw.trimStart().startsWith('#')) {
|
|
30
|
+
return { raw, index, key: null, value: null };
|
|
31
|
+
}
|
|
32
|
+
const match = /^([^\s:#][^:]*):(?:[ \t]*(.*))?$/.exec(raw);
|
|
33
|
+
if (!match || !match[1]) {
|
|
34
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', `unsupported frontmatter structure on line ${index + 2}`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
raw,
|
|
38
|
+
index,
|
|
39
|
+
key: match[1].trim(),
|
|
40
|
+
value: match[2] ?? ''
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function serializeScalar(value) {
|
|
45
|
+
if (typeof value === 'number' && !Number.isFinite(value)) {
|
|
46
|
+
throw new FrontmatterError('MUTATION_INVALID', 'frontmatter numbers must be finite');
|
|
47
|
+
}
|
|
48
|
+
if (value === '')
|
|
49
|
+
return '';
|
|
50
|
+
const serialized = stringify(value).trimEnd();
|
|
51
|
+
if (serialized.includes('\n') || serialized.includes('\r')) {
|
|
52
|
+
throw new FrontmatterError('MUTATION_INVALID', 'frontmatter values must be scalar');
|
|
53
|
+
}
|
|
54
|
+
return serialized;
|
|
55
|
+
}
|
|
1
56
|
function parseTaskFrontmatter(content) {
|
|
2
57
|
const result = {};
|
|
3
58
|
if (!content.startsWith('---'))
|
|
@@ -20,6 +75,109 @@ function parseTaskFrontmatter(content) {
|
|
|
20
75
|
}
|
|
21
76
|
return result;
|
|
22
77
|
}
|
|
78
|
+
function parseTypedTaskFrontmatter(content) {
|
|
79
|
+
const block = locateFrontmatter(content);
|
|
80
|
+
const result = {};
|
|
81
|
+
for (const line of parseFrontmatterLines(content, block)) {
|
|
82
|
+
if (!line.key || line.value === null)
|
|
83
|
+
continue;
|
|
84
|
+
if (Object.hasOwn(result, line.key)) {
|
|
85
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', `duplicate frontmatter key '${line.key}'`);
|
|
86
|
+
}
|
|
87
|
+
if (line.value === '') {
|
|
88
|
+
result[line.key] = '';
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
let value;
|
|
92
|
+
try {
|
|
93
|
+
value = parse(line.value);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', `frontmatter key '${line.key}' is not a valid scalar`);
|
|
97
|
+
}
|
|
98
|
+
if (value !== null &&
|
|
99
|
+
typeof value !== 'string' &&
|
|
100
|
+
typeof value !== 'number' &&
|
|
101
|
+
typeof value !== 'boolean') {
|
|
102
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', `frontmatter key '${line.key}' is not a scalar`);
|
|
103
|
+
}
|
|
104
|
+
if (typeof value === 'number' && !Number.isFinite(value)) {
|
|
105
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', `frontmatter key '${line.key}' is not a finite scalar`);
|
|
106
|
+
}
|
|
107
|
+
result[line.key] = value;
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
function updateTaskFrontmatter(content, set, remove = []) {
|
|
112
|
+
if (!set || typeof set !== 'object' || Array.isArray(set)) {
|
|
113
|
+
throw new FrontmatterError('MUTATION_INVALID', 'frontmatter set must be an object');
|
|
114
|
+
}
|
|
115
|
+
const entries = Object.entries(set);
|
|
116
|
+
if (!Array.isArray(remove)) {
|
|
117
|
+
throw new FrontmatterError('MUTATION_INVALID', 'frontmatter remove must be an array');
|
|
118
|
+
}
|
|
119
|
+
const removeSet = new Set(remove);
|
|
120
|
+
if (removeSet.size !== remove.length) {
|
|
121
|
+
throw new FrontmatterError('MUTATION_INVALID', 'frontmatter remove keys must be unique');
|
|
122
|
+
}
|
|
123
|
+
for (const [key, value] of entries) {
|
|
124
|
+
if (!key || /[\r\n:]/.test(key)) {
|
|
125
|
+
throw new FrontmatterError('MUTATION_INVALID', `invalid frontmatter key '${key}'`);
|
|
126
|
+
}
|
|
127
|
+
if (value !== null &&
|
|
128
|
+
typeof value !== 'string' &&
|
|
129
|
+
typeof value !== 'number' &&
|
|
130
|
+
typeof value !== 'boolean') {
|
|
131
|
+
throw new FrontmatterError('MUTATION_INVALID', `invalid scalar for '${key}'`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const key of remove) {
|
|
135
|
+
if (!key || /[\r\n:]/.test(key)) {
|
|
136
|
+
throw new FrontmatterError('MUTATION_INVALID', `invalid frontmatter key '${key}'`);
|
|
137
|
+
}
|
|
138
|
+
if (Object.hasOwn(set, key)) {
|
|
139
|
+
throw new FrontmatterError('MUTATION_INVALID', `frontmatter key '${key}' cannot be set and removed together`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const block = locateFrontmatter(content);
|
|
143
|
+
const lines = parseFrontmatterLines(content, block);
|
|
144
|
+
const indexes = new Map();
|
|
145
|
+
for (const line of lines) {
|
|
146
|
+
if (!line.key)
|
|
147
|
+
continue;
|
|
148
|
+
const positions = indexes.get(line.key) ?? [];
|
|
149
|
+
positions.push(line.index);
|
|
150
|
+
indexes.set(line.key, positions);
|
|
151
|
+
}
|
|
152
|
+
for (const key of [...entries.map(([entryKey]) => entryKey), ...remove]) {
|
|
153
|
+
if ((indexes.get(key)?.length ?? 0) > 1) {
|
|
154
|
+
throw new FrontmatterError('TASK_DOCUMENT_INVALID', `duplicate frontmatter key '${key}'`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const nextLines = lines.map((line) => line.raw);
|
|
158
|
+
const additions = [];
|
|
159
|
+
for (const [key, value] of entries) {
|
|
160
|
+
const serialized = serializeScalar(value);
|
|
161
|
+
const replacement = serialized === '' ? `${key}:` : `${key}: ${serialized}`;
|
|
162
|
+
const index = indexes.get(key)?.[0];
|
|
163
|
+
if (index === undefined)
|
|
164
|
+
additions.push(replacement);
|
|
165
|
+
else
|
|
166
|
+
nextLines[index] = replacement;
|
|
167
|
+
}
|
|
168
|
+
const retainedLines = nextLines.filter((_, index) => {
|
|
169
|
+
const key = lines[index]?.key;
|
|
170
|
+
return !key || !removeSet.has(key);
|
|
171
|
+
});
|
|
172
|
+
if (additions.length > 0) {
|
|
173
|
+
if (retainedLines.at(-1) === '')
|
|
174
|
+
retainedLines.splice(-1, 0, ...additions);
|
|
175
|
+
else
|
|
176
|
+
retainedLines.push(...additions);
|
|
177
|
+
}
|
|
178
|
+
const body = retainedLines.join(block.eol);
|
|
179
|
+
return content.slice(0, block.bodyStart) + body + content.slice(block.bodyEnd);
|
|
180
|
+
}
|
|
23
181
|
function extractTitle(content) {
|
|
24
182
|
for (const line of content.split('\n')) {
|
|
25
183
|
const m = /^#\s+(?:任务[::]?\s*)?(.+)$/.exec(line.trim());
|
|
@@ -28,5 +186,5 @@ function extractTitle(content) {
|
|
|
28
186
|
}
|
|
29
187
|
return '';
|
|
30
188
|
}
|
|
31
|
-
export { parseTaskFrontmatter, extractTitle };
|
|
189
|
+
export { parseTaskFrontmatter, parseTypedTaskFrontmatter, updateTaskFrontmatter, extractTitle };
|
|
32
190
|
//# sourceMappingURL=frontmatter.js.map
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { parseTable } from './sections.js';
|
|
2
|
+
const SECTION_ALIASES = ['实现输入', 'Implementation Inputs'];
|
|
3
|
+
const COLUMNS = [
|
|
4
|
+
'id', 'ledger_id', 'decision_evidence', 'stage', 'needs_implementation',
|
|
5
|
+
'decided_at', 'status', 'consumed_by'
|
|
6
|
+
];
|
|
7
|
+
const TIMESTAMP_RE = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$/;
|
|
8
|
+
const ARTIFACT_RE = /^code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/;
|
|
9
|
+
function validateInput(row) {
|
|
10
|
+
if (!/^II-[1-9]\d*$/.test(row.id))
|
|
11
|
+
throw new Error(`implementation input id '${row.id}' is invalid`);
|
|
12
|
+
if (!row.ledgerId || !row.decisionEvidence || /[\r\n]/.test(row.ledgerId) || /[\r\n]/.test(row.decisionEvidence))
|
|
13
|
+
throw new Error(`implementation input ${row.id} has incomplete decision identity`);
|
|
14
|
+
if (row.stage !== 'code')
|
|
15
|
+
throw new Error(`implementation input ${row.id} has invalid stage`);
|
|
16
|
+
if (!TIMESTAMP_RE.test(row.decidedAt) || !Number.isFinite(Date.parse(row.decidedAt.replace(' ', 'T')))) {
|
|
17
|
+
throw new Error(`implementation input ${row.id} has invalid decided_at`);
|
|
18
|
+
}
|
|
19
|
+
const valid = (row.needsImplementation && row.status === 'pending' && row.consumedBy === '') ||
|
|
20
|
+
(!row.needsImplementation && row.status === 'not-required' && row.consumedBy === '') ||
|
|
21
|
+
(row.needsImplementation && row.status === 'consumed' && ARTIFACT_RE.test(row.consumedBy));
|
|
22
|
+
if (!valid)
|
|
23
|
+
throw new Error(`implementation input ${row.id} has an invalid state combination`);
|
|
24
|
+
}
|
|
25
|
+
function parseImplementationInputs(content) {
|
|
26
|
+
const table = parseTable(content, { sectionAliases: SECTION_ALIASES, columns: COLUMNS });
|
|
27
|
+
if (!table)
|
|
28
|
+
return { sectionFound: false, rows: [] };
|
|
29
|
+
const rows = [];
|
|
30
|
+
const seen = new Set();
|
|
31
|
+
for (const { values } of table.rows) {
|
|
32
|
+
const id = values.id;
|
|
33
|
+
const ledgerId = values.ledger_id;
|
|
34
|
+
const decisionEvidence = values.decision_evidence;
|
|
35
|
+
const stage = values.stage;
|
|
36
|
+
const needs = values.needs_implementation;
|
|
37
|
+
const decidedAt = values.decided_at;
|
|
38
|
+
const status = values.status;
|
|
39
|
+
const consumedBy = values.consumed_by;
|
|
40
|
+
if (needs !== 'true' && needs !== 'false')
|
|
41
|
+
throw new Error(`implementation input ${id} has invalid needs_implementation`);
|
|
42
|
+
const row = {
|
|
43
|
+
id: id, ledgerId: ledgerId, decisionEvidence: decisionEvidence, stage: stage,
|
|
44
|
+
needsImplementation: needs === 'true', decidedAt: decidedAt,
|
|
45
|
+
status: status, consumedBy: consumedBy
|
|
46
|
+
};
|
|
47
|
+
validateInput(row);
|
|
48
|
+
if (seen.has(row.id))
|
|
49
|
+
throw new Error(`duplicate implementation input id '${row.id}'`);
|
|
50
|
+
seen.add(row.id);
|
|
51
|
+
rows.push(row);
|
|
52
|
+
}
|
|
53
|
+
return { sectionFound: true, rows };
|
|
54
|
+
}
|
|
55
|
+
function nextId(rows) {
|
|
56
|
+
let max = 0;
|
|
57
|
+
for (const row of rows)
|
|
58
|
+
max = Math.max(max, Number.parseInt(row.id.slice(3), 10));
|
|
59
|
+
return `II-${max + 1}`;
|
|
60
|
+
}
|
|
61
|
+
function createImplementationInput(rows, draft) {
|
|
62
|
+
const row = {
|
|
63
|
+
id: nextId(rows), ledgerId: draft.ledgerId, decisionEvidence: draft.decisionEvidence,
|
|
64
|
+
stage: 'code', needsImplementation: draft.needsImplementation, decidedAt: draft.decidedAt,
|
|
65
|
+
status: draft.needsImplementation ? 'pending' : 'not-required', consumedBy: ''
|
|
66
|
+
};
|
|
67
|
+
validateInput(row);
|
|
68
|
+
return row;
|
|
69
|
+
}
|
|
70
|
+
function selectPendingImplementationInput(rows, reviewCompletedAt) {
|
|
71
|
+
const reviewEpoch = Date.parse(reviewCompletedAt.replace(' ', 'T'));
|
|
72
|
+
if (!Number.isFinite(reviewEpoch))
|
|
73
|
+
throw new Error('latest review completion time is invalid');
|
|
74
|
+
const pending = rows.filter((row) => row.needsImplementation && row.status === 'pending');
|
|
75
|
+
const stale = pending.find((row) => Date.parse(row.decidedAt.replace(' ', 'T')) <= reviewEpoch);
|
|
76
|
+
if (stale)
|
|
77
|
+
throw new Error(`implementation input ${stale.id} is not later than the latest approved review`);
|
|
78
|
+
return [...pending].sort((left, right) => {
|
|
79
|
+
const time = Date.parse(left.decidedAt.replace(' ', 'T')) - Date.parse(right.decidedAt.replace(' ', 'T'));
|
|
80
|
+
return time || Number.parseInt(left.id.slice(3), 10) - Number.parseInt(right.id.slice(3), 10);
|
|
81
|
+
})[0] ?? null;
|
|
82
|
+
}
|
|
83
|
+
function consumeImplementationInput(rows, id, artifact) {
|
|
84
|
+
if (!ARTIFACT_RE.test(artifact))
|
|
85
|
+
throw new Error(`implementation input artifact '${artifact}' is invalid`);
|
|
86
|
+
let found = false;
|
|
87
|
+
const next = rows.map((row) => {
|
|
88
|
+
if (row.id !== id)
|
|
89
|
+
return row;
|
|
90
|
+
found = true;
|
|
91
|
+
if (row.status !== 'pending' || !row.needsImplementation) {
|
|
92
|
+
throw new Error(`implementation input ${id} is not pending`);
|
|
93
|
+
}
|
|
94
|
+
return { ...row, status: 'consumed', consumedBy: artifact };
|
|
95
|
+
});
|
|
96
|
+
if (!found)
|
|
97
|
+
throw new Error(`implementation input ${id} was not found`);
|
|
98
|
+
next.forEach(validateInput);
|
|
99
|
+
return next;
|
|
100
|
+
}
|
|
101
|
+
function renderImplementationInputs(rows) {
|
|
102
|
+
rows.forEach(validateInput);
|
|
103
|
+
const ids = new Set(rows.map((row) => row.id));
|
|
104
|
+
if (ids.size !== rows.length)
|
|
105
|
+
throw new Error('implementation input ids must be unique');
|
|
106
|
+
return [
|
|
107
|
+
`| ${COLUMNS.join(' | ')} |`,
|
|
108
|
+
'|----|-----------|-------------------|-------|----------------------|------------|--------|-------------|',
|
|
109
|
+
...rows.map((row) => {
|
|
110
|
+
const cells = [row.id, row.ledgerId, row.decisionEvidence, 'code', String(row.needsImplementation), row.decidedAt, row.status, row.consumedBy]
|
|
111
|
+
.map((value) => value.replace(/\\/g, '\\\\').replace(/\|/g, '\\|'));
|
|
112
|
+
return `| ${cells.join(' | ')} |`;
|
|
113
|
+
})
|
|
114
|
+
].join('\n');
|
|
115
|
+
}
|
|
116
|
+
export { SECTION_ALIASES as IMPLEMENTATION_INPUT_ALIASES, createImplementationInput, consumeImplementationInput, parseImplementationInputs, renderImplementationInputs, selectPendingImplementationInput };
|
|
117
|
+
//# sourceMappingURL=implementation-inputs.js.map
|
package/dist/lib/task/index.js
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
const USAGE = `Usage: ai task <command> [options]
|
|
2
2
|
|
|
3
3
|
Commands:
|
|
4
|
-
cat <ref> <artifact | N>
|
|
5
|
-
decisions, d <ref> [
|
|
6
|
-
files <ref>
|
|
7
|
-
grep <pattern> [ref]
|
|
8
|
-
issue-body <ref> [--template
|
|
9
|
-
log <ref>
|
|
4
|
+
cat [--task <ref>] <artifact | N> Print a task artifact (by name or number)
|
|
5
|
+
decisions, d [--task <ref>] [-i item] List review decisions, or show one item's detail
|
|
6
|
+
files [--task <ref>] List artifacts in a task dir (numbered)
|
|
7
|
+
grep <pattern> [--current|--task <ref>] Literal search across task artifacts (global by default)
|
|
8
|
+
issue-body [--task <ref>] [--template] Print a deterministic Issue body from task.md
|
|
9
|
+
log [--task <ref>] Render a task's activity log as a timeline
|
|
10
10
|
ls [--all | --blocked | --completed] List tasks (default: active)
|
|
11
|
-
show <
|
|
12
|
-
status <ref>
|
|
11
|
+
show [--task <ref>] Print a task.md
|
|
12
|
+
status [--task <ref>] Aggregated status view (metadata / artifacts / git / platform)
|
|
13
13
|
|
|
14
14
|
Examples:
|
|
15
15
|
ai task cat 11 analysis
|
|
16
|
+
ai task cat analysis
|
|
16
17
|
ai task cat 11 3
|
|
17
18
|
ai task decisions 11
|
|
18
|
-
ai task
|
|
19
|
+
ai task decisions --item 1
|
|
20
|
+
ai task d 11 PL-3 --format markdown
|
|
19
21
|
ai task files 11
|
|
20
22
|
ai task grep resolveArtifact
|
|
23
|
+
ai task grep resolveArtifact --current
|
|
21
24
|
ai task grep resolveArtifact 11
|
|
22
25
|
ai task issue-body 11
|
|
23
26
|
ai task issue-body 11 --template .github/ISSUE_TEMPLATE/05_other.yml
|
|
@@ -28,6 +28,23 @@ function mapFieldValue(id, fields) {
|
|
|
28
28
|
return fields.requirements;
|
|
29
29
|
return '';
|
|
30
30
|
}
|
|
31
|
+
function parseFormFields(formText) {
|
|
32
|
+
const doc = parse(formText);
|
|
33
|
+
if (!doc || typeof doc !== 'object' || !Array.isArray(doc.body)) {
|
|
34
|
+
throw new Error('Issue Form has no body[] list');
|
|
35
|
+
}
|
|
36
|
+
return doc.body;
|
|
37
|
+
}
|
|
38
|
+
function requirementFieldLabels(formText) {
|
|
39
|
+
return parseFormFields(formText).flatMap((raw) => {
|
|
40
|
+
if (!raw || typeof raw !== 'object')
|
|
41
|
+
return [];
|
|
42
|
+
const type = typeof raw.type === 'string' ? raw.type : '';
|
|
43
|
+
const id = typeof raw.id === 'string' ? raw.id : '';
|
|
44
|
+
const label = typeof raw.attributes?.label === 'string' ? raw.attributes.label.trim() : '';
|
|
45
|
+
return TEXT_FIELD_TYPES.has(type) && REQUIREMENTS_IDS.has(id) && label ? [label] : [];
|
|
46
|
+
});
|
|
47
|
+
}
|
|
31
48
|
/**
|
|
32
49
|
* Render the final Issue body for a GitHub Issue Form (scenario A).
|
|
33
50
|
*
|
|
@@ -41,12 +58,8 @@ function mapFieldValue(id, fields) {
|
|
|
41
58
|
* caller can fall back to the default body.
|
|
42
59
|
*/
|
|
43
60
|
function renderTemplateBody(formText, fields) {
|
|
44
|
-
const doc = parse(formText);
|
|
45
|
-
if (!doc || typeof doc !== 'object' || !Array.isArray(doc.body)) {
|
|
46
|
-
throw new Error('Issue Form has no body[] list');
|
|
47
|
-
}
|
|
48
61
|
const sections = [];
|
|
49
|
-
for (const raw of
|
|
62
|
+
for (const raw of parseFormFields(formText)) {
|
|
50
63
|
if (!raw || typeof raw !== 'object')
|
|
51
64
|
continue;
|
|
52
65
|
const type = typeof raw.type === 'string' ? raw.type : '';
|
|
@@ -62,5 +75,5 @@ function renderTemplateBody(formText, fields) {
|
|
|
62
75
|
}
|
|
63
76
|
return `${sections.join('\n\n')}\n`;
|
|
64
77
|
}
|
|
65
|
-
export { renderTemplateBody, mapFieldValue, PLACEHOLDER };
|
|
78
|
+
export { requirementFieldLabels, renderTemplateBody, mapFieldValue, PLACEHOLDER };
|
|
66
79
|
//# sourceMappingURL=issue-form.js.map
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { LEDGER_COLUMNS, LEDGER_HEADINGS, nextHdId, parseLedger, validateLedgerRows } from './ledger.js';
|
|
4
|
+
import { resolveTaskRef } from './resolve-ref.js';
|
|
5
|
+
import { writeTask } from './write.js';
|
|
6
|
+
const PREFIX = { analysis: 'AN', plan: 'PL', code: 'CD' };
|
|
7
|
+
const RESPONSE = new Set(['accepted', 'adjusted', 'refuted', 'cannot-judge']);
|
|
8
|
+
const DISPOSITION = new Set(['confirmed', 'closed', 'open', 'needs-human-decision']);
|
|
9
|
+
const REVIEW_ARTIFACT = {
|
|
10
|
+
analysis: /^review-analysis(?:-r(?:[2-9]|[1-9]\d+))?\.md$/,
|
|
11
|
+
plan: /^review-plan(?:-r(?:[2-9]|[1-9]\d+))?\.md$/,
|
|
12
|
+
code: /^review-code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/
|
|
13
|
+
};
|
|
14
|
+
const ARTIFACT = {
|
|
15
|
+
analysis: /^analysis(?:-r(?:[2-9]|[1-9]\d+))?\.md$/,
|
|
16
|
+
plan: /^plan(?:-r(?:[2-9]|[1-9]\d+))?\.md$/,
|
|
17
|
+
code: /^code(?:-r(?:[2-9]|[1-9]\d+))?\.md$/
|
|
18
|
+
};
|
|
19
|
+
function failed(intent, code, message, taskId = null, entityId = null) {
|
|
20
|
+
return { status: 'failed', changed: false, intent: intent.kind, taskId, entityId, before: null, after: null, operations: [], error: { code, message } };
|
|
21
|
+
}
|
|
22
|
+
function normalizedEvidence(value) {
|
|
23
|
+
return value.trim();
|
|
24
|
+
}
|
|
25
|
+
function ledgerReadErrorCode(error) {
|
|
26
|
+
const code = error && typeof error === 'object' && 'code' in error ? String(error.code) : '';
|
|
27
|
+
return code === 'TABLE_DUPLICATE_KEY' ? 'LEDGER_DUPLICATE_ID' : 'LEDGER_DOCUMENT_INVALID';
|
|
28
|
+
}
|
|
29
|
+
function maxHandshakeRounds(repoRoot) {
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(fs.readFileSync(path.join(repoRoot, '.agents', '.airc.json'), 'utf8'));
|
|
32
|
+
const value = parsed.review?.maxHandshakeRounds;
|
|
33
|
+
return Number.isInteger(value) && Number(value) > 0 ? Number(value) : 3;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return 3;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function nextFindingId(rows, stage) {
|
|
40
|
+
const prefix = PREFIX[stage];
|
|
41
|
+
let max = 0;
|
|
42
|
+
for (const row of rows) {
|
|
43
|
+
const match = new RegExp(`^${prefix}-(\\d+)$`).exec(row.id);
|
|
44
|
+
if (match)
|
|
45
|
+
max = Math.max(max, Number(match[1]));
|
|
46
|
+
}
|
|
47
|
+
return `${prefix}-${max + 1}`;
|
|
48
|
+
}
|
|
49
|
+
function reviewArtifactRound(reviewArtifact) {
|
|
50
|
+
const match = /-r([1-9]\d*)\.md$/.exec(reviewArtifact);
|
|
51
|
+
return match ? Number(match[1]) : 1;
|
|
52
|
+
}
|
|
53
|
+
function rowMutation(row) {
|
|
54
|
+
return {
|
|
55
|
+
kind: 'table-row', action: 'upsert', sectionAliases: LEDGER_HEADINGS,
|
|
56
|
+
columns: LEDGER_COLUMNS, keyColumn: 'id', key: row.id,
|
|
57
|
+
values: { stage: row.stage, round: row.round, severity: row.severity, status: row.status, evidence: row.evidence }
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function ledgerSectionMutation(content) {
|
|
61
|
+
if (/^##\s+(审查分歧账本|Review Disagreement Ledger)\s*$/m.test(content))
|
|
62
|
+
return [];
|
|
63
|
+
const english = /^##\s+Activity Log\s*$/m.test(content);
|
|
64
|
+
return [{
|
|
65
|
+
kind: 'section', aliases: LEDGER_HEADINGS, heading: english ? 'Review Disagreement Ledger' : '审查分歧账本',
|
|
66
|
+
body: `| ${LEDGER_COLUMNS.join(' | ')} |\n|----|-------|-------|----------|--------|----------|`
|
|
67
|
+
}];
|
|
68
|
+
}
|
|
69
|
+
function mapWrite(intent, entityId, before, after, result) {
|
|
70
|
+
if (result.status === 'failed')
|
|
71
|
+
return failed(intent, result.error.code, result.error.message, result.taskId, entityId);
|
|
72
|
+
return { status: result.status, changed: result.changed, intent: intent.kind, taskId: result.taskId, entityId, before, after, operations: result.operations, error: null };
|
|
73
|
+
}
|
|
74
|
+
function applyLedgerIntent(intent, options = {}) {
|
|
75
|
+
const resolved = resolveTaskRef(intent.taskRef, { repoRoot: options.repoRoot });
|
|
76
|
+
if (!resolved.ok)
|
|
77
|
+
return failed(intent, resolved.code, resolved.message, resolved.taskId);
|
|
78
|
+
if (resolved.state !== 'active')
|
|
79
|
+
return failed(intent, 'TASK_STATE_MISMATCH', `task ${resolved.taskId} is ${resolved.state}, expected active`, resolved.taskId);
|
|
80
|
+
let content;
|
|
81
|
+
let rows;
|
|
82
|
+
try {
|
|
83
|
+
content = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
84
|
+
rows = parseLedger(content);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
return failed(intent, ledgerReadErrorCode(error), error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
88
|
+
}
|
|
89
|
+
const invalidRows = validateLedgerRows(rows);
|
|
90
|
+
if (invalidRows)
|
|
91
|
+
return failed(intent, invalidRows.code, invalidRows.message, resolved.taskId);
|
|
92
|
+
if (intent.kind === 'decision-next-id') {
|
|
93
|
+
return { status: 'no-op', changed: false, intent: intent.kind, taskId: resolved.taskId, entityId: nextHdId(rows), before: null, after: null, operations: [], error: null };
|
|
94
|
+
}
|
|
95
|
+
let before = null;
|
|
96
|
+
let after;
|
|
97
|
+
if (intent.kind === 'finding-upsert') {
|
|
98
|
+
if (!REVIEW_ARTIFACT[intent.stage]?.test(intent.reviewArtifact) || !Number.isInteger(intent.ordinal) || intent.ordinal < 1 || !['blocker', 'major', 'minor'].includes(intent.severity)) {
|
|
99
|
+
return failed(intent, 'LEDGER_PAYLOAD_INVALID', 'finding identity, stage, ordinal, or severity is invalid', resolved.taskId);
|
|
100
|
+
}
|
|
101
|
+
const evidence = normalizedEvidence(intent.evidence);
|
|
102
|
+
if (!evidence.startsWith(`${intent.reviewArtifact}#`) || /[\r\n]/.test(evidence)) {
|
|
103
|
+
return failed(intent, 'LEDGER_EVIDENCE_INVALID', 'finding evidence must be a single-line anchor in the review artifact', resolved.taskId);
|
|
104
|
+
}
|
|
105
|
+
const artifactRows = rows.filter((row) => row.stage === intent.stage && row.id.startsWith(`${PREFIX[intent.stage]}-`) && row.evidence.startsWith(`${intent.reviewArtifact}#`));
|
|
106
|
+
if (artifactRows.length < intent.ordinal - 1)
|
|
107
|
+
return failed(intent, 'LEDGER_IDENTITY_CONFLICT', 'finding ordinals must be submitted in order', resolved.taskId);
|
|
108
|
+
before = artifactRows[intent.ordinal - 1] ?? null;
|
|
109
|
+
if (before) {
|
|
110
|
+
if (before.severity !== intent.severity || before.evidence !== evidence || before.status !== 'open') {
|
|
111
|
+
return failed(intent, 'LEDGER_IDENTITY_CONFLICT', 'finding identity conflicts with the existing open row', resolved.taskId, before.id);
|
|
112
|
+
}
|
|
113
|
+
after = { ...before };
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
const id = nextFindingId(rows, intent.stage);
|
|
117
|
+
after = {
|
|
118
|
+
id, stage: intent.stage, round: String(reviewArtifactRound(intent.reviewArtifact)),
|
|
119
|
+
severity: intent.severity, status: 'open', evidence, sourceLine: -1
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (intent.kind === 'decision-upsert') {
|
|
124
|
+
if (!/^HD-[1-9]\d*$/.test(intent.id) || !ARTIFACT[intent.stage]?.test(intent.artifact)) {
|
|
125
|
+
return failed(intent, 'LEDGER_PAYLOAD_INVALID', 'decision id, stage, or artifact is invalid', resolved.taskId, intent.id);
|
|
126
|
+
}
|
|
127
|
+
const evidence = `${intent.artifact}#${intent.id}`;
|
|
128
|
+
before = rows.find((row) => row.id === intent.id) ?? null;
|
|
129
|
+
if (before) {
|
|
130
|
+
if (before.stage !== intent.stage || before.round !== '-' || before.severity !== 'decision' || before.status !== 'needs-human-decision' || before.evidence !== evidence) {
|
|
131
|
+
return failed(intent, 'LEDGER_IDENTITY_CONFLICT', `decision id '${intent.id}' conflicts with an existing row`, resolved.taskId, intent.id);
|
|
132
|
+
}
|
|
133
|
+
after = { ...before };
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
if (intent.id !== nextHdId(rows))
|
|
137
|
+
return failed(intent, 'LEDGER_ID_CONFLICT', `next decision id is ${nextHdId(rows)}`, resolved.taskId, intent.id);
|
|
138
|
+
after = { id: intent.id, stage: intent.stage, round: '-', severity: 'decision', status: 'needs-human-decision', evidence, sourceLine: -1 };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
before = rows.find((row) => row.id === intent.id) ?? null;
|
|
143
|
+
if (!before || !/^(AN|PL|CD)-[1-9]\d*$/.test(before.id))
|
|
144
|
+
return failed(intent, 'LEDGER_NOT_FOUND', `finding '${intent.id}' was not found`, resolved.taskId, intent.id);
|
|
145
|
+
const evidence = normalizedEvidence(intent.evidence);
|
|
146
|
+
if (!evidence || /[\r\n]/.test(evidence))
|
|
147
|
+
return failed(intent, 'LEDGER_EVIDENCE_INVALID', 'evidence must be a non-empty single line', resolved.taskId, intent.id);
|
|
148
|
+
if (intent.kind === 'finding-respond') {
|
|
149
|
+
if (!RESPONSE.has(intent.status) || !Number.isInteger(intent.round) || intent.round < 1)
|
|
150
|
+
return failed(intent, 'LEDGER_PAYLOAD_INVALID', 'response status or round is invalid', resolved.taskId, intent.id);
|
|
151
|
+
if (before.status === intent.status && before.round === String(intent.round) && before.evidence === evidence)
|
|
152
|
+
after = { ...before };
|
|
153
|
+
else if (before.status !== 'open' || Number(before.round) + 1 !== intent.round)
|
|
154
|
+
return failed(intent, 'LEDGER_TRANSITION_INVALID', `finding '${intent.id}' cannot accept this response`, resolved.taskId, intent.id);
|
|
155
|
+
else
|
|
156
|
+
after = { ...before, round: String(intent.round), status: intent.status, evidence };
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
if (!DISPOSITION.has(intent.status))
|
|
160
|
+
return failed(intent, 'LEDGER_PAYLOAD_INVALID', 'review disposition is invalid', resolved.taskId, intent.id);
|
|
161
|
+
if (before.status === intent.status && before.evidence === evidence)
|
|
162
|
+
after = { ...before };
|
|
163
|
+
else {
|
|
164
|
+
const allowed = before.status === 'accepted'
|
|
165
|
+
? new Set(['closed', 'open', 'needs-human-decision'])
|
|
166
|
+
: before.status === 'adjusted' || before.status === 'refuted'
|
|
167
|
+
? new Set(['confirmed', 'open', 'needs-human-decision'])
|
|
168
|
+
: before.status === 'cannot-judge' ? new Set(['open', 'needs-human-decision']) : new Set();
|
|
169
|
+
const sameRoundMinorClose = before.status === 'open' && before.severity === 'minor' && intent.status === 'closed';
|
|
170
|
+
if ((!sameRoundMinorClose && !allowed.has(intent.status)) || (intent.status === 'open' && Number(before.round) >= maxHandshakeRounds(resolved.repoRoot))) {
|
|
171
|
+
return failed(intent, 'LEDGER_TRANSITION_INVALID', `finding '${intent.id}' cannot transition from ${before.status} to ${intent.status}`, resolved.taskId, intent.id);
|
|
172
|
+
}
|
|
173
|
+
after = { ...before, status: intent.status, evidence };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const result = writeTask({
|
|
178
|
+
taskRef: intent.taskRef, expectedState: 'active',
|
|
179
|
+
mutations: [...ledgerSectionMutation(content), rowMutation(after)],
|
|
180
|
+
dryRun: 'dryRun' in intent ? intent.dryRun : false
|
|
181
|
+
}, { ...options, taskLocation: { repoRoot: resolved.repoRoot, taskId: resolved.taskId, taskMdPath: resolved.taskMdPath, state: resolved.state } });
|
|
182
|
+
return mapWrite(intent, after.id, before, after, result);
|
|
183
|
+
}
|
|
184
|
+
export { applyLedgerIntent };
|
|
185
|
+
//# sourceMappingURL=ledger-intents.js.map
|