@fitlab-ai/agent-infra 0.9.1 → 0.9.2
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 +16 -4
- package/README.zh-CN.md +16 -4
- package/bin/cli.ts +12 -0
- package/dist/bin/cli.js +14 -0
- package/dist/bin/internal-cli.js +15 -0
- package/dist/lib/agent-client.js +163 -0
- package/dist/lib/agent-clients/adapter.js +294 -0
- package/dist/lib/agent-clients/adapters/claude-code.js +62 -0
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +210 -0
- package/dist/lib/agent-clients/adapters/codex.js +54 -0
- package/dist/lib/agent-clients/adapters/gemini-cli.js +64 -0
- package/dist/lib/agent-clients/adapters/index.js +20 -0
- package/dist/lib/agent-clients/adapters/opencode.js +64 -0
- package/dist/lib/agent-clients/config.js +177 -0
- package/dist/lib/agent-clients/custom-tuis.js +99 -0
- package/dist/lib/agent-clients/invocation.js +9 -0
- package/dist/lib/agent-clients/next-steps.js +38 -0
- package/dist/lib/agent-clients/project-assets.js +45 -0
- package/dist/lib/agent-clients/reconcile.js +235 -0
- package/dist/lib/agent-clients/registry.js +72 -0
- package/dist/lib/agent-clients/schema.js +57 -0
- package/dist/lib/agent-clients/types.js +29 -0
- package/dist/lib/builtin-tuis.js +9 -14
- package/dist/lib/defaults.json +85 -73
- package/dist/lib/git/review-snapshot.js +25 -10
- package/dist/lib/git/reviewed-commit-equivalence.js +110 -0
- package/dist/lib/init.js +47 -91
- package/dist/lib/internal/agent-client.js +117 -0
- package/dist/lib/internal/git-workflow.js +1 -1
- package/dist/lib/internal/release-workflow.js +71 -16
- package/dist/lib/internal/task-orchestration.js +151 -0
- package/dist/lib/internal/task-review.js +65 -0
- package/dist/lib/merge.js +2 -1
- package/dist/lib/platform/adapters.js +38 -1
- package/dist/lib/platform/change-request-git-evidence.js +113 -0
- package/dist/lib/platform/merged-pr-equivalence.js +41 -11
- package/dist/lib/platform/pr-checks.js +38 -10
- package/dist/lib/platform/pull-requests.js +110 -6
- package/dist/lib/platform/releases.js +1 -1
- package/dist/lib/platform/verification-required.js +8 -10
- package/dist/lib/prompt.js +15 -3
- package/dist/lib/release/channels.js +4 -1
- package/dist/lib/release/workflow.js +4 -2
- package/dist/lib/remove-dir.js +25 -0
- package/dist/lib/run/tui.js +8 -2
- package/dist/lib/sandbox/agent-client-reconciler.js +234 -0
- package/dist/lib/sandbox/clipboard/linux.js +2 -1
- package/dist/lib/sandbox/commands/create.js +76 -180
- package/dist/lib/sandbox/commands/enter.js +17 -1
- package/dist/lib/sandbox/commands/prune.js +2 -2
- package/dist/lib/sandbox/commands/rm.js +3 -2
- package/dist/lib/sandbox/config.js +21 -4
- package/dist/lib/sandbox/constants.js +3 -0
- package/dist/lib/sandbox/dockerfile.js +2 -1
- package/dist/lib/sandbox/managed-fs.js +10 -5
- package/dist/lib/sandbox/recovery.js +52 -36
- package/dist/lib/sandbox/shell.js +1 -1
- package/dist/lib/sandbox/tool-types.js +8 -0
- package/dist/lib/sandbox/tools.js +2 -126
- package/dist/lib/task/artifact-lifecycle.js +1 -49
- package/dist/lib/task/commands/decisions.js +50 -20
- package/dist/lib/task/delegation-receipts.js +107 -0
- package/dist/lib/task/events.js +100 -1
- package/dist/lib/task/orchestration.js +420 -0
- package/dist/lib/task/review-artifacts.js +143 -59
- package/dist/lib/task/review-finalization.js +166 -0
- package/dist/lib/task/review-fingerprint.js +4 -0
- package/dist/lib/task/verification-checks.js +2 -1
- package/dist/lib/task/verification-engine.js +156 -28
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/task/verification.js +3 -1
- package/dist/lib/task/workspace-snapshot.js +34 -0
- package/dist/lib/update.js +42 -161
- package/lib/agent-client.ts +214 -0
- package/lib/agent-clients/adapter.ts +461 -0
- package/lib/agent-clients/adapters/claude-code.ts +70 -0
- package/lib/agent-clients/adapters/codex-sandbox.ts +245 -0
- package/lib/agent-clients/adapters/codex.ts +58 -0
- package/lib/agent-clients/adapters/gemini-cli.ts +65 -0
- package/lib/agent-clients/adapters/index.ts +27 -0
- package/lib/agent-clients/adapters/opencode.ts +66 -0
- package/lib/agent-clients/config.ts +278 -0
- package/lib/agent-clients/custom-tuis.ts +149 -0
- package/lib/agent-clients/invocation.ts +19 -0
- package/lib/agent-clients/next-steps.ts +72 -0
- package/lib/agent-clients/project-assets.ts +96 -0
- package/lib/agent-clients/reconcile.ts +324 -0
- package/lib/agent-clients/registry.ts +144 -0
- package/lib/agent-clients/schema.ts +62 -0
- package/lib/agent-clients/types.ts +78 -0
- package/lib/benchmark/schemas/v1.0.0/case-manifest.schema.json +120 -0
- package/lib/benchmark/schemas/v1.0.0/common.schema.json +109 -0
- package/lib/benchmark/schemas/v1.0.0/grader-result.schema.json +160 -0
- package/lib/benchmark/schemas/v1.0.0/run-manifest.schema.json +122 -0
- package/lib/benchmark/schemas/v1.0.0/subject.schema.json +227 -0
- package/lib/builtin-tuis.ts +16 -15
- package/lib/defaults.json +24 -12
- package/lib/git/review-snapshot.ts +39 -9
- package/lib/git/reviewed-commit-equivalence.ts +135 -0
- package/lib/init.ts +53 -121
- package/lib/internal/agent-client.ts +131 -0
- package/lib/internal/git-workflow.ts +1 -1
- package/lib/internal/release-workflow.ts +68 -16
- package/lib/internal/task-orchestration.ts +132 -0
- package/lib/internal/task-review.ts +65 -0
- package/lib/merge.ts +2 -1
- package/lib/platform/adapters.ts +142 -3
- package/lib/platform/change-request-git-evidence.ts +159 -0
- package/lib/platform/merged-pr-equivalence.ts +51 -14
- package/lib/platform/pr-checks.ts +50 -22
- package/lib/platform/pull-requests.ts +134 -25
- package/lib/platform/releases.ts +1 -1
- package/lib/platform/verification-required.ts +12 -10
- package/lib/prompt.ts +16 -3
- package/lib/release/channels.ts +4 -1
- package/lib/release/workflow.ts +4 -3
- package/lib/remove-dir.ts +28 -0
- package/lib/run/tui.ts +9 -1
- package/lib/sandbox/agent-client-reconciler.ts +378 -0
- package/lib/sandbox/clipboard/linux.ts +2 -1
- package/lib/sandbox/commands/create.ts +111 -192
- package/lib/sandbox/commands/enter.ts +23 -1
- package/lib/sandbox/commands/prune.ts +2 -2
- package/lib/sandbox/commands/rm.ts +3 -2
- package/lib/sandbox/config.ts +31 -4
- package/lib/sandbox/constants.ts +6 -0
- package/lib/sandbox/dockerfile.ts +2 -1
- package/lib/sandbox/managed-fs.ts +18 -5
- package/lib/sandbox/recovery.ts +98 -67
- package/lib/sandbox/shell.ts +1 -1
- package/lib/sandbox/tool-types.ts +143 -0
- package/lib/sandbox/tools.ts +5 -157
- package/lib/task/artifact-lifecycle.ts +1 -38
- package/lib/task/commands/decisions.ts +53 -20
- package/lib/task/delegation-receipts.ts +170 -0
- package/lib/task/events.ts +110 -2
- package/lib/task/orchestration.ts +543 -0
- package/lib/task/review-artifacts.ts +201 -69
- package/lib/task/review-finalization.ts +275 -0
- package/lib/task/review-fingerprint.ts +5 -0
- package/lib/task/verification-checks.ts +2 -1
- package/lib/task/verification-engine.ts +177 -28
- package/lib/task/verification-review.ts +1 -0
- package/lib/task/verification.ts +5 -2
- package/lib/task/workspace-snapshot.ts +36 -0
- package/lib/update.ts +48 -184
- package/package.json +2 -2
- package/templates/.agents/README.en.md +21 -20
- package/templates/.agents/README.zh-CN.md +21 -20
- package/templates/.agents/hooks/lifecycle-delegation.js +64 -0
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/commit-and-pr.en.md +1 -0
- package/templates/.agents/rules/commit-and-pr.zh-CN.md +1 -0
- package/templates/.agents/rules/human-decision-context.en.md +14 -12
- package/templates/.agents/rules/human-decision-context.zh-CN.md +14 -12
- package/templates/.agents/rules/lifecycle-orchestration.en.md +21 -0
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +21 -0
- package/templates/.agents/rules/next-step-output.en.md +16 -0
- package/templates/.agents/rules/next-step-output.zh-CN.md +16 -0
- package/templates/.agents/rules/no-mid-flow-questions.en.md +2 -0
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +2 -0
- package/templates/.agents/rules/release-commands.github.en.md +11 -5
- package/templates/.agents/rules/release-commands.github.zh-CN.md +11 -5
- package/templates/.agents/rules/review-handshake.en.md +4 -4
- package/templates/.agents/rules/review-handshake.zh-CN.md +4 -4
- package/templates/.agents/rules/review-method.en.md +113 -0
- package/templates/.agents/rules/review-method.zh-CN.md +98 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/block-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/cancel-task/SKILL.en.md +4 -4
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/check-task/SKILL.en.md +16 -16
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +16 -16
- package/templates/.agents/skills/close-codescan/SKILL.en.md +4 -4
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +4 -4
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/code-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/reference/fix-mode.en.md +14 -16
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +14 -16
- package/templates/.agents/skills/code-task/reference/output-template.en.md +3 -3
- package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/SKILL.en.md +11 -1
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +11 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +24 -28
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +24 -28
- package/templates/.agents/skills/complete-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.en.md +10 -10
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +10 -10
- package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +3 -3
- package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +3 -3
- package/templates/.agents/skills/create-task/SKILL.en.md +11 -11
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +11 -11
- package/templates/.agents/skills/import-codescan/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/import-issue/SKILL.en.md +5 -5
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/init-labels/SKILL.en.md +4 -4
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/init-milestones/SKILL.en.md +4 -4
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/plan-task/SKILL.en.md +5 -5
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -5
- 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 +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +13 -2
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -3
- package/templates/.agents/skills/review-analysis/config/verify.en.json +6 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +6 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +13 -15
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +13 -15
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +51 -5
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +52 -6
- package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +25 -22
- package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +25 -22
- package/templates/.agents/skills/review-code/SKILL.en.md +28 -8
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +28 -8
- package/templates/.agents/skills/review-code/config/verify.en.json +7 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +7 -0
- package/templates/.agents/skills/review-code/reference/concurrency-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/concurrency-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-code/reference/cross-platform-risks.en.md +27 -0
- package/templates/.agents/skills/review-code/reference/cross-platform-risks.zh-CN.md +27 -0
- package/templates/.agents/skills/review-code/reference/documentation-antipatterns.en.md +13 -0
- package/templates/.agents/skills/review-code/reference/documentation-antipatterns.zh-CN.md +13 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +22 -24
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +22 -24
- package/templates/.agents/skills/review-code/reference/report-template.en.md +54 -7
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +54 -7
- package/templates/.agents/skills/review-code/reference/review-criteria.en.md +29 -24
- package/templates/.agents/skills/review-code/reference/review-criteria.zh-CN.md +29 -24
- package/templates/.agents/skills/review-code/reference/security-risks.en.md +25 -0
- package/templates/.agents/skills/review-code/reference/security-risks.zh-CN.md +25 -0
- package/templates/.agents/skills/review-plan/SKILL.en.md +13 -2
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -3
- package/templates/.agents/skills/review-plan/config/verify.en.json +6 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +6 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +13 -15
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +13 -15
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +61 -5
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +61 -5
- package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +21 -24
- package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +21 -24
- package/templates/.agents/skills/run-task/SKILL.en.md +22 -0
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +22 -0
- package/templates/.agents/skills/run-task/config/verify.en.json +9 -0
- package/templates/.agents/skills/run-task/config/verify.zh-CN.json +9 -0
- package/templates/.agents/skills/test/SKILL.en.md +4 -4
- package/templates/.agents/skills/test/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/test-integration/SKILL.en.md +4 -4
- package/templates/.agents/skills/test-integration/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +5 -5
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +647 -203
- package/templates/.agents/skills/upgrade-dependency/SKILL.en.md +4 -4
- package/templates/.agents/skills/upgrade-dependency/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/watch-pr/SKILL.en.md +8 -8
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +8 -8
- package/templates/.claude/agents/agent-infra-lifecycle-executor.en.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-executor.zh-CN.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.en.md +6 -0
- package/templates/.claude/agents/agent-infra-lifecycle-reviewer.zh-CN.md +6 -0
- package/templates/.claude/commands/run-task.en.md +8 -0
- package/templates/.claude/commands/run-task.zh-CN.md +8 -0
- package/templates/.claude/settings.json +24 -0
- package/templates/.codex/agents/agent-infra-lifecycle-executor.en.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-executor.zh-CN.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.en.toml +3 -0
- package/templates/.codex/agents/agent-infra-lifecycle-reviewer.zh-CN.toml +3 -0
- package/templates/.gemini/commands/_project_/run-task.en.toml +8 -0
- package/templates/.gemini/commands/_project_/run-task.zh-CN.toml +8 -0
- package/templates/.opencode/commands/run-task.en.md +11 -0
- package/templates/.opencode/commands/run-task.zh-CN.md +11 -0
|
@@ -4,13 +4,16 @@ import path from "node:path";
|
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { extractReviewBaseline, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from "./verification-review.js";
|
|
7
|
+
import { extractReviewBaseline, extractReviewDiffBase, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from "./verification-review.js";
|
|
8
8
|
import { check as checkPlatformSync } from "../platform/verification-sync.js";
|
|
9
9
|
import { check as checkRequiredChecks } from "../platform/verification-required.js";
|
|
10
10
|
import { inspectPlatformPullRequest } from "../platform/pull-requests.js";
|
|
11
|
+
import { resolveMaterializedReviewedHeadRelation } from "../platform/change-request-git-evidence.js";
|
|
11
12
|
import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.js";
|
|
13
|
+
import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.js";
|
|
12
14
|
import { parseTypedTaskFrontmatter } from "./frontmatter.js";
|
|
13
|
-
import { parseLedger } from "./ledger.js";
|
|
15
|
+
import { parseLedger, summarizeLedgerStage, validateLedgerRows } from "./ledger.js";
|
|
16
|
+
import { equalCounts, parseReviewSummary } from "./review-artifacts.js";
|
|
14
17
|
import { loadVerificationConfig } from "./verification-config.js";
|
|
15
18
|
import { snapshotReview } from "../git/review-snapshot.js";
|
|
16
19
|
const TASK_ENUMS = {
|
|
@@ -93,10 +96,14 @@ function runCheck(type, context, shared) {
|
|
|
93
96
|
return checkCompletionChecklist(context);
|
|
94
97
|
case "review-ledger":
|
|
95
98
|
return checkReviewLedger(context);
|
|
99
|
+
case "review-summary":
|
|
100
|
+
return checkReviewSummary(context);
|
|
96
101
|
case "review-fact":
|
|
97
102
|
return checkReviewFact(context);
|
|
98
103
|
case "post-review-commit":
|
|
99
104
|
return checkPostReviewCommit(context);
|
|
105
|
+
case "orchestration-state":
|
|
106
|
+
return checkOrchestrationState(context);
|
|
100
107
|
default: {
|
|
101
108
|
const adapter = PLATFORM_ADAPTERS[type];
|
|
102
109
|
if (!adapter) {
|
|
@@ -109,6 +116,34 @@ function runCheck(type, context, shared) {
|
|
|
109
116
|
}
|
|
110
117
|
}
|
|
111
118
|
}
|
|
119
|
+
function checkOrchestrationState({ taskDir }) {
|
|
120
|
+
const file = path.join(taskDir, 'orchestration.json');
|
|
121
|
+
const stat = safeStat(file);
|
|
122
|
+
if (!stat?.isFile())
|
|
123
|
+
return failResult('orchestration-state', 'orchestration.json is missing');
|
|
124
|
+
let run;
|
|
125
|
+
try {
|
|
126
|
+
run = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return failResult('orchestration-state', `Invalid orchestration.json: ${String(error)}`);
|
|
130
|
+
}
|
|
131
|
+
if (run.schemaVersion !== 1 || !['paused', 'completed'].includes(run.status)) {
|
|
132
|
+
return failResult('orchestration-state', `Expected paused or completed run, received '${run.status}'`);
|
|
133
|
+
}
|
|
134
|
+
if (run.status === 'paused' && (!run.pause?.code || !run.pause?.message)) {
|
|
135
|
+
return failResult('orchestration-state', 'Paused run requires a stable pause code and message');
|
|
136
|
+
}
|
|
137
|
+
if (run.status === 'completed') {
|
|
138
|
+
if (run.pendingDelegation !== null || !run.commitAuthorization?.consumedAt) {
|
|
139
|
+
return failResult('orchestration-state', 'Completed run must consume commit authorization and clear pending delegation');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (run.pendingDelegation?.status === 'sealed') {
|
|
143
|
+
return failResult('orchestration-state', 'Paused run has a sealed delegation that could still advance');
|
|
144
|
+
}
|
|
145
|
+
return passResult('orchestration-state', `Orchestration run is safely ${run.status}`);
|
|
146
|
+
}
|
|
112
147
|
// === Check Functions ===
|
|
113
148
|
function checkTaskMeta({ taskDir, config }) {
|
|
114
149
|
const task = loadTask(taskDir);
|
|
@@ -239,6 +274,40 @@ function checkArtifact({ taskDir, config, artifactFile }) {
|
|
|
239
274
|
}
|
|
240
275
|
return passResult("artifact", `${path.basename(artifactPath)} passed (${requiredSections.length} sections)`);
|
|
241
276
|
}
|
|
277
|
+
function checkReviewSummary({ taskDir, config, artifactFile }) {
|
|
278
|
+
const stage = String(config.stage || "");
|
|
279
|
+
if (!["analysis", "plan", "code"].includes(stage)) {
|
|
280
|
+
return failResult("review-summary", `Invalid review stage '${stage}'`);
|
|
281
|
+
}
|
|
282
|
+
const resolvedArtifact = resolveArtifactPath(taskDir, "", artifactFile);
|
|
283
|
+
if (!resolvedArtifact.ok || !safeStat(resolvedArtifact.path)?.isFile()) {
|
|
284
|
+
return failResult("review-summary", resolvedArtifact.message || "Review artifact is missing");
|
|
285
|
+
}
|
|
286
|
+
const parsed = parseReviewSummary(fs.readFileSync(resolvedArtifact.path, "utf8"));
|
|
287
|
+
if (!parsed.ok)
|
|
288
|
+
return failResult("review-summary", `${parsed.code}: ${parsed.message}`);
|
|
289
|
+
if (!parsed.summary.counts) {
|
|
290
|
+
return failResult("review-summary", "Review summary finding counts are not finalized");
|
|
291
|
+
}
|
|
292
|
+
const task = loadTask(taskDir);
|
|
293
|
+
if (!task.ok)
|
|
294
|
+
return failResult("review-summary", task.message);
|
|
295
|
+
let rows;
|
|
296
|
+
try {
|
|
297
|
+
rows = parseLedger(task.content);
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
return failResult("review-summary", `Invalid disagreement ledger: ${String(error)}`);
|
|
301
|
+
}
|
|
302
|
+
const invalid = validateLedgerRows(rows);
|
|
303
|
+
if (invalid)
|
|
304
|
+
return failResult("review-summary", `${invalid.code}: ${invalid.message}`);
|
|
305
|
+
const expected = summarizeLedgerStage(rows, stage).unresolvedFindingCounts;
|
|
306
|
+
if (!equalCounts(parsed.summary.counts, expected)) {
|
|
307
|
+
return failResult("review-summary", `Review summary counts ${JSON.stringify(parsed.summary.counts)} do not match ledger ${JSON.stringify(expected)}`);
|
|
308
|
+
}
|
|
309
|
+
return passResult("review-summary", `${path.basename(resolvedArtifact.path)} finding counts match the ${stage} ledger`);
|
|
310
|
+
}
|
|
242
311
|
function checkImplementationInput({ taskDir, artifactFile }) {
|
|
243
312
|
const task = loadTask(taskDir);
|
|
244
313
|
if (!task.ok)
|
|
@@ -568,8 +637,42 @@ function checkPostReviewCommit({ taskDir, config }) {
|
|
|
568
637
|
return blockedResult("post-review-commit", "git unavailable or task directory is not inside a git repository");
|
|
569
638
|
}
|
|
570
639
|
const task = loadTask(taskDir);
|
|
571
|
-
|
|
640
|
+
if (!task.ok)
|
|
641
|
+
return failResult("post-review-commit", task.message);
|
|
572
642
|
const lastReviewedCommit = task.ok ? (task.metadata.last_reviewed_commit || "").trim() : "";
|
|
643
|
+
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
|
|
644
|
+
const hasPullRequest = Number(task.metadata.pr_number) > 0;
|
|
645
|
+
let inspected = null;
|
|
646
|
+
if (hasPullRequest) {
|
|
647
|
+
inspected = inspectPlatformPullRequest(task.metadata.id, { cwd: gitRoot });
|
|
648
|
+
if (!inspected.pullRequest) {
|
|
649
|
+
const message = inspected.error?.message || "PR merge snapshot is unavailable";
|
|
650
|
+
const code = inspected.error?.code || "PR_INSPECTION_INVALID";
|
|
651
|
+
return inspected.status === "blocked"
|
|
652
|
+
? blockedResult("post-review-commit", message, code)
|
|
653
|
+
: failResult("post-review-commit", message, code);
|
|
654
|
+
}
|
|
655
|
+
if (inspected.pullRequest.state === "closed" &&
|
|
656
|
+
inspected.pullRequest.mergedAt &&
|
|
657
|
+
inspected.pullRequest.mergeCommitSha) {
|
|
658
|
+
const relation = resolveMaterializedReviewedHeadRelation({
|
|
659
|
+
cwd: gitRoot,
|
|
660
|
+
platformType: inspected.platform.type,
|
|
661
|
+
lastReviewedCommit,
|
|
662
|
+
pullRequest: inspected.pullRequest
|
|
663
|
+
});
|
|
664
|
+
if (relation.status === "merged-equivalent") {
|
|
665
|
+
return passResult("post-review-commit", `Reviewed PR head is content-equivalent to squash merge ${relation.mergeCommit.slice(0, 8)} on target ${relation.comparisonHead.slice(0, 8)}`);
|
|
666
|
+
}
|
|
667
|
+
if (relation.status === "blocked") {
|
|
668
|
+
return blockedResult("post-review-commit", relation.message, relation.code);
|
|
669
|
+
}
|
|
670
|
+
if (relation.status === "strict") {
|
|
671
|
+
return failResult("post-review-commit", "Merged PR evidence did not establish squash merge equivalence", "PR_MERGE_IDENTITY_INVALID");
|
|
672
|
+
}
|
|
673
|
+
return failResult("post-review-commit", relation.message, relation.code);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
573
676
|
const baselineSource = resolvePostReviewBaseline({
|
|
574
677
|
gitRoot,
|
|
575
678
|
lastReviewedCommit,
|
|
@@ -579,7 +682,6 @@ function checkPostReviewCommit({ taskDir, config }) {
|
|
|
579
682
|
return baselineSource.result;
|
|
580
683
|
}
|
|
581
684
|
const sha = baselineSource.sha;
|
|
582
|
-
const globs = resolvePostReviewGlobs(config, loadPostReviewConfig(repoRoot));
|
|
583
685
|
let commits;
|
|
584
686
|
try {
|
|
585
687
|
const out = execFileSync("git", ["-C", gitRoot, "rev-list", `${sha}..HEAD`, "--", ...globs], { encoding: "utf8" });
|
|
@@ -591,45 +693,62 @@ function checkPostReviewCommit({ taskDir, config }) {
|
|
|
591
693
|
if (commits.length === 0) {
|
|
592
694
|
return passResult("post-review-commit", `No post-review commits to code/rule paths since ${sha.slice(0, 8)}`);
|
|
593
695
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
}
|
|
696
|
+
let localHead = "";
|
|
697
|
+
try {
|
|
698
|
+
localHead = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
699
|
+
}
|
|
700
|
+
catch {
|
|
701
|
+
return blockedResult("post-review-commit", "Unable to resolve the local HEAD");
|
|
702
|
+
}
|
|
703
|
+
if (hasPullRequest) {
|
|
704
|
+
if (inspected?.pullRequest) {
|
|
604
705
|
const relation = resolveReviewedHeadRelation({
|
|
605
706
|
gitRoot,
|
|
606
|
-
localHead,
|
|
707
|
+
comparisonHead: localHead,
|
|
607
708
|
lastReviewedCommit: sha,
|
|
608
|
-
pullRequest: inspected.pullRequest
|
|
609
|
-
pathspecs: globs
|
|
709
|
+
pullRequest: inspected.pullRequest
|
|
610
710
|
});
|
|
611
711
|
if (relation.status === "merged-equivalent") {
|
|
612
712
|
return passResult("post-review-commit", `Reviewed PR head is content-equivalent to squash merge ${relation.mergeCommit.slice(0, 8)}`);
|
|
613
713
|
}
|
|
614
714
|
if (relation.status === "blocked") {
|
|
615
|
-
return blockedResult("post-review-commit", relation.message);
|
|
715
|
+
return blockedResult("post-review-commit", relation.message, relation.code);
|
|
616
716
|
}
|
|
617
717
|
}
|
|
618
|
-
|
|
619
|
-
|
|
718
|
+
}
|
|
719
|
+
else if (commits.length === 1) {
|
|
720
|
+
const relation = resolveLocalReviewedCommitRelation({
|
|
721
|
+
gitRoot,
|
|
722
|
+
localHead,
|
|
723
|
+
lastReviewedCommit: sha,
|
|
724
|
+
rewrittenCommit: commits[0],
|
|
725
|
+
pathspecs: globs
|
|
726
|
+
});
|
|
727
|
+
if (relation.status === "local-equivalent") {
|
|
728
|
+
return passResult("post-review-commit", `Reviewed commit is content-equivalent to local rewrite ${relation.rewrittenCommit.slice(0, 8)}`);
|
|
729
|
+
}
|
|
730
|
+
if (relation.status === "blocked") {
|
|
731
|
+
return blockedResult("post-review-commit", relation.message);
|
|
620
732
|
}
|
|
621
733
|
}
|
|
622
|
-
|
|
734
|
+
const exemption = resolvePostReviewExemption(task.content);
|
|
735
|
+
if (!exemption.ok)
|
|
736
|
+
return failResult("post-review-commit", exemption.message);
|
|
737
|
+
if (exemption.exempt) {
|
|
738
|
+
return passResult("post-review-commit", `${commits.length} post-review commit(s) covered by a human-decided exemption`);
|
|
739
|
+
}
|
|
740
|
+
return failResult("post-review-commit", `${commits.length} commit(s) to code/rule paths after reviewed commit ${sha.slice(0, 8)}; re-run review-code or record a human-decided exemption`);
|
|
741
|
+
}
|
|
742
|
+
function resolvePostReviewExemption(content) {
|
|
623
743
|
try {
|
|
624
|
-
|
|
744
|
+
return {
|
|
745
|
+
ok: true,
|
|
746
|
+
exempt: parseLedger(content).some((row) => row.stage === POST_REVIEW_COMMIT_STAGE && row.status === "human-decided")
|
|
747
|
+
};
|
|
625
748
|
}
|
|
626
749
|
catch {
|
|
627
|
-
return
|
|
750
|
+
return { ok: false, message: "Invalid disagreement ledger" };
|
|
628
751
|
}
|
|
629
|
-
if (exempt) {
|
|
630
|
-
return passResult("post-review-commit", `${commits.length} post-review commit(s) covered by a human-decided exemption`);
|
|
631
|
-
}
|
|
632
|
-
return failResult("post-review-commit", `${commits.length} commit(s) to code/rule paths after reviewed commit ${sha.slice(0, 8)}; re-run review-code or record a human-decided exemption`);
|
|
633
752
|
}
|
|
634
753
|
function checkReviewFact({ taskDir, artifactFile }) {
|
|
635
754
|
const resolvedArtifact = resolveArtifactPath(taskDir, "review-code.md|review-code-r{N}.md", artifactFile);
|
|
@@ -643,6 +762,7 @@ function checkReviewFact({ taskDir, artifactFile }) {
|
|
|
643
762
|
const content = fs.readFileSync(resolvedArtifact.path, "utf8");
|
|
644
763
|
const verdict = parseReviewVerdict(content);
|
|
645
764
|
const reviewBaseline = extractReviewBaseline(content);
|
|
765
|
+
const reviewDiffBase = extractReviewDiffBase(content);
|
|
646
766
|
const reviewedFingerprint = extractReviewDiffFingerprint(content);
|
|
647
767
|
const reviewedTree = extractReviewedSnapshotTree(content);
|
|
648
768
|
if (!["通过", "需要修改", "拒绝", "Approved", "Changes Requested", "Rejected"].includes(verdict)) {
|
|
@@ -651,10 +771,12 @@ function checkReviewFact({ taskDir, artifactFile }) {
|
|
|
651
771
|
let gitRoot;
|
|
652
772
|
let head;
|
|
653
773
|
let baseline;
|
|
774
|
+
let diffBase;
|
|
654
775
|
try {
|
|
655
776
|
gitRoot = execFileSync("git", ["-C", taskDir, "rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim();
|
|
656
777
|
head = execFileSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" }).trim();
|
|
657
778
|
baseline = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
|
|
779
|
+
diffBase = execFileSync("git", ["-C", gitRoot, "rev-parse", `${reviewDiffBase || reviewBaseline}^{commit}`], { encoding: "utf8" }).trim();
|
|
658
780
|
}
|
|
659
781
|
catch {
|
|
660
782
|
return blockedResult("review-fact", `Unable to resolve review baseline '${reviewBaseline}' in the task repository; re-run review-code`);
|
|
@@ -664,7 +786,13 @@ function checkReviewFact({ taskDir, artifactFile }) {
|
|
|
664
786
|
}
|
|
665
787
|
let actualSnapshot;
|
|
666
788
|
try {
|
|
667
|
-
actualSnapshot = snapshotReview({
|
|
789
|
+
actualSnapshot = snapshotReview({
|
|
790
|
+
cwd: gitRoot,
|
|
791
|
+
mode: "worktree",
|
|
792
|
+
baseline,
|
|
793
|
+
diffBase,
|
|
794
|
+
globs: resolvePostReviewGlobs({}, loadPostReviewConfig(repoRoot))
|
|
795
|
+
});
|
|
668
796
|
}
|
|
669
797
|
catch {
|
|
670
798
|
return blockedResult("review-fact", `Unable to recompute reviewed diff fingerprint from baseline ${baseline.slice(0, 8)}; re-run review-code`);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { extractReviewBaseline, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from './review-fingerprint.js';
|
|
1
|
+
export { extractReviewBaseline, extractReviewDiffBase, extractReviewDiffFingerprint, extractReviewedSnapshotTree, findAuthoritativeReviewCodeArtifact, loadPostReviewConfig, parseReviewVerdict, resolvePostReviewGlobs } from './review-fingerprint.js';
|
|
2
2
|
export { parseLedger, summarizeLedgerStage, validateLedgerRows } from './ledger.js';
|
|
3
3
|
//# sourceMappingURL=verification-review.js.map
|
|
@@ -26,7 +26,9 @@ const VERIFICATION_CATALOG = {
|
|
|
26
26
|
'import-codescan.completed': gate('import-codescan', 'active'),
|
|
27
27
|
'import-dependabot.completed': gate('import-dependabot', 'active'),
|
|
28
28
|
'import-issue.completed': gate('import-issue', 'active'),
|
|
29
|
-
'watch-pr.completed': gate('watch-pr', 'active')
|
|
29
|
+
'watch-pr.completed': gate('watch-pr', 'active'),
|
|
30
|
+
'run-task.paused': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state'] },
|
|
31
|
+
'run-task.completed': { skill: 'run-task', expectedState: 'active', mode: 'checks', checks: ['orchestration-state'] }
|
|
30
32
|
};
|
|
31
33
|
function failure(request, code, message, extra = {}) {
|
|
32
34
|
return {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
function git(repoRoot, indexFile, args) {
|
|
6
|
+
const env = indexFile ? { ...process.env, GIT_INDEX_FILE: indexFile } : process.env;
|
|
7
|
+
const result = spawnSync('git', args, { cwd: repoRoot, env, encoding: 'utf8' });
|
|
8
|
+
if (result.status !== 0) {
|
|
9
|
+
throw new Error(String(result.stderr || result.stdout || `git ${args[0]} failed`).trim());
|
|
10
|
+
}
|
|
11
|
+
return result.stdout;
|
|
12
|
+
}
|
|
13
|
+
function captureWorkspaceSnapshot(repoRoot) {
|
|
14
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-infra-orchestration-index-'));
|
|
15
|
+
const indexFile = path.join(tempDir, 'index');
|
|
16
|
+
try {
|
|
17
|
+
git(repoRoot, indexFile, ['read-tree', 'HEAD']);
|
|
18
|
+
git(repoRoot, indexFile, ['add', '-A', '--', ':/']);
|
|
19
|
+
const workspace = path.join(repoRoot, '.agents', 'workspace', 'active');
|
|
20
|
+
if (fs.existsSync(workspace)) {
|
|
21
|
+
git(repoRoot, indexFile, ['add', '-f', '--', '.agents/workspace/active']);
|
|
22
|
+
}
|
|
23
|
+
return git(repoRoot, indexFile, ['write-tree']).trim();
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function diffWorkspaceSnapshots(repoRoot, before, after) {
|
|
30
|
+
const output = git(repoRoot, null, ['diff', '--name-only', '-z', before, after]);
|
|
31
|
+
return output.split('\0').filter(Boolean);
|
|
32
|
+
}
|
|
33
|
+
export { captureWorkspaceSnapshot, diffWorkspaceSnapshots };
|
|
34
|
+
//# sourceMappingURL=workspace-snapshot.js.map
|
package/dist/lib/update.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { normalizeAgentClients } from './agent-clients/config.js';
|
|
4
|
+
import { applyAgentClientReconciliation, planAgentClientReconciliation } from './agent-clients/reconcile.js';
|
|
3
5
|
import { info, ok, err } from './log.js';
|
|
4
6
|
import { resolveTemplateDir } from './paths.js';
|
|
5
|
-
import { renderFile, copySkillDir
|
|
6
|
-
import { isPathOwnedByDisabledTUI, resolveEnabledTUIs } from './builtin-tuis.js';
|
|
7
|
+
import { renderFile, copySkillDir } from './render.js';
|
|
7
8
|
const defaults = JSON.parse(fs.readFileSync(new URL('./defaults.json', import.meta.url), 'utf8'));
|
|
8
9
|
const CONFIG_DIR = '.agents';
|
|
9
10
|
const CONFIG_PATH = path.join(CONFIG_DIR, '.airc.json');
|
|
10
|
-
const AGENT_INFRA_SANDBOX_TOOL = 'agent-infra';
|
|
11
|
-
const LEGACY_DEFAULT_SANDBOX_TOOLS = ['claude-code', 'codex', 'gemini-cli', 'opencode'];
|
|
12
|
-
const DEFAULT_SANDBOX_TOOLS = [AGENT_INFRA_SANDBOX_TOOL, ...LEGACY_DEFAULT_SANDBOX_TOOLS];
|
|
13
11
|
// One-time migration of the legacy project-level PR switch to the three-state
|
|
14
12
|
// `prFlow` preference. `true` (the old default / "PR flow on") maps to the
|
|
15
13
|
// strong constraint `required`; `false` maps to `disabled`. A missing or
|
|
@@ -28,80 +26,6 @@ function migratePrFlow(config) {
|
|
|
28
26
|
}
|
|
29
27
|
return null;
|
|
30
28
|
}
|
|
31
|
-
function isLegacyDefaultSandboxTools(value) {
|
|
32
|
-
if (!Array.isArray(value) || value.length !== LEGACY_DEFAULT_SANDBOX_TOOLS.length) {
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
const tools = new Set(value);
|
|
36
|
-
return LEGACY_DEFAULT_SANDBOX_TOOLS.every((tool) => tools.has(tool));
|
|
37
|
-
}
|
|
38
|
-
function migrateSandboxTools(config) {
|
|
39
|
-
const tools = config.sandbox?.tools;
|
|
40
|
-
if (!isLegacyDefaultSandboxTools(tools)) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
config.sandbox = {
|
|
44
|
-
...config.sandbox,
|
|
45
|
-
tools: [...DEFAULT_SANDBOX_TOOLS]
|
|
46
|
-
};
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
function isPathOwnedByOtherPlatform(relativePath, platformType) {
|
|
50
|
-
const top = String(relativePath || '').replace(/\\/g, '/').replace(/^\.\//, '').split('/')[0] ?? '';
|
|
51
|
-
if (!top.startsWith('.'))
|
|
52
|
-
return false;
|
|
53
|
-
const candidate = top.slice(1);
|
|
54
|
-
if (!KNOWN_PLATFORMS.has(candidate))
|
|
55
|
-
return false;
|
|
56
|
-
return candidate !== platformType;
|
|
57
|
-
}
|
|
58
|
-
function syncFileRegistry(config, platformType, enabledTUIs) {
|
|
59
|
-
config.files ||= {};
|
|
60
|
-
const before = JSON.stringify({
|
|
61
|
-
files: {
|
|
62
|
-
managed: config.files.managed || [],
|
|
63
|
-
merged: config.files.merged || [],
|
|
64
|
-
ejected: config.files.ejected || []
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
config.files.managed = config.files.managed || [];
|
|
68
|
-
config.files.merged = config.files.merged || [];
|
|
69
|
-
config.files.ejected = config.files.ejected || [];
|
|
70
|
-
const allExisting = [
|
|
71
|
-
...config.files.managed,
|
|
72
|
-
...config.files.merged,
|
|
73
|
-
...config.files.ejected
|
|
74
|
-
];
|
|
75
|
-
const added = { managed: [], merged: [] };
|
|
76
|
-
for (const entry of defaults.files.managed) {
|
|
77
|
-
if (isPathOwnedByOtherPlatform(entry, platformType))
|
|
78
|
-
continue;
|
|
79
|
-
if (isPathOwnedByDisabledTUI(entry, enabledTUIs))
|
|
80
|
-
continue;
|
|
81
|
-
if (!allExisting.includes(entry)) {
|
|
82
|
-
config.files.managed.push(entry);
|
|
83
|
-
added.managed.push(entry);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
for (const entry of defaults.files.merged) {
|
|
87
|
-
if (isPathOwnedByOtherPlatform(entry, platformType))
|
|
88
|
-
continue;
|
|
89
|
-
if (isPathOwnedByDisabledTUI(entry, enabledTUIs))
|
|
90
|
-
continue;
|
|
91
|
-
if (!allExisting.includes(entry)) {
|
|
92
|
-
config.files.merged.push(entry);
|
|
93
|
-
added.merged.push(entry);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const after = JSON.stringify({
|
|
97
|
-
files: {
|
|
98
|
-
managed: config.files.managed,
|
|
99
|
-
merged: config.files.merged,
|
|
100
|
-
ejected: config.files.ejected
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
return { added, changed: before !== after };
|
|
104
|
-
}
|
|
105
29
|
async function cmdUpdate() {
|
|
106
30
|
console.log('');
|
|
107
31
|
console.log(' ai update');
|
|
@@ -126,22 +50,36 @@ async function cmdUpdate() {
|
|
|
126
50
|
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
|
127
51
|
const { project, org, language } = config;
|
|
128
52
|
const platformType = config.platform?.type || defaults.platform.type;
|
|
129
|
-
const enabledTUIs = resolveEnabledTUIs(config.tuis);
|
|
130
53
|
const replacements = { project, org };
|
|
54
|
+
const normalizedOriginal = normalizeAgentClients(config);
|
|
55
|
+
const currentRegistry = {
|
|
56
|
+
managed: config.files?.managed || [],
|
|
57
|
+
merged: config.files?.merged || [],
|
|
58
|
+
ejected: config.files?.ejected || []
|
|
59
|
+
};
|
|
60
|
+
const platformAdded = !config.platform;
|
|
61
|
+
const sandboxAdded = !config.sandbox;
|
|
62
|
+
const taskAdded = !config.task;
|
|
63
|
+
const labelsAdded = !config.labels;
|
|
64
|
+
const prFlowMigrated = migratePrFlow(config);
|
|
65
|
+
if (platformAdded)
|
|
66
|
+
config.platform = structuredClone(defaults.platform);
|
|
67
|
+
if (sandboxAdded)
|
|
68
|
+
config.sandbox = structuredClone(defaults.sandbox);
|
|
69
|
+
if (taskAdded)
|
|
70
|
+
config.task = structuredClone(defaults.task);
|
|
71
|
+
if (labelsAdded)
|
|
72
|
+
config.labels = structuredClone(defaults.labels);
|
|
73
|
+
const workflowPlan = planAgentClientReconciliation({
|
|
74
|
+
config: config,
|
|
75
|
+
mutation: { type: 'replace-state', state: normalizedOriginal.state },
|
|
76
|
+
projectRoot: process.cwd(),
|
|
77
|
+
templateRoot: templateDir,
|
|
78
|
+
platformType,
|
|
79
|
+
language
|
|
80
|
+
});
|
|
131
81
|
info(`Updating seed files for: ${project}`);
|
|
132
82
|
console.log('');
|
|
133
|
-
// select language-specific template filenames
|
|
134
|
-
let claudeSrc, geminiSrc, opencodeSrc;
|
|
135
|
-
if (language === 'zh-CN') {
|
|
136
|
-
claudeSrc = 'update-agent-infra.zh-CN.md';
|
|
137
|
-
geminiSrc = 'update-agent-infra.zh-CN.toml';
|
|
138
|
-
opencodeSrc = 'update-agent-infra.zh-CN.md';
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
claudeSrc = 'update-agent-infra.en.md';
|
|
142
|
-
geminiSrc = 'update-agent-infra.en.toml';
|
|
143
|
-
opencodeSrc = 'update-agent-infra.en.md';
|
|
144
|
-
}
|
|
145
83
|
// update skill
|
|
146
84
|
copySkillDir(path.join(templateDir, '.agents', 'skills', 'update-agent-infra'), path.join('.agents', 'skills', 'update-agent-infra'), replacements, language, platformType);
|
|
147
85
|
ok('Updated .agents/skills/update-agent-infra/');
|
|
@@ -153,54 +91,15 @@ async function cmdUpdate() {
|
|
|
153
91
|
catch {
|
|
154
92
|
// Ignore missing legacy script from pre-ESM installs.
|
|
155
93
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
// update Gemini command (only if enabled)
|
|
162
|
-
if (enabledTUIs.has('gemini-cli')) {
|
|
163
|
-
renderFile(path.join(templateDir, '.gemini', 'commands', '_project_', geminiSrc), path.join('.gemini', 'commands', project, 'update-agent-infra.toml'), replacements);
|
|
164
|
-
ok(`Updated .gemini/commands/${project}/update-agent-infra.toml`);
|
|
165
|
-
}
|
|
166
|
-
// update OpenCode command (only if enabled)
|
|
167
|
-
if (enabledTUIs.has('opencode')) {
|
|
168
|
-
renderFile(path.join(templateDir, '.opencode', 'commands', opencodeSrc), path.join('.opencode', 'commands', 'update-agent-infra.md'), replacements);
|
|
169
|
-
ok('Updated .opencode/commands/update-agent-infra.md');
|
|
170
|
-
}
|
|
171
|
-
// sync file registry
|
|
172
|
-
const { added, changed } = syncFileRegistry(config, platformType, enabledTUIs);
|
|
94
|
+
const added = {
|
|
95
|
+
managed: workflowPlan.projectAssets.registry.managed.filter((entry) => !currentRegistry.managed.includes(entry)),
|
|
96
|
+
merged: workflowPlan.projectAssets.registry.merged.filter((entry) => !currentRegistry.merged.includes(entry))
|
|
97
|
+
};
|
|
173
98
|
const hasNewEntries = added.managed.length > 0 || added.merged.length > 0;
|
|
174
|
-
const
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const prFlowMigrated = migratePrFlow(config);
|
|
179
|
-
const sandboxToolsMigrated = !sandboxAdded && migrateSandboxTools(config);
|
|
180
|
-
let configChanged = changed;
|
|
181
|
-
if (platformAdded) {
|
|
182
|
-
config.platform = structuredClone(defaults.platform);
|
|
183
|
-
configChanged = true;
|
|
184
|
-
}
|
|
185
|
-
if (sandboxAdded) {
|
|
186
|
-
config.sandbox = structuredClone(defaults.sandbox);
|
|
187
|
-
configChanged = true;
|
|
188
|
-
}
|
|
189
|
-
if (taskAdded) {
|
|
190
|
-
config.task = structuredClone(defaults.task);
|
|
191
|
-
configChanged = true;
|
|
192
|
-
}
|
|
193
|
-
if (labelsAdded) {
|
|
194
|
-
config.labels = structuredClone(defaults.labels);
|
|
195
|
-
configChanged = true;
|
|
196
|
-
}
|
|
197
|
-
if (prFlowMigrated) {
|
|
198
|
-
configChanged = true;
|
|
199
|
-
}
|
|
200
|
-
if (sandboxToolsMigrated) {
|
|
201
|
-
configChanged = true;
|
|
202
|
-
}
|
|
203
|
-
if (configChanged) {
|
|
99
|
+
const reconcileResult = applyAgentClientReconciliation(workflowPlan);
|
|
100
|
+
for (const target of reconcileResult.applied)
|
|
101
|
+
ok(`Updated ${target}`);
|
|
102
|
+
if (reconcileResult.configUpdated) {
|
|
204
103
|
console.log('');
|
|
205
104
|
if (hasNewEntries) {
|
|
206
105
|
info(`New file entries synced to ${CONFIG_PATH}:`);
|
|
@@ -227,9 +126,6 @@ async function cmdUpdate() {
|
|
|
227
126
|
if (prFlowMigrated) {
|
|
228
127
|
info(`Migrated legacy requiresPullRequest to prFlow="${prFlowMigrated}" in ${CONFIG_PATH}.`);
|
|
229
128
|
}
|
|
230
|
-
if (sandboxToolsMigrated) {
|
|
231
|
-
info(`Migrated default sandbox.tools to include ${AGENT_INFRA_SANDBOX_TOOL} in ${CONFIG_PATH}.`);
|
|
232
|
-
}
|
|
233
129
|
}
|
|
234
130
|
else {
|
|
235
131
|
info(`File registry changed in ${CONFIG_PATH}.`);
|
|
@@ -249,37 +145,22 @@ async function cmdUpdate() {
|
|
|
249
145
|
if (hasNewEntries && prFlowMigrated) {
|
|
250
146
|
info(`Migrated legacy requiresPullRequest to prFlow="${prFlowMigrated}" in ${CONFIG_PATH}.`);
|
|
251
147
|
}
|
|
252
|
-
if (hasNewEntries && sandboxToolsMigrated) {
|
|
253
|
-
info(`Migrated default sandbox.tools to include ${AGENT_INFRA_SANDBOX_TOOL} in ${CONFIG_PATH}.`);
|
|
254
|
-
}
|
|
255
|
-
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n', 'utf8');
|
|
256
148
|
ok(`Updated ${CONFIG_PATH}`);
|
|
257
149
|
}
|
|
258
150
|
// done
|
|
259
151
|
console.log('');
|
|
260
152
|
ok('Seed files updated successfully!');
|
|
261
153
|
console.log('');
|
|
262
|
-
if (
|
|
263
|
-
console.log(' No
|
|
154
|
+
if (workflowPlan.nextSteps.length === 0) {
|
|
155
|
+
console.log(' No Agent Client project integration enabled.');
|
|
264
156
|
console.log(` Configure "customTUIs" in ${CONFIG_PATH} if needed.`);
|
|
265
157
|
console.log('');
|
|
266
158
|
}
|
|
267
159
|
else {
|
|
268
160
|
console.log(' Next step: run the full update in your AI TUI:');
|
|
269
161
|
console.log('');
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
claudeOrOpencode.push('Claude Code');
|
|
273
|
-
if (enabledTUIs.has('opencode'))
|
|
274
|
-
claudeOrOpencode.push('OpenCode');
|
|
275
|
-
if (claudeOrOpencode.length > 0) {
|
|
276
|
-
console.log(` ${claudeOrOpencode.join(' / ')}: /update-agent-infra`);
|
|
277
|
-
}
|
|
278
|
-
if (enabledTUIs.has('gemini-cli')) {
|
|
279
|
-
console.log(` Gemini CLI: /${project}:update-agent-infra`);
|
|
280
|
-
}
|
|
281
|
-
if (enabledTUIs.has('codex')) {
|
|
282
|
-
console.log(' Codex CLI: $update-agent-infra');
|
|
162
|
+
for (const nextStep of workflowPlan.nextSteps) {
|
|
163
|
+
console.log(` ${nextStep.displayName}: ${nextStep.command}`);
|
|
283
164
|
}
|
|
284
165
|
console.log('');
|
|
285
166
|
}
|