@fitlab-ai/agent-infra 0.9.9 → 0.9.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/README.zh-CN.md +13 -3
- package/bin/cli.ts +17 -4
- package/dist/bin/cli.js +19 -4
- package/dist/bin/internal-cli.js +55 -4
- package/dist/lib/agent-client.js +0 -1
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +17 -10
- package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +11 -31
- package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +15 -33
- package/dist/lib/agent-clients/adapters/codex-sandbox.js +72 -11
- package/dist/lib/agent-clients/adapters/index.js +3 -1
- package/dist/lib/agent-clients/adapters/opencode-sandbox.js +0 -4
- package/dist/lib/agent-clients/adapters/traecli.js +65 -0
- package/dist/lib/agent-clients/config.js +14 -99
- package/dist/lib/agent-clients/reconcile.js +1 -11
- package/dist/lib/agent-clients/schema.js +5 -4
- package/dist/lib/agent-clients/tokens.js +7 -17
- package/dist/lib/agent-clients/types.js +2 -1
- package/dist/lib/decide.js +14 -30
- package/dist/lib/defaults.json +9 -0
- package/dist/lib/init.js +2 -2
- package/dist/lib/internal/codex-lifecycle.js +2 -2
- package/dist/lib/internal/codex-sandbox-controller.js +4 -3
- package/dist/lib/internal/release-workflow.js +0 -1
- package/dist/lib/internal/sandbox-control.js +2 -2
- package/dist/lib/internal/task-finalization.js +19 -9
- package/dist/lib/internal/task-ledger.js +8 -2
- package/dist/lib/internal/task-lifecycle.js +17 -93
- package/dist/lib/internal/task-orchestration.js +30 -216
- package/dist/lib/{task/commands/validate.js → internal/task-validate.js} +77 -43
- package/dist/lib/merge.js +205 -103
- package/dist/lib/process-data/normalize.js +2 -9
- package/dist/lib/run/host.js +46 -16
- package/dist/lib/run/tui.js +5 -2
- package/dist/lib/sandbox/agent-client-reconciler.js +4 -12
- package/dist/lib/sandbox/commands/create.js +3 -3
- package/dist/lib/sandbox/commands/enter.js +18 -4
- package/dist/lib/sandbox/config.js +3 -12
- package/dist/lib/sandbox/control/controller-registration.js +4 -2
- package/dist/lib/sandbox/control/executor.js +135 -40
- package/dist/lib/sandbox/control/lifecycle.js +29 -20
- package/dist/lib/sandbox/control/server.js +18 -16
- package/dist/lib/sandbox/mounts.js +3 -2
- package/dist/lib/sandbox/recovery.js +123 -22
- package/dist/lib/sandbox/workspace-identity.js +14 -0
- package/dist/lib/sandbox/workspace-view.js +8 -9
- package/dist/lib/self-update.js +278 -0
- package/dist/lib/server/protocol.js +5 -5
- package/dist/lib/task/activity-log.js +4 -1
- package/dist/lib/task/artifact-lifecycle.js +4 -2
- package/dist/lib/task/codex-orchestration.js +32 -35
- package/dist/lib/task/command-options.js +1 -3
- package/dist/lib/task/commands/cat.js +0 -5
- package/dist/lib/task/commands/decisions.js +76 -92
- package/dist/lib/task/commands/files.js +6 -6
- package/dist/lib/task/commands/grep.js +25 -61
- package/dist/lib/task/commands/issue-body.js +6 -6
- package/dist/lib/task/commands/log.js +25 -10
- package/dist/lib/task/commands/show.js +5 -6
- package/dist/lib/task/commands/status.js +8 -8
- package/dist/lib/task/commit-operation.js +21 -25
- package/dist/lib/task/commit-policy.js +1 -1
- package/dist/lib/task/control-authority.js +431 -0
- package/dist/lib/task/create.js +6 -1
- package/dist/lib/task/current-contract.js +35 -0
- package/dist/lib/task/decision-details.js +263 -0
- package/dist/lib/task/decision-intents.js +5 -2
- package/dist/lib/task/delegation-receipts.js +8 -7
- package/dist/lib/task/events.js +11 -5
- package/dist/lib/task/finalization.js +72 -46
- package/dist/lib/task/index.js +19 -29
- package/dist/lib/task/ledger-intents.js +8 -9
- package/dist/lib/task/ledger.js +13 -6
- package/dist/lib/task/lifecycle.js +16 -0
- package/dist/lib/task/orchestration.js +51 -14
- package/dist/lib/task/review-artifacts.js +31 -12
- package/dist/lib/task/review-finalization.js +19 -6
- package/dist/lib/task/verification-engine.js +38 -18
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/task/workspace-snapshot.js +5 -11
- package/dist/lib/task/write.js +11 -1
- package/dist/lib/update.js +6 -37
- package/dist/lib/version.js +5 -1
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +0 -1
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +25 -10
- package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +16 -33
- package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +16 -35
- package/lib/agent-clients/adapters/codex-sandbox.ts +89 -14
- package/lib/agent-clients/adapters/index.ts +3 -1
- package/lib/agent-clients/adapters/opencode-sandbox.ts +0 -5
- package/lib/agent-clients/adapters/traecli.ts +66 -0
- package/lib/agent-clients/config.ts +14 -144
- package/lib/agent-clients/reconcile.ts +1 -12
- package/lib/agent-clients/schema.ts +5 -4
- package/lib/agent-clients/tokens.ts +7 -20
- package/lib/agent-clients/types.ts +2 -1
- package/lib/decide.ts +12 -22
- package/lib/defaults.json +9 -0
- package/lib/init.ts +2 -2
- package/lib/internal/codex-lifecycle.ts +2 -2
- package/lib/internal/codex-sandbox-controller.ts +4 -3
- package/lib/internal/release-workflow.ts +0 -1
- package/lib/internal/sandbox-control.ts +2 -2
- package/lib/internal/task-finalization.ts +27 -13
- package/lib/internal/task-ledger.ts +8 -2
- package/lib/internal/task-lifecycle.ts +33 -76
- package/lib/internal/task-orchestration.ts +33 -190
- package/lib/{task/commands/validate.ts → internal/task-validate.ts} +77 -41
- package/lib/merge.ts +236 -120
- package/lib/process-data/normalize.ts +2 -8
- package/lib/run/host.ts +63 -14
- package/lib/run/tui.ts +5 -3
- package/lib/sandbox/agent-client-reconciler.ts +5 -15
- package/lib/sandbox/commands/create.ts +4 -4
- package/lib/sandbox/commands/enter.ts +24 -4
- package/lib/sandbox/config.ts +2 -14
- package/lib/sandbox/control/container-identity.ts +2 -2
- package/lib/sandbox/control/controller-registration.ts +8 -3
- package/lib/sandbox/control/executor.ts +156 -53
- package/lib/sandbox/control/lifecycle.ts +34 -28
- package/lib/sandbox/control/protocol.ts +1 -3
- package/lib/sandbox/control/server.ts +15 -12
- package/lib/sandbox/control/state.ts +7 -7
- package/lib/sandbox/mounts.ts +4 -3
- package/lib/sandbox/recovery.ts +162 -34
- package/lib/sandbox/tools.ts +1 -1
- package/lib/sandbox/workspace-identity.ts +28 -0
- package/lib/sandbox/workspace-view.ts +14 -10
- package/lib/self-update.ts +341 -0
- package/lib/server/protocol.ts +5 -5
- package/lib/task/activity-log.ts +6 -1
- package/lib/task/artifact-lifecycle.ts +5 -3
- package/lib/task/codex-orchestration.ts +40 -45
- package/lib/task/command-options.ts +1 -2
- package/lib/task/commands/cat.ts +0 -4
- package/lib/task/commands/decisions.ts +80 -75
- package/lib/task/commands/files.ts +6 -6
- package/lib/task/commands/grep.ts +23 -51
- package/lib/task/commands/issue-body.ts +6 -6
- package/lib/task/commands/log.ts +22 -10
- package/lib/task/commands/show.ts +5 -6
- package/lib/task/commands/status.ts +8 -8
- package/lib/task/commit-operation.ts +25 -30
- package/lib/task/commit-policy.ts +1 -2
- package/lib/task/control-authority.ts +563 -0
- package/lib/task/create.ts +6 -1
- package/lib/task/current-contract.ts +49 -0
- package/lib/task/decision-details.ts +340 -0
- package/lib/task/decision-intents.ts +7 -2
- package/lib/task/delegation-receipts.ts +8 -6
- package/lib/task/events.ts +10 -5
- package/lib/task/finalization.ts +84 -42
- package/lib/task/index.ts +19 -28
- package/lib/task/ledger-intents.ts +6 -8
- package/lib/task/ledger.ts +17 -7
- package/lib/task/lifecycle.ts +20 -0
- package/lib/task/orchestration.ts +42 -16
- package/lib/task/review-artifacts.ts +53 -15
- package/lib/task/review-finalization.ts +33 -7
- package/lib/task/verification-engine.ts +33 -21
- package/lib/task/verification-review.ts +1 -1
- package/lib/task/workspace-snapshot.ts +4 -13
- package/lib/task/write.ts +20 -1
- package/lib/update.ts +6 -40
- package/lib/version.ts +6 -1
- package/package.json +1 -1
- package/templates/.agents/QUICKSTART.en.md +2 -3
- package/templates/.agents/QUICKSTART.zh-CN.md +2 -3
- package/templates/.agents/README.en.md +5 -3
- package/templates/.agents/README.zh-CN.md +5 -3
- package/templates/.agents/rules/README.en.md +1 -0
- package/templates/.agents/rules/README.zh-CN.md +1 -0
- package/templates/.agents/rules/compatibility-policy.en.md +40 -0
- package/templates/.agents/rules/compatibility-policy.zh-CN.md +40 -0
- package/templates/.agents/rules/create-issue.github.en.md +1 -1
- package/templates/.agents/rules/create-issue.github.zh-CN.md +1 -1
- package/templates/.agents/rules/human-decision-context.en.md +9 -7
- package/templates/.agents/rules/human-decision-context.zh-CN.md +9 -7
- package/templates/.agents/rules/issue-fields.github.en.md +1 -1
- package/templates/.agents/rules/issue-fields.github.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.en.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-pr-commands.zh-CN.md +1 -1
- package/templates/.agents/rules/issue-sync.github.en.md +1 -1
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +2 -2
- package/templates/.agents/rules/lifecycle-orchestration.en.md +4 -4
- package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +4 -4
- package/templates/.agents/rules/milestone-inference.github.en.md +1 -1
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +1 -1
- package/templates/.agents/rules/next-step-output.en.md +3 -3
- package/templates/.agents/rules/next-step-output.zh-CN.md +3 -3
- package/templates/.agents/rules/no-mid-flow-questions.en.md +1 -1
- package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +1 -1
- package/templates/.agents/rules/pr-sync.en.md +2 -2
- package/templates/.agents/rules/pr-sync.github.en.md +3 -2
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +3 -1
- package/templates/.agents/rules/pr-sync.zh-CN.md +2 -1
- package/templates/.agents/rules/release-commands.github.en.md +6 -0
- package/templates/.agents/rules/release-commands.github.zh-CN.md +6 -0
- package/templates/.agents/rules/review-handshake.en.md +1 -1
- package/templates/.agents/rules/review-handshake.zh-CN.md +1 -1
- package/templates/.agents/rules/review-method.en.md +1 -0
- package/templates/.agents/rules/review-method.zh-CN.md +1 -0
- package/templates/.agents/rules/task-management.en.md +1 -2
- package/templates/.agents/rules/task-management.zh-CN.md +1 -2
- package/templates/.agents/skills/analyze-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/check-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/SKILL.en.md +4 -3
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/commit/SKILL.en.md +27 -7
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -4
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -5
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -5
- package/templates/.agents/skills/complete-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/create-pr/SKILL.en.md +15 -11
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +15 -11
- package/templates/.agents/skills/create-pr/reference/change-report.en.md +46 -0
- package/templates/.agents/skills/create-pr/reference/change-report.zh-CN.md +46 -0
- package/templates/.agents/skills/create-pr/scripts/change-report.mjs +203 -0
- package/templates/.agents/skills/create-release-note/SKILL.en.md +5 -6
- package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +5 -6
- package/templates/.agents/skills/create-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/plan-task/SKILL.en.md +5 -4
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +5 -4
- package/templates/.agents/skills/restore-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/review-analysis/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/review-code/reference/migration-risks.en.md +9 -6
- package/templates/.agents/skills/review-code/reference/migration-risks.zh-CN.md +9 -6
- package/templates/.agents/skills/review-plan/SKILL.en.md +5 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +5 -3
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -0
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +7 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +7 -3
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.en.md +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/discovery-and-execution.zh-CN.md +1 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
- package/templates/.agents/skills/run-task/SKILL.en.md +6 -2
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +6 -2
- package/templates/.agents/skills/run-task/reference/host-validation.en.md +2 -2
- package/templates/.agents/skills/run-task/reference/host-validation.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.en.md +2 -2
- package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +159 -104
- package/templates/.agents/skills/watch-pr/SKILL.en.md +2 -2
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +2 -2
- package/templates/.agents/templates/task.en.md +1 -1
- package/templates/.agents/templates/task.zh-CN.md +1 -1
- package/templates/.claude/commands/analyze-task.en.md +1 -1
- package/templates/.claude/commands/analyze-task.zh-CN.md +1 -1
- package/templates/.claude/commands/block-task.en.md +1 -1
- package/templates/.claude/commands/block-task.zh-CN.md +1 -1
- package/templates/.claude/commands/cancel-task.en.md +1 -1
- package/templates/.claude/commands/cancel-task.zh-CN.md +1 -1
- package/templates/.claude/commands/check-task.en.md +1 -1
- package/templates/.claude/commands/check-task.zh-CN.md +1 -1
- package/templates/.claude/commands/code-task.en.md +1 -1
- package/templates/.claude/commands/code-task.zh-CN.md +1 -1
- package/templates/.claude/commands/commit.en.md +1 -1
- package/templates/.claude/commands/commit.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.en.md +1 -1
- package/templates/.claude/commands/complete-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/complete-task.en.md +1 -1
- package/templates/.claude/commands/complete-task.zh-CN.md +1 -1
- package/templates/.claude/commands/create-pr.en.md +1 -1
- package/templates/.claude/commands/create-pr.zh-CN.md +1 -1
- package/templates/.claude/commands/plan-task.en.md +1 -1
- package/templates/.claude/commands/plan-task.zh-CN.md +1 -1
- package/templates/.claude/commands/review-analysis.en.md +1 -1
- package/templates/.claude/commands/review-analysis.zh-CN.md +1 -1
- package/templates/.claude/commands/review-code.en.md +1 -1
- package/templates/.claude/commands/review-code.zh-CN.md +1 -1
- package/templates/.claude/commands/review-plan.en.md +1 -1
- package/templates/.claude/commands/review-plan.zh-CN.md +1 -1
- package/templates/.claude/commands/run-manual-validation.en.md +1 -1
- package/templates/.claude/commands/run-manual-validation.zh-CN.md +1 -1
- package/templates/.claude/commands/run-task.en.md +1 -1
- package/templates/.claude/commands/run-task.zh-CN.md +1 -1
- package/templates/.claude/commands/watch-pr.en.md +1 -1
- package/templates/.claude/commands/watch-pr.zh-CN.md +1 -1
- package/templates/.traecli/commands/update-agent-infra.en.md +7 -0
- package/templates/.traecli/commands/update-agent-infra.zh-CN.md +7 -0
- package/dist/lib/builtin-tuis.js +0 -40
- package/lib/builtin-tuis.ts +0 -56
|
@@ -2,11 +2,12 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
|
|
5
|
-
import { locateActivityLog, pairEntries } from './activity-log.ts';
|
|
5
|
+
import { locateActivityLog, pairEntries, startedBackedRows } from './activity-log.ts';
|
|
6
6
|
import { parseArtifactName, validateCompletedArtifact } from './artifact-lifecycle.ts';
|
|
7
|
-
import {
|
|
7
|
+
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
8
8
|
import type { LedgerStageStatus, ReviewStage } from './ledger.ts';
|
|
9
9
|
import { finalizeReviewSummaryContent } from './review-artifacts.ts';
|
|
10
|
+
import { inspectDecisionDetailDuplicates, repairDecisionDetailDuplicates } from './decision-details.ts';
|
|
10
11
|
import { resolveTaskRef } from './resolve-ref.ts';
|
|
11
12
|
import { validateLifecycleExecution } from './lifecycle-execution.ts';
|
|
12
13
|
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.ts';
|
|
@@ -25,6 +26,7 @@ type ReviewFinalizationErrorCode =
|
|
|
25
26
|
| 'REVIEW_SUMMARY_NOT_FOUND'
|
|
26
27
|
| 'REVIEW_SUMMARY_PLACEHOLDER_INVALID'
|
|
27
28
|
| 'REVIEW_SUMMARY_COUNT_MISMATCH'
|
|
29
|
+
| 'REVIEW_DECISION_DETAIL_INVALID'
|
|
28
30
|
| 'REVIEW_ARTIFACT_CONFLICT'
|
|
29
31
|
| 'REVIEW_PROVENANCE_INVALID'
|
|
30
32
|
| 'REVIEW_TEMP_WRITE_FAILED'
|
|
@@ -106,8 +108,8 @@ function openReviewRound(content: string, action: string, round: number): boolea
|
|
|
106
108
|
const section = locateActivityLog(content);
|
|
107
109
|
if (!section) return false;
|
|
108
110
|
const expected = `${action} (Round ${round})`;
|
|
109
|
-
return pairEntries(section.entries).filter((row) => (
|
|
110
|
-
row.step === expected &&
|
|
111
|
+
return startedBackedRows(pairEntries(section.entries)).filter((row) => (
|
|
112
|
+
row.step === expected && !row.done
|
|
111
113
|
)).length === 1;
|
|
112
114
|
}
|
|
113
115
|
|
|
@@ -194,7 +196,11 @@ function finalizeReviewSummaryUnlocked(
|
|
|
194
196
|
|
|
195
197
|
let rows;
|
|
196
198
|
try {
|
|
197
|
-
|
|
199
|
+
const ledger = parseLedgerDocument(taskContent);
|
|
200
|
+
if (!ledger.present) {
|
|
201
|
+
return failed(request, 'REVIEW_LEDGER_INVALID', `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`, resolved.taskId);
|
|
202
|
+
}
|
|
203
|
+
rows = ledger.rows;
|
|
198
204
|
} catch (error) {
|
|
199
205
|
return failed(request, 'REVIEW_LEDGER_INVALID', String(error), resolved.taskId);
|
|
200
206
|
}
|
|
@@ -208,14 +214,34 @@ function finalizeReviewSummaryUnlocked(
|
|
|
208
214
|
);
|
|
209
215
|
}
|
|
210
216
|
const stageStatus = summarizeLedgerStage(rows, stage);
|
|
217
|
+
const repaired = repairDecisionDetailDuplicates(artifactContent);
|
|
218
|
+
if (!repaired.ok) {
|
|
219
|
+
return failed(
|
|
220
|
+
request,
|
|
221
|
+
'REVIEW_DECISION_DETAIL_INVALID',
|
|
222
|
+
`${repaired.code}: ${repaired.message}`,
|
|
223
|
+
resolved.taskId,
|
|
224
|
+
stageStatus
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const detailInspection = inspectDecisionDetailDuplicates(repaired.content);
|
|
228
|
+
if (!detailInspection.ok) {
|
|
229
|
+
return failed(
|
|
230
|
+
request,
|
|
231
|
+
'REVIEW_DECISION_DETAIL_INVALID',
|
|
232
|
+
`${detailInspection.code}: ${detailInspection.message}`,
|
|
233
|
+
resolved.taskId,
|
|
234
|
+
stageStatus
|
|
235
|
+
);
|
|
236
|
+
}
|
|
211
237
|
const transformed = finalizeReviewSummaryContent(
|
|
212
|
-
|
|
238
|
+
repaired.content,
|
|
213
239
|
stageStatus.unresolvedFindingCounts
|
|
214
240
|
);
|
|
215
241
|
if (!transformed.ok) {
|
|
216
242
|
return failed(request, transformed.code, transformed.message, resolved.taskId, stageStatus);
|
|
217
243
|
}
|
|
218
|
-
if (!transformed.changed) {
|
|
244
|
+
if (!repaired.changed && !transformed.changed) {
|
|
219
245
|
return {
|
|
220
246
|
...failed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, stageStatus),
|
|
221
247
|
status: 'no-op',
|
|
@@ -22,9 +22,11 @@ import { resolveMaterializedReviewedHeadRelation } from "../platform/change-requ
|
|
|
22
22
|
import { resolveReviewedHeadRelation } from "../platform/merged-pr-equivalence.ts";
|
|
23
23
|
import { resolveLocalReviewedCommitRelation } from "../git/reviewed-commit-equivalence.ts";
|
|
24
24
|
import { parseTypedTaskFrontmatter } from "./frontmatter.ts";
|
|
25
|
-
import {
|
|
25
|
+
import { LEDGER_SECTION_MISSING_CODE, LEDGER_SECTION_MISSING_MESSAGE, parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from "./ledger.ts";
|
|
26
26
|
import type { LedgerRow } from "./ledger.ts";
|
|
27
|
+
import { isValidAgentInfraVersion } from "../version.ts";
|
|
27
28
|
import { equalCounts, parseReviewSummary } from "./review-artifacts.ts";
|
|
29
|
+
import { inspectDecisionDetailDuplicates } from "./decision-details.ts";
|
|
28
30
|
import { loadVerificationConfig } from "./verification-config.ts";
|
|
29
31
|
import { snapshotReview } from "../git/review-snapshot.ts";
|
|
30
32
|
import { OrchestrationStateError, readRun } from "./orchestration.ts";
|
|
@@ -48,7 +50,6 @@ const DEFAULT_REQUIRED_FIELDS = [
|
|
|
48
50
|
];
|
|
49
51
|
|
|
50
52
|
const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?$/;
|
|
51
|
-
const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
52
53
|
const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:[+-]\d{2}:\d{2})?) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
|
|
53
54
|
// Start markers (action suffixed with ` [started]`) are excluded from the
|
|
54
55
|
// "latest action" / freshness computation so a step's in-flight marker never
|
|
@@ -108,6 +109,8 @@ function runCheck(type: any, context: any, shared: any): any {
|
|
|
108
109
|
return checkTaskMeta(context);
|
|
109
110
|
case "artifact":
|
|
110
111
|
return checkArtifact(context);
|
|
112
|
+
case "decision-details":
|
|
113
|
+
return checkDecisionDetails(context);
|
|
111
114
|
case "implementation-input":
|
|
112
115
|
return checkImplementationInput(context);
|
|
113
116
|
case "activity-log":
|
|
@@ -341,9 +344,6 @@ function checkOrchestrationEvidence({ taskDir }: any): any {
|
|
|
341
344
|
|| (activatedCodex && (
|
|
342
345
|
host?.kind !== 'codex-lifecycle-v2'
|
|
343
346
|
|| host.protocolVersion !== provenance.protocolVersion
|
|
344
|
-
|| host.packageVersion !== provenance.packageVersion
|
|
345
|
-
|| host.internalExecutableBuildHash !== provenance.internalExecutableBuildHash
|
|
346
|
-
|| host.lifecycleContractHash !== provenance.lifecycleContractHash
|
|
347
347
|
|| host.hookDefinitionHash !== provenance.hookDefinitionHash
|
|
348
348
|
|| host.hookSource !== provenance.hookSource
|
|
349
349
|
|| host.hookSourcePathDigest !== provenance.hookSourcePathDigest
|
|
@@ -395,23 +395,20 @@ function checkTaskMeta({ taskDir, config }: any): any {
|
|
|
395
395
|
const metadata = task.metadata;
|
|
396
396
|
const requiredFields = config.required_fields || DEFAULT_REQUIRED_FIELDS;
|
|
397
397
|
const missingFields = requiredFields.filter((field: any) => isBlank(metadata[field]));
|
|
398
|
-
const
|
|
398
|
+
const currentTask = metadata.status === 'active';
|
|
399
|
+
const blockingMissingFields = missingFields.filter((field: any) => field !== "agent_infra_version" || currentTask);
|
|
399
400
|
const warnings = [];
|
|
400
|
-
if (missingFields.includes("agent_infra_version")) {
|
|
401
|
+
if (missingFields.includes("agent_infra_version") && !currentTask) {
|
|
401
402
|
warnings.push("field 'agent_infra_version' missing — historical task or skipped version stamp");
|
|
402
403
|
}
|
|
403
404
|
if (blockingMissingFields.length > 0) {
|
|
404
405
|
return failResult("task-meta", `Missing required fields: ${blockingMissingFields.join(", ")}`);
|
|
405
406
|
}
|
|
406
407
|
|
|
407
|
-
if (
|
|
408
|
-
!isBlank(metadata.agent_infra_version) &&
|
|
409
|
-
metadata.agent_infra_version !== "unknown" &&
|
|
410
|
-
!AGENT_INFRA_VERSION_PATTERN.test(metadata.agent_infra_version)
|
|
411
|
-
) {
|
|
408
|
+
if (currentTask && !isValidAgentInfraVersion(metadata.agent_infra_version)) {
|
|
412
409
|
return failResult(
|
|
413
410
|
"task-meta",
|
|
414
|
-
`Invalid agent_infra_version: ${metadata.agent_infra_version}`
|
|
411
|
+
`Invalid agent_infra_version: ${String(metadata.agent_infra_version ?? 'missing')}`
|
|
415
412
|
);
|
|
416
413
|
}
|
|
417
414
|
|
|
@@ -625,6 +622,18 @@ function checkArtifact({ taskDir, config, artifactFile }: any): any {
|
|
|
625
622
|
);
|
|
626
623
|
}
|
|
627
624
|
|
|
625
|
+
function checkDecisionDetails({ taskDir, artifactFile }: any): any {
|
|
626
|
+
const resolvedArtifact = resolveArtifactPath(taskDir, "", artifactFile);
|
|
627
|
+
if (!resolvedArtifact.ok) return failResult("decision-details", resolvedArtifact.message);
|
|
628
|
+
const artifactPath = resolvedArtifact.path;
|
|
629
|
+
const stat = safeStat(artifactPath);
|
|
630
|
+
if (!stat?.isFile()) return failResult("decision-details", `Artifact not found: ${path.basename(artifactPath)}`);
|
|
631
|
+
if (stat.size === 0) return passResult("decision-details", `${path.basename(artifactPath)} contains no decision details`);
|
|
632
|
+
const inspection = inspectDecisionDetailDuplicates(fs.readFileSync(artifactPath, "utf8"));
|
|
633
|
+
if (!inspection.ok) return failResult("decision-details", `${path.basename(artifactPath)}: ${inspection.message}`);
|
|
634
|
+
return passResult("decision-details", `${path.basename(artifactPath)} has no duplicate decision detail ids`);
|
|
635
|
+
}
|
|
636
|
+
|
|
628
637
|
function checkReviewSummary({ taskDir, config, artifactFile }: any): any {
|
|
629
638
|
const stage = String(config.stage || "");
|
|
630
639
|
if (!["analysis", "plan", "code"].includes(stage)) {
|
|
@@ -643,7 +652,9 @@ function checkReviewSummary({ taskDir, config, artifactFile }: any): any {
|
|
|
643
652
|
if (!task.ok) return failResult("review-summary", task.message);
|
|
644
653
|
let rows;
|
|
645
654
|
try {
|
|
646
|
-
|
|
655
|
+
const ledger = parseLedgerDocument(task.content);
|
|
656
|
+
if (!ledger.present) return failResult("review-summary", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
657
|
+
rows = ledger.rows;
|
|
647
658
|
} catch (error) {
|
|
648
659
|
return failResult("review-summary", `Invalid disagreement ledger: ${String(error)}`);
|
|
649
660
|
}
|
|
@@ -949,14 +960,11 @@ function checkReviewLedger({ taskDir, config }: any): any {
|
|
|
949
960
|
return failResult("review-ledger", task.message);
|
|
950
961
|
}
|
|
951
962
|
|
|
952
|
-
const section = getSectionContent(task.content, LEDGER_SECTION_NAMES);
|
|
953
|
-
if (!section.trim()) {
|
|
954
|
-
return passResult("review-ledger", "No disagreement ledger section; treated as no open disagreements");
|
|
955
|
-
}
|
|
956
|
-
|
|
957
963
|
let rows;
|
|
958
964
|
try {
|
|
959
|
-
|
|
965
|
+
const ledger = parseLedgerDocument(task.content);
|
|
966
|
+
if (!ledger.present) return failResult("review-ledger", `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}`);
|
|
967
|
+
rows = ledger.rows.map((row) => [
|
|
960
968
|
row.id, row.stage, row.round, row.severity, row.status, row.evidence
|
|
961
969
|
]);
|
|
962
970
|
} catch (error) {
|
|
@@ -1251,7 +1259,11 @@ function resolvePostReviewExemption(content: string):
|
|
|
1251
1259
|
| { ok: true; exemptions: readonly LedgerRow[] }
|
|
1252
1260
|
| { ok: false; code: "POST_REVIEW_EXEMPTION_INVALID"; message: string } {
|
|
1253
1261
|
try {
|
|
1254
|
-
const
|
|
1262
|
+
const ledger = parseLedgerDocument(content);
|
|
1263
|
+
if (!ledger.present) {
|
|
1264
|
+
return { ok: false, code: "POST_REVIEW_EXEMPTION_INVALID", message: `${LEDGER_SECTION_MISSING_CODE}: ${LEDGER_SECTION_MISSING_MESSAGE}` };
|
|
1265
|
+
}
|
|
1266
|
+
const rows = ledger.rows;
|
|
1255
1267
|
const invalid = validateLedgerRows(rows);
|
|
1256
1268
|
if (invalid) {
|
|
1257
1269
|
return {
|
|
@@ -8,4 +8,4 @@ export {
|
|
|
8
8
|
parseReviewVerdict,
|
|
9
9
|
resolvePostReviewGlobs
|
|
10
10
|
} from './review-fingerprint.ts';
|
|
11
|
-
export {
|
|
11
|
+
export { parseLedgerDocument, summarizeLedgerStage, validateLedgerRows } from './ledger.ts';
|
|
@@ -53,13 +53,6 @@ function captureWorktreeTree(repoRoot: string, forcedPath: string | null): strin
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function captureLegacyWorkspaceSnapshot(repoRoot: string, taskId: string | null): string {
|
|
57
|
-
const workspaceRelative = taskId
|
|
58
|
-
? `.agents/workspace/active/${taskId}`
|
|
59
|
-
: '.agents/workspace/active';
|
|
60
|
-
return captureWorktreeTree(repoRoot, workspaceRelative);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
56
|
function taskFileFingerprints(stateRoot: string, taskId: string | null): TaskFileFingerprint[] {
|
|
64
57
|
const activeRoot = path.join(stateRoot, '.agents', 'workspace', 'active');
|
|
65
58
|
const roots = taskId ? [path.join(activeRoot, taskId)] : [activeRoot];
|
|
@@ -73,6 +66,7 @@ function taskFileFingerprints(stateRoot: string, taskId: string | null): TaskFil
|
|
|
73
66
|
return;
|
|
74
67
|
}
|
|
75
68
|
if (!stat.isFile() && !stat.isSymbolicLink()) return;
|
|
69
|
+
if (relative.startsWith('.agents/workspace/active/') && path.posix.basename(relative) === 'orchestration.json') return;
|
|
76
70
|
const content = stat.isSymbolicLink()
|
|
77
71
|
? Buffer.from(fs.readlinkSync(absolute))
|
|
78
72
|
: fs.readFileSync(absolute);
|
|
@@ -108,14 +102,11 @@ function decodeWorkspaceFingerprint(value: string): OrchestrationWorkspaceFinger
|
|
|
108
102
|
}
|
|
109
103
|
}
|
|
110
104
|
|
|
111
|
-
function captureWorkspaceSnapshot(context: WorkspaceSnapshotContext): string
|
|
112
|
-
function captureWorkspaceSnapshot(repoRoot: string, taskId: string | null): string;
|
|
113
|
-
function captureWorkspaceSnapshot(contextOrRoot: WorkspaceSnapshotContext | string, taskId?: string | null): string {
|
|
114
|
-
if (typeof contextOrRoot === 'string') return captureLegacyWorkspaceSnapshot(contextOrRoot, taskId ?? null);
|
|
105
|
+
function captureWorkspaceSnapshot(context: WorkspaceSnapshotContext): string {
|
|
115
106
|
return encodeWorkspaceFingerprint({
|
|
116
107
|
version: 2,
|
|
117
|
-
gitTree: captureWorktreeTree(
|
|
118
|
-
taskFiles: taskFileFingerprints(
|
|
108
|
+
gitTree: captureWorktreeTree(context.gitRoot, null),
|
|
109
|
+
taskFiles: taskFileFingerprints(context.stateRoot, context.taskId)
|
|
119
110
|
});
|
|
120
111
|
}
|
|
121
112
|
|
package/lib/task/write.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
|
|
4
|
-
import { VERSION } from '../version.ts';
|
|
4
|
+
import { isValidAgentInfraVersion, VERSION } from '../version.ts';
|
|
5
5
|
import {
|
|
6
6
|
parseTypedTaskFrontmatter,
|
|
7
7
|
updateTaskFrontmatter
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
import { allowsManualOverride } from './guard-override.ts';
|
|
16
16
|
import type { ManualOverrideCapability } from './guard-override.ts';
|
|
17
17
|
import { mutateTableRow, upsertSection } from './sections.ts';
|
|
18
|
+
import { validateCurrentTaskContract } from './current-contract.ts';
|
|
18
19
|
import type {
|
|
19
20
|
TableRowDeleteMutation,
|
|
20
21
|
TableRowUpsertMutation
|
|
@@ -84,6 +85,7 @@ type TaskWriteMetadata = {
|
|
|
84
85
|
type TaskWriteErrorCode =
|
|
85
86
|
| ResolveTaskRefErrorCode
|
|
86
87
|
| 'TASK_STATE_MISMATCH'
|
|
88
|
+
| 'TASK_CURRENT_CONTRACT_INVALID'
|
|
87
89
|
| 'TASK_READ_FAILED'
|
|
88
90
|
| 'TASK_DOCUMENT_INVALID'
|
|
89
91
|
| 'MUTATION_INVALID'
|
|
@@ -268,6 +270,13 @@ function writeTask(request: TaskWriteRequest, options: TaskWriteOptions = {}): T
|
|
|
268
270
|
);
|
|
269
271
|
}
|
|
270
272
|
|
|
273
|
+
if (resolved.state === 'active') {
|
|
274
|
+
const contract = validateCurrentTaskContract(original);
|
|
275
|
+
if (!contract.ok) {
|
|
276
|
+
return failure(request, identity, contract.code, contract.message);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
271
280
|
let candidate = original;
|
|
272
281
|
const operations: TaskOperationSummary[] = [];
|
|
273
282
|
try {
|
|
@@ -342,6 +351,16 @@ function writeTask(request: TaskWriteRequest, options: TaskWriteOptions = {}): T
|
|
|
342
351
|
operations
|
|
343
352
|
);
|
|
344
353
|
}
|
|
354
|
+
if (resolved.state === 'active' && !isValidAgentInfraVersion(metadata.agentInfraVersion)) {
|
|
355
|
+
return failure(
|
|
356
|
+
request,
|
|
357
|
+
identity,
|
|
358
|
+
'TASK_CURRENT_CONTRACT_INVALID',
|
|
359
|
+
`metadata agentInfraVersion must be a valid v-prefixed semver (received ${metadata.agentInfraVersion})`,
|
|
360
|
+
operations,
|
|
361
|
+
metadata
|
|
362
|
+
);
|
|
363
|
+
}
|
|
345
364
|
|
|
346
365
|
if (candidate === original) {
|
|
347
366
|
return {
|
package/lib/update.ts
CHANGED
|
@@ -20,13 +20,11 @@ type UpdateConfig = {
|
|
|
20
20
|
org: string;
|
|
21
21
|
language: string;
|
|
22
22
|
platform?: { type?: string };
|
|
23
|
-
requiresPullRequest?: boolean; // legacy field; read-only, migrated to prFlow then removed
|
|
24
23
|
prFlow?: 'required' | 'disabled';
|
|
25
24
|
sandbox?: Record<string, unknown>;
|
|
26
25
|
task?: { shortIdLength: number };
|
|
27
26
|
labels?: Record<string, unknown>;
|
|
28
27
|
files?: Partial<FileRegistry>;
|
|
29
|
-
tuis?: unknown;
|
|
30
28
|
agentClients?: unknown;
|
|
31
29
|
customTUIs?: unknown;
|
|
32
30
|
};
|
|
@@ -46,28 +44,9 @@ const defaults = JSON.parse(
|
|
|
46
44
|
const CONFIG_DIR = '.agents';
|
|
47
45
|
const CONFIG_PATH = path.join(CONFIG_DIR, '.airc.json');
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
// `prFlow` preference. `true` (the old default / "PR flow on") maps to the
|
|
51
|
-
// strong constraint `required`; `false` maps to `disabled`. A missing or
|
|
52
|
-
// already-migrated config is left untouched (idempotent). Returns the new
|
|
53
|
-
// prFlow value when a migration happened, otherwise null.
|
|
54
|
-
function migratePrFlow(config: UpdateConfig): 'required' | 'disabled' | null {
|
|
55
|
-
if (config.requiresPullRequest === true) {
|
|
56
|
-
delete config.requiresPullRequest;
|
|
57
|
-
config.prFlow = 'required';
|
|
58
|
-
return 'required';
|
|
59
|
-
}
|
|
60
|
-
if (config.requiresPullRequest === false) {
|
|
61
|
-
delete config.requiresPullRequest;
|
|
62
|
-
config.prFlow = 'disabled';
|
|
63
|
-
return 'disabled';
|
|
64
|
-
}
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function cmdUpdate(): Promise<void> {
|
|
47
|
+
async function cmdSync(): Promise<void> {
|
|
69
48
|
console.log('');
|
|
70
|
-
console.log(' ai
|
|
49
|
+
console.log(' ai sync');
|
|
71
50
|
console.log(' ==================================');
|
|
72
51
|
console.log('');
|
|
73
52
|
|
|
@@ -104,7 +83,6 @@ async function cmdUpdate(): Promise<void> {
|
|
|
104
83
|
const sandboxAdded = !config.sandbox;
|
|
105
84
|
const taskAdded = !config.task;
|
|
106
85
|
const labelsAdded = !config.labels;
|
|
107
|
-
const prFlowMigrated = migratePrFlow(config);
|
|
108
86
|
if (platformAdded) config.platform = structuredClone(defaults.platform);
|
|
109
87
|
if (sandboxAdded) config.sandbox = structuredClone(defaults.sandbox);
|
|
110
88
|
if (taskAdded) config.task = structuredClone(defaults.task);
|
|
@@ -119,7 +97,7 @@ async function cmdUpdate(): Promise<void> {
|
|
|
119
97
|
language
|
|
120
98
|
});
|
|
121
99
|
|
|
122
|
-
info(`
|
|
100
|
+
info(`Syncing seed files for: ${project}`);
|
|
123
101
|
console.log('');
|
|
124
102
|
|
|
125
103
|
// update skill
|
|
@@ -137,12 +115,6 @@ async function cmdUpdate(): Promise<void> {
|
|
|
137
115
|
replacements
|
|
138
116
|
);
|
|
139
117
|
ok('Updated .agents/scripts/lib/agent-infra-package.js');
|
|
140
|
-
try {
|
|
141
|
-
fs.unlinkSync(path.join('.agents', 'skills', 'update-agent-infra', 'scripts', 'sync-templates.cjs'));
|
|
142
|
-
} catch {
|
|
143
|
-
// Ignore missing legacy script from pre-ESM installs.
|
|
144
|
-
}
|
|
145
|
-
|
|
146
118
|
const added = {
|
|
147
119
|
managed: workflowPlan.projectAssets.registry.managed.filter(
|
|
148
120
|
(entry) => !currentRegistry.managed.includes(entry)
|
|
@@ -165,7 +137,7 @@ async function cmdUpdate(): Promise<void> {
|
|
|
165
137
|
for (const entry of added.merged) {
|
|
166
138
|
ok(` merged: ${entry}`);
|
|
167
139
|
}
|
|
168
|
-
} else if (platformAdded || sandboxAdded || taskAdded || labelsAdded
|
|
140
|
+
} else if (platformAdded || sandboxAdded || taskAdded || labelsAdded) {
|
|
169
141
|
if (platformAdded) {
|
|
170
142
|
info(`Default platform config added to ${CONFIG_PATH}.`);
|
|
171
143
|
}
|
|
@@ -178,9 +150,6 @@ async function cmdUpdate(): Promise<void> {
|
|
|
178
150
|
if (labelsAdded) {
|
|
179
151
|
info(`Default labels.in config added to ${CONFIG_PATH}.`);
|
|
180
152
|
}
|
|
181
|
-
if (prFlowMigrated) {
|
|
182
|
-
info(`Migrated legacy requiresPullRequest to prFlow="${prFlowMigrated}" in ${CONFIG_PATH}.`);
|
|
183
|
-
}
|
|
184
153
|
} else {
|
|
185
154
|
info(`File registry changed in ${CONFIG_PATH}.`);
|
|
186
155
|
}
|
|
@@ -196,15 +165,12 @@ async function cmdUpdate(): Promise<void> {
|
|
|
196
165
|
if (hasNewEntries && platformAdded) {
|
|
197
166
|
info(`Default platform config added to ${CONFIG_PATH}.`);
|
|
198
167
|
}
|
|
199
|
-
if (hasNewEntries && prFlowMigrated) {
|
|
200
|
-
info(`Migrated legacy requiresPullRequest to prFlow="${prFlowMigrated}" in ${CONFIG_PATH}.`);
|
|
201
|
-
}
|
|
202
168
|
ok(`Updated ${CONFIG_PATH}`);
|
|
203
169
|
}
|
|
204
170
|
|
|
205
171
|
// done
|
|
206
172
|
console.log('');
|
|
207
|
-
ok('Seed files
|
|
173
|
+
ok('Seed files synced successfully!');
|
|
208
174
|
console.log('');
|
|
209
175
|
if (workflowPlan.nextSteps.length === 0) {
|
|
210
176
|
console.log(' No Agent Client project integration enabled.');
|
|
@@ -220,4 +186,4 @@ async function cmdUpdate(): Promise<void> {
|
|
|
220
186
|
}
|
|
221
187
|
}
|
|
222
188
|
|
|
223
|
-
export {
|
|
189
|
+
export { cmdSync };
|
package/lib/version.ts
CHANGED
|
@@ -11,5 +11,10 @@ if (!packageJsonUrl) {
|
|
|
11
11
|
|
|
12
12
|
const { version } = JSON.parse(readFileSync(packageJsonUrl, 'utf8'));
|
|
13
13
|
const VERSION = `v${version}`;
|
|
14
|
+
const AGENT_INFRA_VERSION_PATTERN = /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
function isValidAgentInfraVersion(value: unknown): value is string {
|
|
17
|
+
return typeof value === 'string' && AGENT_INFRA_VERSION_PATTERN.test(value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { VERSION, isValidAgentInfraVersion };
|
package/package.json
CHANGED
|
@@ -27,11 +27,10 @@ npm install
|
|
|
27
27
|
npm run build
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
Lifecycle hooks always invoke `agent-infra-internal` through `PATH`; they do not implicitly switch to checkout source or `dist`. In a Codex sandbox, the controller's `PATH`-first shim is authoritative and binds the controller's selected executable. Skills, rules, hooks, and task data continue to come from the current checkout. The commands above develop the CLI itself and do not change hook executable selection.
|
|
30
|
+
Lifecycle hooks always invoke `agent-infra-internal` through `PATH`; they do not implicitly switch to checkout source or `dist`. In a Codex sandbox, the controller's `PATH`-first shim is authoritative and binds the controller's selected executable. Skills, rules, hooks, and task data continue to come from the current checkout. The commands above develop the CLI itself and do not change hook executable selection. To run the CLI from the current checkout, invoke the build output directly and compare its version with the package version. Do not run `npm link` on the host: it writes to npm's global prefix and can shadow a stable installation managed by Homebrew or npm.
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
|
|
34
|
-
ai version --raw
|
|
33
|
+
node ./dist/bin/cli.js version --raw
|
|
35
34
|
node -p "'v' + require('./package.json').version"
|
|
36
35
|
```
|
|
37
36
|
|
|
@@ -27,11 +27,10 @@ npm install
|
|
|
27
27
|
npm run build
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
生命周期 hook 始终通过 `PATH` 调用 `agent-infra-internal`,不会隐式切换到当前检出的 source 或 `dist`。在 Codex sandbox 中,controller 放在 `PATH` 首位的 shim 是权威入口,并绑定 controller 选定的 executable。skills、rules、hooks 和任务数据仍从当前检出读取。上面的命令只用于开发 CLI 本身,不会改变 hook 的 executable
|
|
30
|
+
生命周期 hook 始终通过 `PATH` 调用 `agent-infra-internal`,不会隐式切换到当前检出的 source 或 `dist`。在 Codex sandbox 中,controller 放在 `PATH` 首位的 shim 是权威入口,并绑定 controller 选定的 executable。skills、rules、hooks 和任务数据仍从当前检出读取。上面的命令只用于开发 CLI 本身,不会改变 hook 的 executable 选择。如需运行当前检出的 CLI,请直接执行构建产物并比较当前版本与包版本。不要在宿主机上执行 `npm link`:它会写入 npm 全局前缀,并可能遮蔽由 Homebrew 或 npm 安装的稳定版。
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
|
|
34
|
-
ai version --raw
|
|
33
|
+
node ./dist/bin/cli.js version --raw
|
|
35
34
|
node -p "'v' + require('./package.json').version"
|
|
36
35
|
```
|
|
37
36
|
|
|
@@ -124,7 +124,7 @@ To adapt agent-infra to a private code-hosting platform:
|
|
|
124
124
|
|
|
125
125
|
1. Set `.agents/.airc.json` `platform.type` to a stable identifier such as `my-platform`.
|
|
126
126
|
2. Copy the generated rule files in `.agents/rules/` and adapt them to your platform's CLI or API while keeping the runtime filenames unchanged.
|
|
127
|
-
3. Add the customized rule files to `.agents/.airc.json` `files.ejected` so future `
|
|
127
|
+
3. Add the customized rule files to `.agents/.airc.json` `files.ejected` so future `ai sync` runs do not overwrite them.
|
|
128
128
|
4. If you maintain a fork of the template source, add matching `.{platform}.` template variants before adding that platform identifier to the sync logic.
|
|
129
129
|
5. Validate the customized workflow on a test task before rolling it out broadly.
|
|
130
130
|
|
|
@@ -227,7 +227,7 @@ Ordinary `managed` files keep their overwrite semantics. A small set of platform
|
|
|
227
227
|
|
|
228
228
|
## Agent Client Configuration
|
|
229
229
|
|
|
230
|
-
Use the top-level `.agents/.airc.json` `agentClients` array to configure all
|
|
230
|
+
Use the top-level `.agents/.airc.json` `agentClients` array to configure all five built-in clients (`claude-code`, `codex`, `antigravity-cli`, `opencode`, `traecli`). Each canonical entry has three required fields and one optional orchestration policy:
|
|
231
231
|
|
|
232
232
|
| Field | Meaning |
|
|
233
233
|
|-------|---------|
|
|
@@ -250,7 +250,9 @@ ai agent-client configure
|
|
|
250
250
|
|
|
251
251
|
`enable` and `disable` only change `enabled`; `configure` edits both dimensions. `ai init` asks which clients to enable and preserves the displayed defaults when you press Enter. All clients default to `installInSandbox: true`.
|
|
252
252
|
|
|
253
|
-
|
|
253
|
+
TraeCode CLI uses `.agents/skills/` as the canonical Skill source. agent-infra generates lightweight slash-command wrappers under `.traecli/commands/`; each wrapper reads the corresponding shared Skill and forwards `$ARGUMENTS` when that Skill declares arguments. It does not mirror Skill packages into `.trae/skills/`, which remains user-owned for intentional Trae-specific overrides.
|
|
254
|
+
|
|
255
|
+
`agentClients` is the sole source of truth for built-in client state. The top-level array must contain all five built-in clients in the fixed canonical order; `sandbox.tools` lists only non-client tools such as `agent-infra` and custom tools. A legacy `tuis` field or a built-in client id in `sandbox.tools` is rejected, and configuration is never rewritten automatically.
|
|
254
256
|
|
|
255
257
|
### Side effects of disabling an Agent Client
|
|
256
258
|
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
|
|
123
123
|
1. 在 `.agents/.airc.json` 中把 `platform.type` 设为稳定标识,例如 `my-platform`。
|
|
124
124
|
2. 以 `.agents/rules/` 下已生成的规则文件为起点,改写为你的平台 CLI 或 API 调用,同时保持运行时文件名不变。
|
|
125
|
-
3. 将这些自定义规则文件加入 `.agents/.airc.json` 的 `files.ejected`,避免后续执行 `
|
|
125
|
+
3. 将这些自定义规则文件加入 `.agents/.airc.json` 的 `files.ejected`,避免后续执行 `ai sync` 时被覆盖。
|
|
126
126
|
4. 如果你维护的是模板源码分支或私有 fork,需要先补齐对应的 `.{platform}.` 模板变体,再把该平台标识加入模板同步逻辑。
|
|
127
127
|
5. 在正式推广前,先用一个测试任务完整验证工作流和 gate 校验。
|
|
128
128
|
|
|
@@ -225,7 +225,7 @@ disable-model-invocation: true # 可选;由支持该能力的 TUI 适配器
|
|
|
225
225
|
|
|
226
226
|
## Agent Client 配置
|
|
227
227
|
|
|
228
|
-
`.agents/.airc.json` 顶层 `agentClients`
|
|
228
|
+
`.agents/.airc.json` 顶层 `agentClients` 数组用于配置全部五个内建客户端(`claude-code`、`codex`、`antigravity-cli`、`opencode`、`traecli`)。每个规范条目包含三个必填字段和一个可选编排策略:
|
|
229
229
|
|
|
230
230
|
| 字段 | 含义 |
|
|
231
231
|
|------|------|
|
|
@@ -248,7 +248,9 @@ ai agent-client configure
|
|
|
248
248
|
|
|
249
249
|
`enable` 和 `disable` 只修改 `enabled`;`configure` 同时编辑两个维度。`ai init` 会询问启用哪些客户端,直接回车会保留界面展示的默认值。所有客户端的 `installInSandbox` 默认均为 `true`。
|
|
250
250
|
|
|
251
|
-
|
|
251
|
+
TraeCode CLI 以 `.agents/skills/` 作为 Skill 的唯一权威源。agent-infra 仅在 `.traecli/commands/` 下生成轻量 slash-command 包装文件;每个包装文件读取对应的共享 Skill,并在该 Skill 声明参数时转发 `$ARGUMENTS`。它不会把 Skill 包镜像到 `.trae/skills/`;该目录继续由用户所有,仅用于有意添加的 Trae 专属覆盖。
|
|
252
|
+
|
|
253
|
+
`agentClients` 是内建客户端状态的唯一配置来源。顶层数组必须按固定规范顺序包含全部五个内建客户端;`sandbox.tools` 只列出 `agent-infra` 和自定义工具等非客户端工具。旧 `tuis` 字段或 `sandbox.tools` 中的内建客户端 id 会被拒绝,配置不会被自动改写。
|
|
252
254
|
|
|
253
255
|
### 取消 Agent Client 的副作用
|
|
254
256
|
|
|
@@ -12,6 +12,7 @@ so you can quickly find "which ones to read" without opening each file.
|
|
|
12
12
|
- [`next-step-output.md`](next-step-output.md) — "Next step" output rules: task short-id rendering and the `Completed at` trailer.
|
|
13
13
|
- [`version-stamp.md`](version-stamp.md) — How and when to stamp `agent_infra_version`.
|
|
14
14
|
- [`debugging-guide.md`](debugging-guide.md) — Structured debugging flow: gather evidence → form hypothesis → verify hypothesis → fix the root cause; no blind patch-and-retry.
|
|
15
|
+
- [`compatibility-policy.md`](compatibility-policy.md) — Compatibility by exception: admission evidence, implementation boundaries, exit conditions, and lifecycle review requirements.
|
|
15
16
|
|
|
16
17
|
## Issue / PR
|
|
17
18
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
- [`next-step-output.md`](next-step-output.md) — 「下一步」输出规则:任务短号渲染与 `Completed at` 收尾行。
|
|
12
12
|
- [`version-stamp.md`](version-stamp.md) — `agent_infra_version` 版本戳的取值命令与写入时机。
|
|
13
13
|
- [`debugging-guide.md`](debugging-guide.md) — 结构化调试流程:收集证据→形成假设→验证假设→修复根因,禁止盲目改代码重试。
|
|
14
|
+
- [`compatibility-policy.md`](compatibility-policy.md) — 兼容性默认关闭:准入证据、实现边界、退出条件与生命周期审查要求。
|
|
14
15
|
|
|
15
16
|
## Issue / PR
|
|
16
17
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Compatibility Policy
|
|
2
|
+
|
|
3
|
+
This rule governs compatibility decisions during analysis, planning, implementation, and review. Support the current contract by default. Compatibility is an exception budget that requires evidence and an exit condition; it is not a synonym for safety.
|
|
4
|
+
|
|
5
|
+
## What Counts as Compatibility
|
|
6
|
+
|
|
7
|
+
Compatibility logic includes accepting or writing multiple generations of schemas, fields, states, or commands; retaining legacy aliases, adapters, wrappers, or shims; migrating data in the normal runtime path; falling back to different semantics based on an old format; or maintaining parallel facts and tests for old callers.
|
|
8
|
+
|
|
9
|
+
Current-operation idempotency and crash recovery, explicit platform or permission capability branches, fail-closed handling of unknown state, and user-required public multi-version contracts are not inherently legacy compatibility. Do not use those labels to expand support for an old protocol.
|
|
10
|
+
|
|
11
|
+
## Admission Gate
|
|
12
|
+
|
|
13
|
+
Add or extend compatibility only when the task or an existing public contract explicitly requires it and the artifact records all four items:
|
|
14
|
+
|
|
15
|
+
1. **Subject**: concrete consumers, released versions, or stored data still using the old contract.
|
|
16
|
+
2. **Necessity**: why an atomic cutover, one-time conversion, or actionable failure is insufficient.
|
|
17
|
+
3. **Window**: a version, date, or verifiable endpoint for the compatibility period.
|
|
18
|
+
4. **Exit**: removal conditions and the code, tests, and documentation to delete.
|
|
19
|
+
|
|
20
|
+
If any item is missing, compatibility is unauthorized scope expansion. Implement the current contract, fail closed with an actionable repair message for old input, or perform an explicit one-time conversion outside the main path.
|
|
21
|
+
|
|
22
|
+
## Implementation Boundaries
|
|
23
|
+
|
|
24
|
+
- Keep one canonical write format and one source of truth. Do not dual-write, maintain shadow state, or try the new path before silently falling back to the old path.
|
|
25
|
+
- Concentrate an approved conversion at one boundary and immediately enter the current model; business logic must not understand several historical versions.
|
|
26
|
+
- Mark temporarily retained compatibility at its single boundary with `TODO(compat): Remove ... once ...`, naming the removal target and a verifiable removal condition. The TODO stays co-located with the code; tasks and issues are optional scheduling aids, not compatibility facts or workflow gates.
|
|
27
|
+
- Use warnings only when the primary action remains correct and the user can retry an ancillary operation. Never hide uncertainty about identity, authorization, data interpretation, or side-effect correctness.
|
|
28
|
+
- When removing an old capability, remove its adapters, branches, fixtures, tests, and migration documentation together. Do not add negative tests that permanently remember deleted behavior.
|
|
29
|
+
- Never guess the meaning of unknown state. Preserve it, stop writes, and provide rebuild or manual-repair guidance.
|
|
30
|
+
|
|
31
|
+
## Lifecycle Requirements
|
|
32
|
+
|
|
33
|
+
- **Analysis**: separate explicit compatibility requirements from model speculation and identify real consumers or stored data. State current-only when evidence is absent.
|
|
34
|
+
- **Plan**: for approved compatibility, identify the boundary, single conversion point, window, and deletion plan. Do not present a compatibility layer as the default low-risk option.
|
|
35
|
+
- **Implementation**: implement only the approved compatibility budget, and add or move its `TODO(compat)` at the single compatibility boundary. Do not preserve an unapproved old branch “just in case.”
|
|
36
|
+
- **Review**: verify the four admission items, single source of truth, exit condition, and co-located `TODO(compat)`. Flag unauthorized compatibility, indefinite shims, dual writes, and runtime-path migrations as scope and maintainability problems.
|
|
37
|
+
|
|
38
|
+
## Existing Compatibility Logic
|
|
39
|
+
|
|
40
|
+
During an ordinary task, when out-of-scope compatibility is found, only ensure that its single boundary has one `TODO(compat)` and record the location and risk. Do not delete the logic or duplicate the marker. A dedicated simplification task should first search those TODOs and inventory consumers and stored data, then process items in this order: remove now, warn then remove, retain temporarily.
|