@fitlab-ai/agent-infra 0.9.2 → 0.9.3
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 +10 -9
- package/README.zh-CN.md +10 -9
- package/dist/bin/internal-cli.js +15 -0
- package/dist/lib/agent-clients/adapter.js +45 -2
- package/dist/lib/agent-clients/adapters/antigravity-cli.js +64 -0
- package/dist/lib/agent-clients/adapters/claude-code.js +10 -1
- package/dist/lib/agent-clients/adapters/codex.js +9 -0
- package/dist/lib/agent-clients/adapters/index.js +2 -2
- package/dist/lib/agent-clients/adapters/opencode.js +9 -0
- package/dist/lib/agent-clients/config.js +42 -4
- package/dist/lib/agent-clients/next-steps.js +11 -2
- package/dist/lib/agent-clients/reconcile.js +2 -1
- package/dist/lib/agent-clients/registry.js +7 -1
- package/dist/lib/agent-clients/schema.js +18 -0
- package/dist/lib/agent-clients/tokens.js +49 -0
- package/dist/lib/agent-clients/types.js +1 -1
- package/dist/lib/defaults.json +1 -1
- package/dist/lib/git/workflow.js +54 -1
- package/dist/lib/internal/agent-client.js +61 -4
- package/dist/lib/internal/git-workflow.js +6 -1
- package/dist/lib/internal/platform-checks.js +3 -3
- package/dist/lib/internal/platform-comment.js +29 -2
- package/dist/lib/internal/platform-issue.js +7 -0
- package/dist/lib/internal/platform-pr-review.js +132 -0
- package/dist/lib/internal/platform-pr.js +20 -2
- package/dist/lib/internal/platform-release-notes.js +52 -16
- package/dist/lib/internal/pr-review-grade.js +140 -0
- package/dist/lib/internal/release-workflow.js +13 -6
- package/dist/lib/internal/task-activity.js +73 -0
- package/dist/lib/internal/task-event.js +17 -1
- package/dist/lib/internal/task-lifecycle.js +7 -0
- package/dist/lib/internal/task-orchestration.js +51 -6
- package/dist/lib/internal/task-review.js +8 -3
- package/dist/lib/platform/adapters.js +8 -1
- package/dist/lib/platform/completion-backfill.js +122 -0
- package/dist/lib/platform/issue-comments.js +3 -2
- package/dist/lib/platform/merged-pr-equivalence.js +115 -5
- package/dist/lib/platform/pr-checks.js +64 -41
- package/dist/lib/platform/pr-review.js +166 -0
- package/dist/lib/platform/pull-requests.js +324 -3
- package/dist/lib/platform/release-notes.js +85 -3
- package/dist/lib/pr-review/evidence-grading.js +229 -0
- package/dist/lib/run/tui.js +3 -5
- package/dist/lib/sandbox/commands/create.js +0 -20
- package/dist/lib/sandbox/commands/show.js +1 -1
- package/dist/lib/task/activity-intent.js +101 -0
- package/dist/lib/task/artifact-lifecycle.js +2 -1
- package/dist/lib/task/commands/log.js +15 -14
- package/dist/lib/task/delegation-receipts.js +23 -2
- package/dist/lib/task/events.js +67 -28
- package/dist/lib/task/finalization-artifacts.js +35 -0
- package/dist/lib/task/lifecycle-execution.js +46 -0
- package/dist/lib/task/orchestration.js +408 -44
- package/dist/lib/task/review-finalization.js +29 -9
- package/dist/lib/task/task-execution-lock.js +231 -0
- package/dist/lib/task/verification-checks.js +1 -1
- package/dist/lib/task/verification-engine.js +218 -2
- package/dist/lib/task/verification.js +4 -3
- package/dist/lib/task/workspace-snapshot.js +17 -5
- package/lib/agent-clients/adapter.ts +75 -2
- package/lib/agent-clients/adapters/antigravity-cli.ts +65 -0
- package/lib/agent-clients/adapters/claude-code.ts +10 -1
- package/lib/agent-clients/adapters/codex.ts +9 -0
- package/lib/agent-clients/adapters/index.ts +2 -2
- package/lib/agent-clients/adapters/opencode.ts +9 -0
- package/lib/agent-clients/config.ts +49 -4
- package/lib/agent-clients/next-steps.ts +15 -2
- package/lib/agent-clients/reconcile.ts +2 -1
- package/lib/agent-clients/registry.ts +10 -0
- package/lib/agent-clients/schema.ts +18 -0
- package/lib/agent-clients/tokens.ts +53 -0
- package/lib/agent-clients/types.ts +15 -1
- package/lib/defaults.json +1 -1
- package/lib/git/workflow.ts +66 -2
- package/lib/internal/agent-client.ts +59 -4
- package/lib/internal/git-workflow.ts +5 -1
- package/lib/internal/platform-checks.ts +4 -4
- package/lib/internal/platform-comment.ts +17 -2
- package/lib/internal/platform-issue.ts +4 -0
- package/lib/internal/platform-pr-review.ts +104 -0
- package/lib/internal/platform-pr.ts +14 -1
- package/lib/internal/platform-release-notes.ts +59 -16
- package/lib/internal/pr-review-grade.ts +130 -0
- package/lib/internal/release-workflow.ts +13 -6
- package/lib/internal/task-activity.ts +55 -0
- package/lib/internal/task-event.ts +9 -1
- package/lib/internal/task-lifecycle.ts +4 -0
- package/lib/internal/task-orchestration.ts +45 -6
- package/lib/internal/task-review.ts +8 -3
- package/lib/platform/adapters.ts +29 -2
- package/lib/platform/completion-backfill.ts +134 -0
- package/lib/platform/issue-comments.ts +3 -2
- package/lib/platform/merged-pr-equivalence.ts +127 -5
- package/lib/platform/pr-checks.ts +72 -45
- package/lib/platform/pr-review.ts +201 -0
- package/lib/platform/pull-requests.ts +395 -2
- package/lib/platform/release-notes.ts +100 -4
- package/lib/pr-review/evidence-grading.ts +318 -0
- package/lib/run/tui.ts +3 -4
- package/lib/sandbox/commands/create.ts +0 -20
- package/lib/sandbox/commands/show.ts +1 -1
- package/lib/server/server.schema.json +2 -2
- package/lib/task/activity-intent.ts +128 -0
- package/lib/task/artifact-lifecycle.ts +2 -1
- package/lib/task/commands/log.ts +15 -14
- package/lib/task/delegation-receipts.ts +32 -3
- package/lib/task/events.ts +75 -30
- package/lib/task/finalization-artifacts.ts +58 -0
- package/lib/task/lifecycle-execution.ts +106 -0
- package/lib/task/orchestration.ts +543 -64
- package/lib/task/review-finalization.ts +40 -9
- package/lib/task/task-execution-lock.ts +296 -0
- package/lib/task/verification-checks.ts +1 -1
- package/lib/task/verification-engine.ts +249 -2
- package/lib/task/verification.ts +5 -3
- package/lib/task/workspace-snapshot.ts +26 -5
- package/package.json +3 -3
- package/templates/.agents/QUICKSTART.en.md +25 -8
- package/templates/.agents/QUICKSTART.zh-CN.md +25 -8
- package/templates/.agents/README.en.md +10 -7
- package/templates/.agents/README.zh-CN.md +10 -7
- package/templates/.agents/hooks/lifecycle-delegation.js +15 -4
- package/templates/.agents/rules/create-issue.github.en.md +4 -2
- package/templates/.agents/rules/create-issue.github.zh-CN.md +4 -2
- package/templates/.agents/rules/issue-fields.github.en.md +3 -1
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +3 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +5 -3
- package/templates/.agents/rules/issue-pr-commands.github.en.md +5 -3
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +5 -3
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +5 -3
- package/templates/.agents/rules/issue-sync.github.en.md +7 -3
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +8 -4
- package/templates/.agents/rules/lifecycle-orchestration.en.md +5 -2
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +5 -2
- package/templates/.agents/rules/milestone-inference.github.en.md +4 -2
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +4 -2
- package/templates/.agents/rules/next-step-output.en.md +3 -1
- package/templates/.agents/rules/next-step-output.zh-CN.md +3 -1
- package/templates/.agents/rules/no-mid-flow-questions.en.md +17 -0
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +17 -0
- package/templates/.agents/rules/pr-checks-commands.en.md +3 -3
- package/templates/.agents/rules/pr-checks-commands.github.en.md +2 -2
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +2 -2
- package/templates/.agents/rules/pr-checks-commands.zh-CN.md +3 -3
- package/templates/.agents/rules/pr-sync.en.md +3 -1
- package/templates/.agents/rules/pr-sync.github.en.md +11 -1
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +11 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +3 -1
- package/templates/.agents/rules/release-commands.en.md +1 -1
- package/templates/.agents/rules/release-commands.github.en.md +12 -2
- package/templates/.agents/rules/release-commands.github.zh-CN.md +12 -2
- package/templates/.agents/rules/release-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/task-management.en.md +11 -0
- package/templates/.agents/rules/task-management.zh-CN.md +11 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +10 -7
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +10 -7
- package/templates/.agents/skills/block-task/SKILL.en.md +7 -5
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +7 -5
- package/templates/.agents/skills/cancel-task/SKILL.en.md +6 -4
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +6 -4
- package/templates/.agents/skills/close-codescan/SKILL.en.md +3 -1
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +3 -1
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +3 -1
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +9 -6
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +11 -8
- package/templates/.agents/skills/commit/SKILL.en.md +3 -1
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -1
- package/templates/.agents/skills/commit/reference/commit-message.en.md +1 -1
- package/templates/.agents/skills/commit/reference/commit-message.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +6 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +6 -4
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +21 -6
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +21 -6
- package/templates/.agents/skills/complete-task/config/verify.en.json +1 -0
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +17 -0
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +17 -0
- package/templates/.agents/skills/create-pr/SKILL.en.md +3 -1
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +3 -1
- package/templates/.agents/skills/create-pr/reference/comment-publish.en.md +1 -1
- package/templates/.agents/skills/create-pr/reference/comment-publish.zh-CN.md +1 -1
- package/templates/.agents/skills/create-release-note/SKILL.en.md +17 -16
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +17 -16
- package/templates/.agents/skills/create-task/SKILL.en.md +5 -3
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/import-issue/SKILL.en.md +5 -3
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/plan-task/SKILL.en.md +8 -5
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +8 -5
- package/templates/.agents/skills/post-release/SKILL.en.md +2 -0
- package/templates/.agents/skills/post-release/SKILL.zh-CN.md +2 -0
- package/templates/.agents/skills/release/SKILL.en.md +16 -10
- package/templates/.agents/skills/release/SKILL.zh-CN.md +16 -10
- package/templates/.agents/skills/restore-task/SKILL.en.md +4 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +7 -4
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +7 -4
- package/templates/.agents/skills/review-code/SKILL.en.md +9 -6
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +9 -6
- package/templates/.agents/skills/review-plan/SKILL.en.md +7 -4
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +7 -4
- package/templates/.agents/skills/review-pr/SKILL.en.md +158 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +158 -0
- package/templates/.agents/skills/review-pr/config/verify.en.json +37 -0
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +37 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +65 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +65 -0
- package/templates/.agents/skills/review-pr/reference/output-guidance.en.md +18 -0
- package/templates/.agents/skills/review-pr/reference/output-guidance.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +85 -0
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +85 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +8 -8
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/run-task/config/verify.en.json +2 -1
- package/templates/.agents/skills/run-task/config/verify.zh-CN.json +2 -1
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +20 -0
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +20 -0
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +35 -61
- package/templates/.agents/skills/watch-pr/SKILL.en.md +13 -13
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +13 -13
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.en.md +27 -6
- package/templates/.agents/skills/watch-pr/reference/monitor-and-heal.zh-CN.md +26 -5
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.agents/workflows/bug-fix.en.yaml +3 -3
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +3 -3
- package/templates/.agents/workflows/code-review.en.yaml +1 -1
- package/templates/.agents/workflows/code-review.zh-CN.yaml +1 -1
- package/templates/.agents/workflows/feature-development.en.yaml +4 -4
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +4 -4
- package/templates/.agents/workflows/refactoring.en.yaml +3 -3
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +3 -3
- package/templates/.claude/commands/post-release.en.md +1 -0
- package/templates/.claude/commands/post-release.zh-CN.md +1 -0
- package/templates/.claude/commands/review-pr.en.md +8 -0
- package/templates/.claude/commands/review-pr.zh-CN.md +8 -0
- package/templates/.gemini/commands/_project_/review-pr.en.toml +10 -0
- package/templates/.gemini/commands/_project_/review-pr.zh-CN.toml +10 -0
- package/templates/.opencode/commands/post-release.en.md +2 -0
- package/templates/.opencode/commands/post-release.zh-CN.md +2 -0
- package/templates/.opencode/commands/review-pr.en.md +11 -0
- package/templates/.opencode/commands/review-pr.zh-CN.md +11 -0
- package/dist/lib/agent-clients/adapters/gemini-cli.js +0 -64
- package/lib/agent-clients/adapters/gemini-cli.ts +0 -65
- package/templates/.gemini/commands/_project_/analyze-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/analyze-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/archive-tasks.en.toml +0 -10
- package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/block-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/block-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/cancel-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/cancel-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/check-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/check-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/close-codescan.en.toml +0 -8
- package/templates/.gemini/commands/_project_/close-codescan.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/close-dependabot.en.toml +0 -8
- package/templates/.gemini/commands/_project_/close-dependabot.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/code-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/commit.en.toml +0 -10
- package/templates/.gemini/commands/_project_/commit.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-manual-validation.en.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-manual-validation.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/complete-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/create-pr.en.toml +0 -10
- package/templates/.gemini/commands/_project_/create-pr.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/create-release-note.en.toml +0 -8
- package/templates/.gemini/commands/_project_/create-release-note.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/create-task.en.toml +0 -8
- package/templates/.gemini/commands/_project_/create-task.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/import-codescan.en.toml +0 -8
- package/templates/.gemini/commands/_project_/import-codescan.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/import-dependabot.en.toml +0 -8
- package/templates/.gemini/commands/_project_/import-dependabot.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/import-issue.en.toml +0 -8
- package/templates/.gemini/commands/_project_/import-issue.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/init-labels.en.toml +0 -8
- package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/init-milestones.en.toml +0 -10
- package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/plan-task.en.toml +0 -10
- package/templates/.gemini/commands/_project_/plan-task.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/post-release.en.toml +0 -6
- package/templates/.gemini/commands/_project_/post-release.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/refine-title.en.toml +0 -8
- package/templates/.gemini/commands/_project_/refine-title.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/release.en.toml +0 -8
- package/templates/.gemini/commands/_project_/release.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/restore-task.en.toml +0 -8
- package/templates/.gemini/commands/_project_/restore-task.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/review-analysis.en.toml +0 -10
- package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/review-code.en.toml +0 -10
- package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/review-plan.en.toml +0 -10
- package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +0 -10
- package/templates/.gemini/commands/_project_/run-task.en.toml +0 -8
- package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/test-integration.en.toml +0 -6
- package/templates/.gemini/commands/_project_/test-integration.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/test.en.toml +0 -6
- package/templates/.gemini/commands/_project_/test.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/update-agent-infra.en.toml +0 -6
- package/templates/.gemini/commands/_project_/update-agent-infra.zh-CN.toml +0 -6
- package/templates/.gemini/commands/_project_/upgrade-dependency.en.toml +0 -8
- package/templates/.gemini/commands/_project_/upgrade-dependency.zh-CN.toml +0 -8
- package/templates/.gemini/commands/_project_/watch-pr.en.toml +0 -10
- package/templates/.gemini/commands/_project_/watch-pr.zh-CN.toml +0 -10
- package/templates/.gemini/settings.json +0 -3
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseTaskFrontmatter } from '../task/frontmatter.js';
|
|
4
|
+
export class HostResolutionError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(code, message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = 'HostResolutionError';
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function toPositiveNumber(value) {
|
|
13
|
+
const n = Number(value);
|
|
14
|
+
return Number.isInteger(n) && n > 0 ? n : null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse the PR body for closing-issue references. Handles the conventional
|
|
18
|
+
* `Closes #1` / `Fixes: #2, #3` shapes (case-insensitive, comma/space
|
|
19
|
+
* separated, optional keyword list on the same logical line).
|
|
20
|
+
*/
|
|
21
|
+
export function extractClosingIssueNumbers(body) {
|
|
22
|
+
const result = [];
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
const linePattern = /(?:^|\n)[^\n]*\b(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\b[^\n]*/gi;
|
|
25
|
+
let lineMatch;
|
|
26
|
+
while ((lineMatch = linePattern.exec(body)) !== null) {
|
|
27
|
+
const line = lineMatch[0];
|
|
28
|
+
for (const numMatch of line.matchAll(/#(\d+)/g)) {
|
|
29
|
+
const n = Number(numMatch[1]);
|
|
30
|
+
if (Number.isInteger(n) && n > 0 && !seen.has(n)) {
|
|
31
|
+
seen.add(n);
|
|
32
|
+
result.push(n);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Scan `.agents/workspace/active/{task-id}/task.md` files for tasks bound to the
|
|
40
|
+
* PR number or to one of the PR's closing issues. A task is emitted at most once;
|
|
41
|
+
* a direct `pr_number` hit takes priority over the issue-number reverse lookup.
|
|
42
|
+
*/
|
|
43
|
+
export function collectHostCandidates(input) {
|
|
44
|
+
const activeRoot = path.join(input.workspaceRoot, '.agents', 'workspace', 'active');
|
|
45
|
+
const candidates = [];
|
|
46
|
+
let entries;
|
|
47
|
+
try {
|
|
48
|
+
entries = fs.readdirSync(activeRoot, { withFileTypes: true });
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
if (!entry.isDirectory())
|
|
55
|
+
continue;
|
|
56
|
+
const taskDir = path.join(activeRoot, entry.name);
|
|
57
|
+
const taskMdPath = path.join(taskDir, 'task.md');
|
|
58
|
+
let content;
|
|
59
|
+
try {
|
|
60
|
+
content = fs.readFileSync(taskMdPath, 'utf8');
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const frontmatter = parseTaskFrontmatter(content);
|
|
66
|
+
const issueNumber = toPositiveNumber(frontmatter.issue_number);
|
|
67
|
+
const prNumber = toPositiveNumber(frontmatter.pr_number);
|
|
68
|
+
if (prNumber === input.prNumber) {
|
|
69
|
+
candidates.push({ taskId: entry.name, taskDir, issueNumber, prNumber });
|
|
70
|
+
}
|
|
71
|
+
else if (issueNumber !== null && input.closingIssues.includes(issueNumber)) {
|
|
72
|
+
candidates.push({ taskId: entry.name, taskDir, issueNumber, prNumber });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return candidates;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Collapse a candidate list into a typed HostResolution. Zero candidates ->
|
|
79
|
+
* none; exactly one -> unique; more than one (no stable selection rule) ->
|
|
80
|
+
* ambiguous (fail closed, AN-6).
|
|
81
|
+
*/
|
|
82
|
+
export function resolveHostFromCandidates(candidates) {
|
|
83
|
+
if (candidates.length === 0)
|
|
84
|
+
return { kind: 'none' };
|
|
85
|
+
if (candidates.length === 1) {
|
|
86
|
+
const candidate = candidates[0];
|
|
87
|
+
return {
|
|
88
|
+
kind: 'unique',
|
|
89
|
+
taskId: candidate.taskId,
|
|
90
|
+
taskDir: candidate.taskDir,
|
|
91
|
+
issueNumber: candidate.issueNumber ?? 0,
|
|
92
|
+
prNumber: candidate.prNumber ?? 0
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
kind: 'ambiguous',
|
|
97
|
+
candidates: candidates.map((candidate) => ({ taskId: candidate.taskId, issueNumber: candidate.issueNumber ?? 0 }))
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function hasNoLifecycleArtifacts(presence) {
|
|
101
|
+
return !presence.hasAnalysis && !presence.hasPlan && !presence.hasCode &&
|
|
102
|
+
!presence.hasReviewAnalysis && !presence.hasReviewPlan && !presence.hasReviewCode &&
|
|
103
|
+
!presence.hasPriorPrReview;
|
|
104
|
+
}
|
|
105
|
+
function hasFullArtifacts(presence) {
|
|
106
|
+
return presence.hasAnalysis && presence.hasPlan && presence.hasCode &&
|
|
107
|
+
presence.hasReviewAnalysis && presence.hasReviewPlan && presence.hasReviewCode;
|
|
108
|
+
}
|
|
109
|
+
function isTrusted(head) {
|
|
110
|
+
return head.issueNumberBound && head.taskIssueMatches && (!head.prNumberBound || head.taskPrMatches);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Derive the S1(a) trust factor `taskIssueMatches` (PL-3) mechanically from
|
|
114
|
+
* resolved data: a unique host is trusted on the issue dimension only when the
|
|
115
|
+
* task's bound issue_number is among the PR's closing issues. Ambiguous/none
|
|
116
|
+
* hosts and tasks without a positive issue_number cannot be confirmed -> false
|
|
117
|
+
* (fail closed to S2/audit). `resolve-host` emits this value so the prompt layer
|
|
118
|
+
* does not derive the trust factor ad hoc (CD-2).
|
|
119
|
+
*/
|
|
120
|
+
export function deriveTaskIssueMatches(host, closingIssues) {
|
|
121
|
+
return host.kind === 'unique' && host.issueNumber > 0 && closingIssues.includes(host.issueNumber);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* S1 -> S2 -> S3 classification (analysis §6.1). The ambiguous host is rejected
|
|
125
|
+
* before classification (AN-6 fail closed). S3(a) is host.kind === 'none';
|
|
126
|
+
* S3(b) is a unique task with no lifecycle artifacts and no prior pr-review
|
|
127
|
+
* (PL-5/PL-9 symmetric: any review-only task falls to S2).
|
|
128
|
+
*/
|
|
129
|
+
export function classifyScenario(host, presence, head) {
|
|
130
|
+
if (host.kind === 'ambiguous') {
|
|
131
|
+
throw new HostResolutionError('HOST_AMBIGUOUS', 'multiple candidate hosts; resolve before evidence classification');
|
|
132
|
+
}
|
|
133
|
+
if (host.kind === 'none')
|
|
134
|
+
return 'S3';
|
|
135
|
+
if (hasNoLifecycleArtifacts(presence))
|
|
136
|
+
return 'S3';
|
|
137
|
+
const priorHeadMatches = presence.hasPriorPrReview && head.priorHeadSha !== null && head.priorHeadSha === head.currentHeadSha;
|
|
138
|
+
if (hasFullArtifacts(presence) && priorHeadMatches && isTrusted(head))
|
|
139
|
+
return 'S1';
|
|
140
|
+
return 'S2';
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Freshness is benchmarked against the prior `pr-review*` reviewed head SHA
|
|
144
|
+
* (analysis §6.2, AN-7). No prior review -> n/a/n/a (first-review special case).
|
|
145
|
+
*/
|
|
146
|
+
export function evaluateHead(head) {
|
|
147
|
+
if (head.priorHeadSha === null)
|
|
148
|
+
return { freshness: 'n/a', alignment: 'n/a' };
|
|
149
|
+
const freshness = head.priorHeadSha === head.currentHeadSha ? 'fresh' : 'stale';
|
|
150
|
+
const aligned = freshness === 'fresh' && isTrusted(head);
|
|
151
|
+
return { freshness, alignment: aligned ? 'aligned' : 'misaligned' };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Pure-evidence risk aggregation (analysis §6.3, AN-5): any priority factor
|
|
155
|
+
* (sensitivity / sourceCredibility) HIGH -> HIGH; otherwise any HIGH -> MEDIUM;
|
|
156
|
+
* all LOW -> LOW. Identity factors are structurally absent from the input type.
|
|
157
|
+
*/
|
|
158
|
+
export function gradeRisk(factors) {
|
|
159
|
+
const priority = [factors.sensitivity, factors.sourceCredibility];
|
|
160
|
+
if (priority.includes('HIGH'))
|
|
161
|
+
return 'HIGH';
|
|
162
|
+
const values = Object.values(factors);
|
|
163
|
+
if (values.includes('HIGH'))
|
|
164
|
+
return 'MEDIUM';
|
|
165
|
+
return 'LOW';
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* verify / audit / reconstruct selection matrix (analysis §6.4). S3 ->
|
|
169
|
+
* reconstruct; S2 -> audit; S1 fresh+aligned -> verify (LOW/MEDIUM risk) or
|
|
170
|
+
* audit (HIGH risk); any other S1 combination falls back to audit.
|
|
171
|
+
*/
|
|
172
|
+
export function selectMode(scenario, freshness, alignment, risk) {
|
|
173
|
+
if (scenario === 'S3')
|
|
174
|
+
return 'reconstruct';
|
|
175
|
+
if (scenario === 'S2')
|
|
176
|
+
return 'audit';
|
|
177
|
+
if (freshness === 'fresh' && alignment === 'aligned') {
|
|
178
|
+
return risk === 'HIGH' ? 'audit' : 'verify';
|
|
179
|
+
}
|
|
180
|
+
return 'audit';
|
|
181
|
+
}
|
|
182
|
+
function buildReason(input) {
|
|
183
|
+
const pieces = [];
|
|
184
|
+
if (input.firstReview)
|
|
185
|
+
pieces.push('first review (no prior pr-review head)');
|
|
186
|
+
if (input.hasPriorPrReview)
|
|
187
|
+
pieces.push(`prior head ${input.freshness}`);
|
|
188
|
+
if (input.freshness === 'fresh')
|
|
189
|
+
pieces.push(`alignment ${input.alignment}`);
|
|
190
|
+
pieces.push(`evidence scenario ${input.scenario}`);
|
|
191
|
+
pieces.push(`risk ${input.risk}`);
|
|
192
|
+
pieces.push(`mode ${input.mode}`);
|
|
193
|
+
return pieces.join('; ');
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Full decision pipeline: classify -> freshness/alignment -> risk -> mode,
|
|
197
|
+
* producing a traceable DecisionRecord (AC3). Ambiguous hosts are rejected
|
|
198
|
+
* before any classification runs (AN-6).
|
|
199
|
+
*/
|
|
200
|
+
export function decide(input) {
|
|
201
|
+
if (input.host.kind === 'ambiguous') {
|
|
202
|
+
throw new HostResolutionError('HOST_AMBIGUOUS', 'ambiguous host; resolve before evidence classification');
|
|
203
|
+
}
|
|
204
|
+
const scenario = classifyScenario(input.host, input.presence, input.head);
|
|
205
|
+
const { freshness, alignment } = evaluateHead(input.head);
|
|
206
|
+
const risk = gradeRisk(input.riskFactors);
|
|
207
|
+
const mode = selectMode(scenario, freshness, alignment, risk);
|
|
208
|
+
const firstReview = !input.presence.hasPriorPrReview;
|
|
209
|
+
return {
|
|
210
|
+
host: input.host,
|
|
211
|
+
scenario,
|
|
212
|
+
freshness,
|
|
213
|
+
alignment,
|
|
214
|
+
risk,
|
|
215
|
+
mode,
|
|
216
|
+
firstReview,
|
|
217
|
+
reason: buildReason({
|
|
218
|
+
scenario,
|
|
219
|
+
freshness,
|
|
220
|
+
alignment,
|
|
221
|
+
risk,
|
|
222
|
+
mode,
|
|
223
|
+
firstReview,
|
|
224
|
+
hasPriorPrReview: input.presence.hasPriorPrReview
|
|
225
|
+
})
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
export { hasFullArtifacts, hasNoLifecycleArtifacts, isTrusted };
|
|
229
|
+
//# sourceMappingURL=evidence-grading.js.map
|
package/dist/lib/run/tui.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { renderAgentClientInvocation } from '../agent-clients/invocation.js';
|
|
2
2
|
import { getAgentClientAdapter } from '../agent-clients/registry.js';
|
|
3
|
-
const TUI_NAMES = new Set(['claude', 'codex', '
|
|
3
|
+
const TUI_NAMES = new Set(['claude', 'codex', 'antigravity', 'opencode']);
|
|
4
4
|
function isTuiName(value) {
|
|
5
5
|
return typeof value === 'string' && TUI_NAMES.has(value);
|
|
6
6
|
}
|
|
@@ -25,15 +25,13 @@ export function renderPrompt(params) {
|
|
|
25
25
|
args: params.args
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
|
-
if (params.tui === 'gemini')
|
|
29
|
-
return `/agent-infra:${suffix}`;
|
|
30
28
|
return `/${suffix}`;
|
|
31
29
|
}
|
|
32
30
|
export function buildTuiCommand(tui, prompt) {
|
|
33
31
|
if (tui === 'claude')
|
|
34
32
|
return ['claude', ['--dangerously-skip-permissions', '--print', prompt]];
|
|
35
|
-
if (tui === '
|
|
36
|
-
return ['
|
|
33
|
+
if (tui === 'antigravity')
|
|
34
|
+
return ['agy', ['--dangerously-skip-permissions', '--print', prompt]];
|
|
37
35
|
if (tui === 'opencode')
|
|
38
36
|
return ['opencode', ['run', '--dangerously-skip-permissions', prompt]];
|
|
39
37
|
return ['codex', ['exec', '--dangerously-bypass-approvals-and-sandbox', prompt]];
|
|
@@ -729,22 +729,6 @@ export function ensureOpenCodeModelInheritance(toolDir, hostHomeDir) {
|
|
|
729
729
|
fs.writeFileSync(sandboxConfigPath, JSON.stringify(sandboxJson, null, 2), 'utf8');
|
|
730
730
|
}
|
|
731
731
|
}
|
|
732
|
-
export function ensureGeminiWorkspaceTrust(toolDir) {
|
|
733
|
-
const trustPath = path.join(toolDir, 'trustedFolders.json');
|
|
734
|
-
let data = {};
|
|
735
|
-
if (fs.existsSync(trustPath)) {
|
|
736
|
-
try {
|
|
737
|
-
data = JSON.parse(fs.readFileSync(trustPath, 'utf8'));
|
|
738
|
-
}
|
|
739
|
-
catch {
|
|
740
|
-
// malformed JSON, start fresh
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
if (data['/workspace'] !== 'TRUST_FOLDER') {
|
|
744
|
-
data['/workspace'] = 'TRUST_FOLDER';
|
|
745
|
-
fs.writeFileSync(trustPath, JSON.stringify(data, null, 2), 'utf8');
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
732
|
export function sandboxAliasesPath(home) {
|
|
749
733
|
return hostJoin(home, '.agent-infra', 'aliases', 'sandbox.sh');
|
|
750
734
|
}
|
|
@@ -1125,10 +1109,6 @@ export async function create(args) {
|
|
|
1125
1109
|
// provider/API settings are enough for Claude Code. If no usable
|
|
1126
1110
|
// auth was present, the claude-code entry was removed above.
|
|
1127
1111
|
}
|
|
1128
|
-
const geminiEntry = effectiveResolvedTools.find(({ tool }) => tool.id === 'gemini-cli');
|
|
1129
|
-
if (geminiEntry) {
|
|
1130
|
-
ensureGeminiWorkspaceTrust(geminiEntry.dir);
|
|
1131
|
-
}
|
|
1132
1112
|
const opencodeEntry = effectiveResolvedTools.find(({ tool }) => tool.id === 'opencode');
|
|
1133
1113
|
if (opencodeEntry) {
|
|
1134
1114
|
// The TUI reads <toolDir>/opencode.json via OPENCODE_CONFIG pinned in tools.js.
|
|
@@ -8,7 +8,7 @@ import { resolveTools, toolConfigDirCandidates } from '../tools.js';
|
|
|
8
8
|
const USAGE = `Usage: ai sandbox show <branch | TASK-id | N>
|
|
9
9
|
|
|
10
10
|
Shows one sandbox's worktree path and per-tool state paths (Claude Code,
|
|
11
|
-
Codex,
|
|
11
|
+
Codex, Antigravity CLI, OpenCode). The argument follows the same contract as
|
|
12
12
|
'ai sandbox exec' and 'ai sandbox start': N (bare) is the recommended form
|
|
13
13
|
for task short ids (e.g. 'ai sandbox show 11'); a TASK-id or a plain
|
|
14
14
|
branch name are also accepted. Use 'ai sandbox ls' for the container list.`;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveTaskRef } from './resolve-ref.js';
|
|
4
|
+
import { locateActivityLog, appendActivityEntry } from './activity-log.js';
|
|
5
|
+
import { buildArtifactLinkSection, parseArtifactName } from './artifact-lifecycle.js';
|
|
6
|
+
import { captureTaskWriteMetadata, writeTask } from './write.js';
|
|
7
|
+
function failed(intent, code, message, taskId = null) {
|
|
8
|
+
return {
|
|
9
|
+
status: 'failed', changed: false, intent: 'append', taskId,
|
|
10
|
+
artifact: intent.artifact ?? null, operations: [], error: { code, message }
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function oneLine(value) {
|
|
14
|
+
return value.replace(/\s*\r?\n\s*/g, ' ').trim();
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Append an Activity Log entry (and, optionally, a `## 审查反馈` artifact link)
|
|
18
|
+
* to an active task via the atomic `writeTask` path. `current_step` is never
|
|
19
|
+
* touched (PL-2): review-pr does not join the standard stage chain.
|
|
20
|
+
*/
|
|
21
|
+
export function applyActivityAppendIntent(intent, options = {}) {
|
|
22
|
+
if (intent.kind !== 'append')
|
|
23
|
+
return failed(intent, 'ACTIVITY_INTENT_INVALID', 'intent kind must be append');
|
|
24
|
+
const resolved = resolveTaskRef(intent.taskRef, { repoRoot: options.repoRoot });
|
|
25
|
+
if (!resolved.ok)
|
|
26
|
+
return failed(intent, resolved.code, resolved.message, resolved.taskId);
|
|
27
|
+
if (resolved.state !== 'active') {
|
|
28
|
+
return failed(intent, 'TASK_STATE_MISMATCH', `task ${resolved.taskId} is ${resolved.state}, expected active`, resolved.taskId);
|
|
29
|
+
}
|
|
30
|
+
const step = oneLine(intent.step);
|
|
31
|
+
const agent = oneLine(intent.agent);
|
|
32
|
+
const note = oneLine(intent.note);
|
|
33
|
+
if (!step || !agent || !note || /[\r\n]/.test(intent.step) || /[\r\n]/.test(intent.agent) || /[\r\n]/.test(intent.note)) {
|
|
34
|
+
return failed(intent, 'ACTIVITY_INTENT_INVALID', 'step, agent and note must be non-empty single-line values', resolved.taskId);
|
|
35
|
+
}
|
|
36
|
+
let artifact = null;
|
|
37
|
+
if (intent.artifact !== undefined) {
|
|
38
|
+
artifact = parseArtifactName(intent.artifact);
|
|
39
|
+
if (!artifact || artifact.family !== 'pr-review') {
|
|
40
|
+
return failed(intent, 'ACTIVITY_ARTIFACT_INVALID', `artifact '${intent.artifact}' is not a canonical pr-review artifact`, resolved.taskId);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
let content;
|
|
44
|
+
try {
|
|
45
|
+
content = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return failed(intent, 'TASK_READ_FAILED', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
49
|
+
}
|
|
50
|
+
const section = locateActivityLog(content);
|
|
51
|
+
if (!section) {
|
|
52
|
+
return failed(intent, 'ACTIVITY_SECTION_MISSING', 'task has no unique Activity Log section', resolved.taskId);
|
|
53
|
+
}
|
|
54
|
+
let metadata;
|
|
55
|
+
try {
|
|
56
|
+
metadata = (options.metadataProvider ?? captureTaskWriteMetadata)();
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return failed(intent, 'METADATA_CAPTURE_FAILED', error instanceof Error ? error.message : String(error), resolved.taskId);
|
|
60
|
+
}
|
|
61
|
+
const mutations = [];
|
|
62
|
+
const activityBody = appendActivityEntry(section, { time: metadata.timestamp, step, agent, note });
|
|
63
|
+
mutations.push({ kind: 'section', aliases: ['活动日志', 'Activity Log'], heading: section.heading, body: activityBody });
|
|
64
|
+
if (artifact) {
|
|
65
|
+
const link = buildArtifactLinkSection(content, {
|
|
66
|
+
...artifact,
|
|
67
|
+
path: path.join(resolved.taskDir, artifact.name),
|
|
68
|
+
size: 0,
|
|
69
|
+
mtimeMs: 0
|
|
70
|
+
});
|
|
71
|
+
mutations.push({ kind: 'section', aliases: link.aliases, heading: link.heading, body: link.body });
|
|
72
|
+
}
|
|
73
|
+
const writeResult = writeTask({
|
|
74
|
+
taskRef: intent.taskRef,
|
|
75
|
+
expectedState: 'active',
|
|
76
|
+
mutations,
|
|
77
|
+
dryRun: intent.dryRun
|
|
78
|
+
}, {
|
|
79
|
+
...options,
|
|
80
|
+
taskLocation: {
|
|
81
|
+
repoRoot: resolved.repoRoot,
|
|
82
|
+
taskId: resolved.taskId,
|
|
83
|
+
taskMdPath: resolved.taskMdPath,
|
|
84
|
+
state: resolved.state
|
|
85
|
+
},
|
|
86
|
+
metadataProvider: () => metadata
|
|
87
|
+
});
|
|
88
|
+
if (writeResult.status === 'failed') {
|
|
89
|
+
return failed(intent, writeResult.error.code, writeResult.error.message, writeResult.taskId);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
status: writeResult.status,
|
|
93
|
+
changed: writeResult.changed,
|
|
94
|
+
intent: 'append',
|
|
95
|
+
taskId: writeResult.taskId,
|
|
96
|
+
artifact: intent.artifact ?? null,
|
|
97
|
+
operations: writeResult.operations,
|
|
98
|
+
error: null
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=activity-intent.js.map
|
|
@@ -12,7 +12,8 @@ const artifactFamilyCatalog = [
|
|
|
12
12
|
{ family: 'review-plan', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['技术方案审查', 'Plan Review'] },
|
|
13
13
|
{ family: 'code', sectionAliases: ['实现备注', 'Implementation Notes'], heading: '实现备注', labels: ['实现报告', 'Implementation Report'] },
|
|
14
14
|
{ family: 'review-code', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['代码审查', 'Code Review'] },
|
|
15
|
-
{ family: 'manual-validation', sectionAliases: ['实现备注', 'Implementation Notes'], heading: '实现备注', labels: ['人工验证', 'Manual Validation'] }
|
|
15
|
+
{ family: 'manual-validation', sectionAliases: ['实现备注', 'Implementation Notes'], heading: '实现备注', labels: ['人工验证', 'Manual Validation'] },
|
|
16
|
+
{ family: 'pr-review', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['PR 审查报告', 'PR Review Report'] }
|
|
16
17
|
];
|
|
17
18
|
const FAMILY_SET = new Set(artifactFamilyCatalog.map((item) => item.family));
|
|
18
19
|
const BLOCKING_DIAGNOSTICS = new Set([
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import { classifyAgent } from '../../agent-clients/tokens.js';
|
|
2
3
|
import { formatTable } from '../../table.js';
|
|
3
4
|
import { parseTaskScope } from '../command-options.js';
|
|
4
5
|
import { resolveTaskContext } from '../resolve-ref.js';
|
|
@@ -30,11 +31,11 @@ const TABLE_HEADERS = ['#', 'STEP', 'AGENT', 'STARTED', 'DONE', 'NOTE'];
|
|
|
30
31
|
// with ` [started]`; the matching done entry carries the identical base action
|
|
31
32
|
// without the suffix. Pairing therefore keys on the base action (including any
|
|
32
33
|
// `(Round N)`), so every round and every repeated execution pairs on its own.
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
|
|
34
|
+
// Known AI tokens, long-name mapping, and loose rendering classification live
|
|
35
|
+
// in lib/agent-clients/tokens.ts (single source of truth shared with the
|
|
36
|
+
// write-side internal commands). Any other executor token (a human name,
|
|
37
|
+
// possibly CJK, or an unknown value) is rendered as human with a visible
|
|
38
|
+
// `(unknown)` marker.
|
|
38
39
|
const REVIEW_STAGE_PREFIXES = [
|
|
39
40
|
{ prefix: 'Review Analysis', stage: 'analysis' },
|
|
40
41
|
{ prefix: 'Review Plan', stage: 'plan' },
|
|
@@ -83,12 +84,11 @@ function humanValidationCount(note) {
|
|
|
83
84
|
function isHumanCountField(field) {
|
|
84
85
|
return fieldNumber(field, 'manual-validation') !== undefined || fieldNumber(field, 'human-decision') !== undefined;
|
|
85
86
|
}
|
|
86
|
-
// A step is human-executed when its agent token is not a known AI token.
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
function isHumanAgent(agent) {
|
|
90
|
-
|
|
91
|
-
return token !== '' && !KNOWN_AI_AGENTS.has(token);
|
|
87
|
+
// A step is human-executed when its agent token is not a known AI token.
|
|
88
|
+
// Known long names (claude-code -> claude, gemini-cli -> gemini) classify as
|
|
89
|
+
// AI; empty or unknown tokens classify as non-AI (human).
|
|
90
|
+
export function isHumanAgent(agent) {
|
|
91
|
+
return classifyAgent(agent).status !== 'ai';
|
|
92
92
|
}
|
|
93
93
|
// Fold the two human counts into a review row's verdict NOTE: comma-joined, right
|
|
94
94
|
// after the blockers/major/minor list and before the ` → artifact` link, mirroring
|
|
@@ -148,8 +148,9 @@ function log(args = []) {
|
|
|
148
148
|
const note = stage
|
|
149
149
|
? foldHumanCounts(s.note, humanDecisionCounts.get(stage) ?? 0, humanValidationCount(s.note))
|
|
150
150
|
: s.note;
|
|
151
|
-
const
|
|
152
|
-
const
|
|
151
|
+
const { status, display } = classifyAgent(s.agent);
|
|
152
|
+
const human = status !== 'ai';
|
|
153
|
+
const agent = status === 'unknown' ? `${display} (unknown)` : display;
|
|
153
154
|
const started = s.started || (human ? '-' : '');
|
|
154
155
|
return [String(idx + 1), s.step, agent, started, s.done || (s.started ? '(in progress)' : ''), note];
|
|
155
156
|
});
|
|
@@ -158,5 +159,5 @@ function log(args = []) {
|
|
|
158
159
|
}
|
|
159
160
|
process.stdout.write(`Total: ${steps.length} steps\n`);
|
|
160
161
|
}
|
|
161
|
-
export { log
|
|
162
|
+
export { log };
|
|
162
163
|
//# sourceMappingURL=log.js.map
|
|
@@ -14,7 +14,9 @@ function prepareDelegation(input, options = {}) {
|
|
|
14
14
|
...input,
|
|
15
15
|
id: (options.id ?? randomUUID)(),
|
|
16
16
|
actualModel: null,
|
|
17
|
+
actualReasoningEffort: null,
|
|
17
18
|
modelFallbackReason: null,
|
|
19
|
+
reasoningEffortFallbackReason: null,
|
|
18
20
|
parentId: null,
|
|
19
21
|
childId: null,
|
|
20
22
|
spawnMode: null,
|
|
@@ -41,10 +43,27 @@ function activateDelegation(receipt, event, options = {}) {
|
|
|
41
43
|
}
|
|
42
44
|
if (event.spawnMode !== 'fresh')
|
|
43
45
|
return fail('DELEGATION_FORK_FORBIDDEN', `spawn mode '${event.spawnMode}' is not fresh`);
|
|
44
|
-
const actualModel = event.actualModel
|
|
45
|
-
if (actualModel
|
|
46
|
+
const actualModel = event.actualModel;
|
|
47
|
+
if (!actualModel || actualModel.trim() !== actualModel) {
|
|
48
|
+
return fail('DELEGATION_MODEL_IDENTITY_MISSING', 'native start event must provide a non-empty actual model identity');
|
|
49
|
+
}
|
|
50
|
+
if (actualModel !== receipt.requestedModel && (!event.modelFallbackReason || event.modelFallbackReason.trim() === '')) {
|
|
46
51
|
return fail('DELEGATION_MODEL_FALLBACK_UNRECORDED', 'actual model differs from requested model without a fallback reason');
|
|
47
52
|
}
|
|
53
|
+
const actualReasoningEffort = event.actualReasoningEffort;
|
|
54
|
+
if (!actualReasoningEffort || actualReasoningEffort.trim() !== actualReasoningEffort) {
|
|
55
|
+
return fail('DELEGATION_REASONING_EFFORT_MISSING', 'native start event must provide a non-empty actual reasoning effort');
|
|
56
|
+
}
|
|
57
|
+
if (actualReasoningEffort !== receipt.requestedReasoningEffort
|
|
58
|
+
&& (!event.reasoningEffortFallbackReason || event.reasoningEffortFallbackReason.trim() === '')) {
|
|
59
|
+
return fail('DELEGATION_REASONING_EFFORT_FALLBACK_UNRECORDED', 'actual reasoning effort differs from requested effort without a fallback reason');
|
|
60
|
+
}
|
|
61
|
+
if (actualModel === receipt.requestedModel && event.modelFallbackReason) {
|
|
62
|
+
return fail('DELEGATION_MODEL_FALLBACK_INVALID', 'model fallback reason is only valid when actual model differs');
|
|
63
|
+
}
|
|
64
|
+
if (actualReasoningEffort === receipt.requestedReasoningEffort && event.reasoningEffortFallbackReason) {
|
|
65
|
+
return fail('DELEGATION_REASONING_EFFORT_FALLBACK_INVALID', 'reasoning-effort fallback reason is only valid when actual effort differs');
|
|
66
|
+
}
|
|
48
67
|
return { ok: true, receipt: Object.freeze({
|
|
49
68
|
...receipt,
|
|
50
69
|
status: 'activated',
|
|
@@ -52,7 +71,9 @@ function activateDelegation(receipt, event, options = {}) {
|
|
|
52
71
|
childId: event.childId,
|
|
53
72
|
spawnMode: event.spawnMode,
|
|
54
73
|
actualModel,
|
|
74
|
+
actualReasoningEffort,
|
|
55
75
|
modelFallbackReason: event.modelFallbackReason ?? null,
|
|
76
|
+
reasoningEffortFallbackReason: event.reasoningEffortFallbackReason ?? null,
|
|
56
77
|
activatedAt: (options.now ?? (() => new Date().toISOString()))()
|
|
57
78
|
}) };
|
|
58
79
|
}
|