@fitlab-ai/agent-infra 0.9.11 → 0.9.12
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 +6 -6
- package/README.zh-CN.md +6 -6
- package/dist/bin/internal-cli.js +5 -0
- package/dist/lib/agent-clients/adapters/codex-lifecycle/build-identity.js +71 -10
- package/dist/lib/defaults.json +4 -0
- package/dist/lib/git/workflow.js +43 -1
- package/dist/lib/init.js +1 -0
- package/dist/lib/internal/git-workflow.js +8 -1
- package/dist/lib/internal/platform-pr.js +8 -2
- package/dist/lib/internal/task-delivery.js +59 -0
- package/dist/lib/platform/github-client.js +7 -1
- package/dist/lib/platform/pr-checks.js +8 -5
- package/dist/lib/platform/pr-summary.js +12 -8
- package/dist/lib/platform/pull-requests.js +393 -91
- package/dist/lib/platform/verification-required.js +13 -2
- package/dist/lib/platform/verification-sync.js +9 -4
- package/dist/lib/pr-review/evidence-grading.js +12 -4
- package/dist/lib/sandbox/config.js +5 -0
- package/dist/lib/sandbox/control/lifecycle.js +29 -7
- package/dist/lib/server/process-state.js +2 -2
- package/dist/lib/task/artifact-lifecycle.js +2 -2
- package/dist/lib/task/commit-intent.js +100 -0
- package/dist/lib/task/commit-operation.js +195 -101
- package/dist/lib/task/create.js +33 -7
- package/dist/lib/task/decision-details.js +3 -48
- package/dist/lib/task/delivery-target.js +97 -0
- package/dist/lib/task/delivery.js +153 -0
- package/dist/lib/task/human-override.js +5 -2
- package/dist/lib/task/lifecycle.js +106 -9
- package/dist/lib/task/orchestration.js +55 -62
- package/dist/lib/task/pr-delivery-fact.js +182 -0
- package/dist/lib/task/review-finalization.js +4 -8
- package/dist/lib/task/review-fingerprint.js +8 -0
- package/dist/lib/task/verification-engine.js +48 -24
- package/dist/lib/task/verification-review.js +1 -1
- package/dist/lib/update.js +9 -0
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-clients/adapters/codex-lifecycle/build-identity.ts +105 -10
- package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +12 -1
- package/lib/defaults.json +4 -0
- package/lib/git/workflow.ts +38 -1
- package/lib/init.ts +3 -0
- package/lib/internal/git-workflow.ts +7 -1
- package/lib/internal/platform-pr.ts +8 -1
- package/lib/internal/task-delivery.ts +53 -0
- package/lib/platform/github-client.ts +8 -1
- package/lib/platform/pr-checks.ts +7 -5
- package/lib/platform/pr-summary.ts +10 -7
- package/lib/platform/pull-requests.ts +425 -87
- package/lib/platform/verification-required.ts +12 -2
- package/lib/platform/verification-sync.ts +9 -4
- package/lib/pr-review/evidence-grading.ts +7 -4
- package/lib/sandbox/config.ts +7 -0
- package/lib/sandbox/control/lifecycle.ts +30 -8
- package/lib/server/process-state.ts +2 -2
- package/lib/task/artifact-lifecycle.ts +2 -2
- package/lib/task/commit-intent.ts +137 -0
- package/lib/task/commit-operation.ts +174 -87
- package/lib/task/create.ts +34 -9
- package/lib/task/decision-details.ts +2 -62
- package/lib/task/delivery-target.ts +130 -0
- package/lib/task/delivery.ts +160 -0
- package/lib/task/human-override.ts +5 -2
- package/lib/task/lifecycle.ts +93 -4
- package/lib/task/orchestration.ts +62 -65
- package/lib/task/pr-delivery-fact.ts +254 -0
- package/lib/task/review-finalization.ts +4 -14
- package/lib/task/review-fingerprint.ts +10 -0
- package/lib/task/verification-engine.ts +45 -28
- package/lib/task/verification-review.ts +2 -0
- package/lib/update.ts +10 -0
- package/package.json +1 -1
- package/templates/.agents/rules/README.en.md +4 -2
- package/templates/.agents/rules/README.zh-CN.md +4 -2
- package/templates/.agents/rules/create-issue.en.md +11 -2
- package/templates/.agents/rules/create-issue.zh-CN.md +24 -2
- package/templates/.agents/rules/issue-pr-commands.en.md +4 -17
- package/templates/.agents/rules/issue-sync.en.md +26 -5
- package/templates/.agents/rules/issue-sync.zh-CN.md +62 -5
- package/templates/.agents/rules/label-milestone-setup.en.md +15 -2
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +15 -2
- package/templates/.agents/rules/local-artifact-repair.en.md +46 -0
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +46 -0
- package/templates/.agents/rules/milestone-inference.en.md +12 -2
- package/templates/.agents/rules/milestone-inference.zh-CN.md +25 -3
- package/templates/.agents/rules/pr-sync.en.md +22 -13
- package/templates/.agents/rules/pr-sync.zh-CN.md +22 -1
- package/templates/.agents/rules/release-commands.en.md +42 -3
- package/templates/.agents/rules/release-commands.zh-CN.md +42 -3
- package/templates/.agents/rules/security-alerts.en.md +17 -2
- package/templates/.agents/rules/security-alerts.zh-CN.md +17 -2
- package/templates/.agents/rules/sync-content-generation.en.md +8 -0
- package/templates/.agents/rules/sync-content-generation.zh-CN.md +8 -0
- package/templates/.agents/rules/task-management.en.md +1 -1
- package/templates/.agents/rules/task-management.zh-CN.md +1 -1
- package/templates/.agents/scripts/security-alerts.github.sh +151 -0
- package/templates/.agents/scripts/security-alerts.sh +31 -0
- package/templates/.agents/skills/analyze-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
- package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/code-task/SKILL.en.md +5 -2
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +6 -3
- package/templates/.agents/skills/commit/SKILL.en.md +3 -3
- package/templates/.agents/skills/commit/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/config/verify.json +1 -1
- package/templates/.agents/skills/commit/reference/commit-orchestration.en.md +3 -3
- package/templates/.agents/skills/commit/reference/commit-orchestration.zh-CN.md +3 -3
- package/templates/.agents/skills/commit/reference/pr-summary-sync.en.md +1 -1
- package/templates/.agents/skills/commit/reference/pr-summary-sync.zh-CN.md +1 -1
- package/templates/.agents/skills/commit/reference/task-status-update.en.md +2 -2
- package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +2 -2
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +2 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +2 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.en.md +1 -1
- package/templates/.agents/skills/complete-manual-validation/reference/summary-update.zh-CN.md +1 -1
- package/templates/.agents/skills/complete-task/SKILL.en.md +10 -10
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +10 -10
- package/templates/.agents/skills/complete-task/reference/external-delivery.en.md +2 -2
- package/templates/.agents/skills/complete-task/reference/external-delivery.zh-CN.md +2 -2
- package/templates/.agents/skills/create-pr/SKILL.en.md +4 -4
- package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/create-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
- package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/init-labels/SKILL.en.md +9 -10
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +9 -10
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +57 -1
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +27 -1
- package/templates/.agents/skills/init-milestones/SKILL.en.md +3 -5
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +3 -5
- package/templates/.agents/skills/plan-task/SKILL.en.md +1 -0
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-analysis/SKILL.en.md +4 -3
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-code/SKILL.en.md +7 -6
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +7 -6
- package/templates/.agents/skills/review-code/reference/output-templates.en.md +19 -1
- package/templates/.agents/skills/review-code/reference/output-templates.zh-CN.md +19 -1
- package/templates/.agents/skills/review-code/reference/report-template.en.md +4 -2
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +4 -2
- package/templates/.agents/skills/review-plan/SKILL.en.md +4 -3
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +4 -3
- package/templates/.agents/skills/review-plan/reference/output-templates.en.md +18 -0
- package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +18 -0
- package/templates/.agents/skills/review-pr/SKILL.en.md +1 -0
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/review-pr/reference/evidence-grading.en.md +2 -2
- package/templates/.agents/skills/review-pr/reference/evidence-grading.zh-CN.md +2 -2
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +1 -0
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +1 -0
- package/templates/.agents/skills/run-task/SKILL.en.md +1 -1
- package/templates/.agents/skills/run-task/SKILL.zh-CN.md +1 -1
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +4 -0
- package/templates/.agents/skills/watch-pr/SKILL.en.md +4 -4
- package/templates/.agents/skills/watch-pr/SKILL.zh-CN.md +4 -4
- package/templates/.agents/templates/task.en.md +5 -1
- package/templates/.agents/templates/task.zh-CN.md +5 -1
- package/templates/.agents/workflows/bug-fix.en.yaml +9 -8
- package/templates/.agents/workflows/bug-fix.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/feature-development.en.yaml +9 -8
- package/templates/.agents/workflows/feature-development.zh-CN.yaml +9 -8
- package/templates/.agents/workflows/refactoring.en.yaml +9 -8
- package/templates/.agents/workflows/refactoring.zh-CN.yaml +9 -8
- package/templates/.agents/rules/create-issue.github.en.md +0 -14
- package/templates/.agents/rules/create-issue.github.zh-CN.md +0 -27
- package/templates/.agents/rules/issue-pr-commands.github.en.md +0 -34
- package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +0 -49
- package/templates/.agents/rules/issue-sync.github.en.md +0 -40
- package/templates/.agents/rules/issue-sync.github.zh-CN.md +0 -76
- package/templates/.agents/rules/label-milestone-setup.github.en.md +0 -60
- package/templates/.agents/rules/label-milestone-setup.github.zh-CN.md +0 -60
- package/templates/.agents/rules/milestone-inference.github.en.md +0 -15
- package/templates/.agents/rules/milestone-inference.github.zh-CN.md +0 -27
- package/templates/.agents/rules/pr-checks-commands.github.en.md +0 -18
- package/templates/.agents/rules/pr-checks-commands.github.zh-CN.md +0 -34
- package/templates/.agents/rules/pr-sync.github.en.md +0 -43
- package/templates/.agents/rules/pr-sync.github.zh-CN.md +0 -69
- package/templates/.agents/rules/release-commands.github.en.md +0 -44
- package/templates/.agents/rules/release-commands.github.zh-CN.md +0 -44
- package/templates/.agents/rules/security-alerts.github.en.md +0 -43
- package/templates/.agents/rules/security-alerts.github.zh-CN.md +0 -43
- /package/templates/.agents/rules/{issue-fields.github.en.md → issue-fields.en.md} +0 -0
- /package/templates/.agents/rules/{issue-fields.github.zh-CN.md → issue-fields.zh-CN.md} +0 -0
|
@@ -5,6 +5,7 @@ import { hasPlatformCapability } from "./adapters.js";
|
|
|
5
5
|
import { inspectRequiredChecks } from "./pr-checks.js";
|
|
6
6
|
import { resolvePlatformContext } from "./context.js";
|
|
7
7
|
import { resolveReviewedHeadRelation } from "./merged-pr-equivalence.js";
|
|
8
|
+
import { readPrDeliveryFact } from "../task/pr-delivery-fact.js";
|
|
8
9
|
const CHECK_TYPE = "required-checks";
|
|
9
10
|
const SHA_PATTERN = /^[0-9a-f]{7,40}$/i;
|
|
10
11
|
function validPrNumber(value) {
|
|
@@ -30,7 +31,13 @@ function readHead(repoRoot) {
|
|
|
30
31
|
}
|
|
31
32
|
export function evaluateRequiredChecks(context, shared) {
|
|
32
33
|
const { metadata, localHead, inspection, prFlow } = context;
|
|
33
|
-
|
|
34
|
+
const factRead = readPrDeliveryFact(metadata);
|
|
35
|
+
if (factRead.status === "invalid") {
|
|
36
|
+
return shared.failResult(CHECK_TYPE, factRead.error.message, "check_failed");
|
|
37
|
+
}
|
|
38
|
+
const fact = factRead.status === "valid" ? factRead.fact : null;
|
|
39
|
+
const prNumber = fact?.state === "bound" ? fact.identity.number : null;
|
|
40
|
+
if (prFlow === "disabled" || fact?.state === "skipped" || !validPrNumber(prNumber)) {
|
|
34
41
|
return shared.passResult(CHECK_TYPE, "Skipped: required checks are not applicable to this task");
|
|
35
42
|
}
|
|
36
43
|
const reviewedHead = String(metadata.last_reviewed_commit || "");
|
|
@@ -78,7 +85,11 @@ export function check({ taskDir }, shared) {
|
|
|
78
85
|
if (!task.ok)
|
|
79
86
|
return shared.failResult(CHECK_TYPE, task.message);
|
|
80
87
|
const prFlow = readPrFlow(shared.repoRoot);
|
|
81
|
-
|
|
88
|
+
const factRead = readPrDeliveryFact(task.metadata);
|
|
89
|
+
if (factRead.status === "invalid")
|
|
90
|
+
return shared.failResult(CHECK_TYPE, factRead.error.message, "check_failed");
|
|
91
|
+
const bound = factRead.status === "valid" && factRead.fact.state === "bound";
|
|
92
|
+
if (prFlow === "disabled" || (factRead.status === "valid" && factRead.fact.state === "skipped") || !bound) {
|
|
82
93
|
return evaluateRequiredChecks({ metadata: task.metadata, localHead: null, inspection: null, prFlow }, shared);
|
|
83
94
|
}
|
|
84
95
|
const platform = resolvePlatformContext({ cwd: shared.repoRoot });
|
|
@@ -9,6 +9,7 @@ import { inspectGitHubIssueMetadata, requirementSectionAnchors } from "./issues.
|
|
|
9
9
|
import { listRemoteComments } from "./issue-comments.js";
|
|
10
10
|
import { taskTypeLabel } from "./metadata-labels.js";
|
|
11
11
|
import { inspectGitHubPullRequest } from "./pull-requests.js";
|
|
12
|
+
import { readPrDeliveryFact } from "../task/pr-delivery-fact.js";
|
|
12
13
|
const CHECK_TYPE = "platform-sync";
|
|
13
14
|
const VERSION_LINE_REGEX = /^[0-9]+\.[0-9]+\.x$/;
|
|
14
15
|
const FRONTMATTER_FIELD_MAP = {
|
|
@@ -127,12 +128,16 @@ function buildSyncContext({ taskDir, config, artifactFile }) {
|
|
|
127
128
|
return { earlyReturn: failResult(CHECK_TYPE, task.message) };
|
|
128
129
|
}
|
|
129
130
|
const issueNumber = parseIssueNumber(task.metadata.issue_number);
|
|
130
|
-
const
|
|
131
|
+
const fact = readPrDeliveryFact(task.metadata);
|
|
132
|
+
if (fact.status === "invalid") {
|
|
133
|
+
return { earlyReturn: failResult(CHECK_TYPE, fact.error.message, "check_failed") };
|
|
134
|
+
}
|
|
135
|
+
const prNumber = fact.status === "valid" && fact.fact.state === "bound" ? fact.fact.identity.number : null;
|
|
131
136
|
if (config.when === "issue_number_exists" && !issueNumber) {
|
|
132
137
|
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: task has no issue_number") };
|
|
133
138
|
}
|
|
134
|
-
if (config.when === "
|
|
135
|
-
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: task has no
|
|
139
|
+
if (config.when === "pr_fact_bound" && !prNumber) {
|
|
140
|
+
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: task has no verified bound pull request") };
|
|
136
141
|
}
|
|
137
142
|
if (!issueNumber) {
|
|
138
143
|
return { earlyReturn: passResult(CHECK_TYPE, "Skipped: platform-sync not required for this task") };
|
|
@@ -276,7 +281,7 @@ function fetchRemoteData(context) {
|
|
|
276
281
|
if (context.prMarker) {
|
|
277
282
|
if (!context.prNumber) {
|
|
278
283
|
return {
|
|
279
|
-
earlyReturn: failResult(CHECK_TYPE, "Expected a
|
|
284
|
+
earlyReturn: failResult(CHECK_TYPE, "Expected a verified bound pull request for PR comment verification", "check_failed")
|
|
280
285
|
};
|
|
281
286
|
}
|
|
282
287
|
const prCommentsResult = listRemoteComments(githubClient, context.upstreamRepo, context.prNumber, context.taskDir);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { parseTypedTaskFrontmatter } from '../task/frontmatter.js';
|
|
4
|
+
import { readPrDeliveryFact } from '../task/pr-delivery-fact.js';
|
|
4
5
|
export class HostResolutionError extends Error {
|
|
5
6
|
code;
|
|
6
7
|
constructor(code, message) {
|
|
@@ -38,7 +39,7 @@ export function extractClosingIssueNumbers(body) {
|
|
|
38
39
|
/**
|
|
39
40
|
* Scan `.agents/workspace/active/{task-id}/task.md` files for tasks bound to the
|
|
40
41
|
* PR number or to one of the PR's closing issues. A task is emitted at most once;
|
|
41
|
-
* a
|
|
42
|
+
* a verified fact identity hit takes priority over the issue-number reverse lookup.
|
|
42
43
|
*/
|
|
43
44
|
export function collectHostCandidates(input) {
|
|
44
45
|
const activeRoot = path.join(input.workspaceRoot, '.agents', 'workspace', 'active');
|
|
@@ -62,9 +63,16 @@ export function collectHostCandidates(input) {
|
|
|
62
63
|
catch {
|
|
63
64
|
continue;
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
let frontmatter;
|
|
67
|
+
try {
|
|
68
|
+
frontmatter = parseTypedTaskFrontmatter(content);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
66
73
|
const issueNumber = toPositiveNumber(frontmatter.issue_number);
|
|
67
|
-
const
|
|
74
|
+
const fact = readPrDeliveryFact(frontmatter);
|
|
75
|
+
const prNumber = fact.status === 'valid' && fact.fact.state === 'bound' ? fact.fact.identity.number : null;
|
|
68
76
|
if (prNumber === input.prNumber) {
|
|
69
77
|
candidates.push({ taskId: entry.name, taskDir, issueNumber, prNumber });
|
|
70
78
|
}
|
|
@@ -67,6 +67,7 @@ export function loadConfig({ platformFn = platform, writeStderr = (chunk) => pro
|
|
|
67
67
|
const agentClients = normalizeAgentClients(airc);
|
|
68
68
|
const defaults = cloneDefaults();
|
|
69
69
|
const sandbox = airc.sandbox ?? {};
|
|
70
|
+
const delivery = airc.delivery ?? {};
|
|
70
71
|
const engine = validateSandboxEngine(sandbox.engine ?? defaults.engine, { platformFn });
|
|
71
72
|
const project = airc.project;
|
|
72
73
|
if (!project || typeof project !== 'string') {
|
|
@@ -111,6 +112,10 @@ export function loadConfig({ platformFn = platform, writeStderr = (chunk) => pro
|
|
|
111
112
|
tools,
|
|
112
113
|
customTools,
|
|
113
114
|
agentClientState: agentClients.state,
|
|
115
|
+
delivery: {
|
|
116
|
+
remote: typeof delivery.remote === 'string' ? delivery.remote : 'origin',
|
|
117
|
+
baseRef: typeof delivery.baseRef === 'string' ? delivery.baseRef : 'main'
|
|
118
|
+
},
|
|
114
119
|
refreshIntervalDays: asNonNegativeIntegerOrDefault(sandbox.refreshIntervalDays, defaults.refreshIntervalDays),
|
|
115
120
|
dockerfile,
|
|
116
121
|
vm: {
|
|
@@ -448,25 +448,27 @@ function readSandboxControlManifestValue(manifestPath) {
|
|
|
448
448
|
'mode', 'processingDir', 'project', 'publicStatusDir', 'repoRoot', 'runtimeDir',
|
|
449
449
|
'taskId', 'token', 'worktreeRoot'
|
|
450
450
|
];
|
|
451
|
-
if ('
|
|
452
|
-
|
|
453
|
-
throw new Error('SANDBOX_CONTROL_MANIFEST_REBUILD_REQUIRED: container-only recreation/rebuild is required');
|
|
451
|
+
if (Object.keys(manifest).sort().join(',') !== expectedKeys.sort().join(',')) {
|
|
452
|
+
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
454
453
|
}
|
|
455
454
|
if (typeof candidate.containerIdentity !== 'object' || candidate.containerIdentity === null
|
|
456
455
|
|| Array.isArray(candidate.containerIdentity))
|
|
457
456
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
458
457
|
const containerIdentity = candidate.containerIdentity;
|
|
459
|
-
if (
|
|
458
|
+
if (Object.keys(containerIdentity).sort().join(',') !== 'id,labels'
|
|
459
|
+
|| typeof candidate.engine !== 'string' || candidate.engine.length === 0
|
|
460
460
|
|| typeof candidate.repoRoot !== 'string' || typeof candidate.worktreeRoot !== 'string'
|
|
461
461
|
|| typeof candidate.project !== 'string' || typeof candidate.container !== 'string'
|
|
462
462
|
|| typeof containerIdentity.id !== 'string' || containerIdentity.id.length === 0
|
|
463
463
|
|| typeof containerIdentity.labels !== 'object' || containerIdentity.labels === null
|
|
464
464
|
|| Array.isArray(containerIdentity.labels)
|
|
465
465
|
|| Object.values(containerIdentity.labels).some((value) => typeof value !== 'string')
|
|
466
|
-
|| typeof candidate.branch !== 'string'
|
|
466
|
+
|| typeof candidate.branch !== 'string'
|
|
467
|
+
|| (candidate.mode !== 'task-bound' && candidate.mode !== 'branch-only')
|
|
467
468
|
|| (candidate.taskId !== null && typeof candidate.taskId !== 'string')
|
|
468
469
|
|| typeof candidate.channelDir !== 'string' || typeof candidate.publicStatusDir !== 'string'
|
|
469
|
-
|| typeof candidate.processingDir !== 'string' || typeof candidate.
|
|
470
|
+
|| typeof candidate.processingDir !== 'string' || typeof candidate.runtimeDir !== 'string'
|
|
471
|
+
|| typeof candidate.token !== 'string'
|
|
470
472
|
|| typeof candidate.generation !== 'string'
|
|
471
473
|
|| (candidate.mode === 'task-bound' && (typeof candidate.taskId !== 'string' || candidate.taskId.length === 0))
|
|
472
474
|
|| (candidate.mode === 'branch-only' && candidate.taskId !== null))
|
|
@@ -480,7 +482,27 @@ function readSandboxControlManifestValue(manifestPath) {
|
|
|
480
482
|
if (path.resolve(candidate.runtimeDir) !== path.join(root, 'runtime')) {
|
|
481
483
|
throw new Error('SANDBOX_CONTROL_MANIFEST_INVALID');
|
|
482
484
|
}
|
|
483
|
-
|
|
485
|
+
const normalized = {
|
|
486
|
+
engine: candidate.engine,
|
|
487
|
+
repoRoot: candidate.repoRoot,
|
|
488
|
+
worktreeRoot: candidate.worktreeRoot,
|
|
489
|
+
project: candidate.project,
|
|
490
|
+
container: candidate.container,
|
|
491
|
+
containerIdentity: {
|
|
492
|
+
id: containerIdentity.id,
|
|
493
|
+
labels: { ...containerIdentity.labels }
|
|
494
|
+
},
|
|
495
|
+
branch: candidate.branch,
|
|
496
|
+
mode: candidate.mode,
|
|
497
|
+
taskId: candidate.taskId,
|
|
498
|
+
token: candidate.token,
|
|
499
|
+
generation: candidate.generation,
|
|
500
|
+
channelDir: candidate.channelDir,
|
|
501
|
+
publicStatusDir: candidate.publicStatusDir,
|
|
502
|
+
processingDir: candidate.processingDir,
|
|
503
|
+
runtimeDir: candidate.runtimeDir
|
|
504
|
+
};
|
|
505
|
+
return normalized;
|
|
484
506
|
}
|
|
485
507
|
export function readSandboxControlManifest(manifestPath) {
|
|
486
508
|
return readSandboxControlManifestValue(manifestPath);
|
|
@@ -50,8 +50,8 @@ export function isProcessAlive(pid, platform = process.platform) {
|
|
|
50
50
|
return error.code === 'EPERM';
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
function parseDarwinStartTime(output) {
|
|
54
|
-
const match = output.trim().match(/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) ([A-Z][a-z]{2})
|
|
53
|
+
export function parseDarwinStartTime(output) {
|
|
54
|
+
const match = output.trim().match(/^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) ([A-Z][a-z]{2})\s+(\d{1,2}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/);
|
|
55
55
|
if (!match)
|
|
56
56
|
return null;
|
|
57
57
|
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
@@ -429,9 +429,9 @@ function buildArtifactLinkSection(content, artifact) {
|
|
|
429
429
|
const label = english
|
|
430
430
|
? `${spec.labels[1]} (Round ${artifact.round})`
|
|
431
431
|
: `${spec.labels[0]}(Round ${artifact.round})`;
|
|
432
|
-
const link =
|
|
432
|
+
const link = `${label}:\`${artifact.name}\``;
|
|
433
433
|
let body = extractSection(content, aliases);
|
|
434
|
-
if (body.includes(
|
|
434
|
+
if (body.includes(link))
|
|
435
435
|
return { aliases, heading, body };
|
|
436
436
|
const placeholders = new Set([
|
|
437
437
|
'[分析阶段的发现。哪些文件受影响?范围是什么?]',
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
function intentRoot(repoRoot) {
|
|
5
|
+
return path.join(repoRoot, '.agents', 'workspace', '.task-commit-intents');
|
|
6
|
+
}
|
|
7
|
+
function intentPath(repoRoot, taskId) {
|
|
8
|
+
return path.join(intentRoot(repoRoot), `${taskId}.json`);
|
|
9
|
+
}
|
|
10
|
+
function checkpointIntentDigest(identity) {
|
|
11
|
+
return createHash('sha256').update(JSON.stringify({
|
|
12
|
+
taskId: identity.taskId,
|
|
13
|
+
branch: identity.branch,
|
|
14
|
+
mode: identity.mode,
|
|
15
|
+
expectedHead: identity.expectedHead,
|
|
16
|
+
expectedTree: identity.expectedTree,
|
|
17
|
+
paths: [...identity.paths],
|
|
18
|
+
message: identity.message,
|
|
19
|
+
round: identity.round
|
|
20
|
+
})).digest('hex');
|
|
21
|
+
}
|
|
22
|
+
function isIntent(value) {
|
|
23
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
24
|
+
return false;
|
|
25
|
+
const intent = value;
|
|
26
|
+
return intent.version === 1
|
|
27
|
+
&& typeof intent.taskId === 'string' && intent.taskId.length > 0
|
|
28
|
+
&& typeof intent.branch === 'string' && intent.branch.length > 0
|
|
29
|
+
&& intent.mode === 'local'
|
|
30
|
+
&& typeof intent.expectedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.expectedHead)
|
|
31
|
+
&& typeof intent.expectedTree === 'string' && /^[a-f0-9]{40,64}$/.test(intent.expectedTree)
|
|
32
|
+
&& Array.isArray(intent.paths) && intent.paths.every((item) => typeof item === 'string' && item.length > 0)
|
|
33
|
+
&& typeof intent.message === 'string' && intent.message.length > 0
|
|
34
|
+
&& Number.isSafeInteger(intent.round) && Number(intent.round) > 0
|
|
35
|
+
&& typeof intent.digest === 'string' && /^[a-f0-9]{64}$/.test(intent.digest)
|
|
36
|
+
&& ['prepared', 'committed', 'synced'].includes(String(intent.state))
|
|
37
|
+
&& (intent.committedHead === null || (typeof intent.committedHead === 'string' && /^[a-f0-9]{40,64}$/.test(intent.committedHead)))
|
|
38
|
+
&& typeof intent.createdAt === 'string' && intent.createdAt.length > 0
|
|
39
|
+
&& typeof intent.updatedAt === 'string' && intent.updatedAt.length > 0
|
|
40
|
+
&& intent.digest === checkpointIntentDigest(intent);
|
|
41
|
+
}
|
|
42
|
+
function readCheckpointIntent(repoRoot, taskId) {
|
|
43
|
+
const target = intentPath(repoRoot, taskId);
|
|
44
|
+
if (!fs.existsSync(target))
|
|
45
|
+
return null;
|
|
46
|
+
const value = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
47
|
+
if (!isIntent(value))
|
|
48
|
+
throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
function writeCheckpointIntent(repoRoot, value) {
|
|
52
|
+
if (!isIntent(value))
|
|
53
|
+
throw new Error('COMMIT_INTENT_INVALID: checkpoint intent schema is invalid');
|
|
54
|
+
const directory = intentRoot(repoRoot);
|
|
55
|
+
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
56
|
+
const target = intentPath(repoRoot, value.taskId);
|
|
57
|
+
const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
58
|
+
fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
|
|
59
|
+
try {
|
|
60
|
+
fs.renameSync(temporary, target);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
try {
|
|
64
|
+
fs.unlinkSync(temporary);
|
|
65
|
+
}
|
|
66
|
+
catch { /* preserve primary error */ }
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function updateCheckpointIntent(value, patch) {
|
|
71
|
+
const next = { ...value, ...patch };
|
|
72
|
+
if (next.state === 'prepared' && next.committedHead !== null)
|
|
73
|
+
throw new Error('COMMIT_INTENT_INVALID: prepared intent cannot have a committed head');
|
|
74
|
+
if (next.state !== 'prepared' && !next.committedHead)
|
|
75
|
+
throw new Error('COMMIT_INTENT_INVALID: committed intent requires a committed head');
|
|
76
|
+
return next;
|
|
77
|
+
}
|
|
78
|
+
function removeCheckpointIntent(repoRoot, taskId) {
|
|
79
|
+
const target = intentPath(repoRoot, taskId);
|
|
80
|
+
try {
|
|
81
|
+
fs.unlinkSync(target);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error.code !== 'ENOENT')
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function sameCheckpointIntent(left, right) {
|
|
89
|
+
return left.digest === checkpointIntentDigest(right)
|
|
90
|
+
&& left.taskId === right.taskId
|
|
91
|
+
&& left.branch === right.branch
|
|
92
|
+
&& left.mode === right.mode
|
|
93
|
+
&& left.expectedHead === right.expectedHead
|
|
94
|
+
&& left.expectedTree === right.expectedTree
|
|
95
|
+
&& left.message === right.message
|
|
96
|
+
&& left.round === right.round
|
|
97
|
+
&& JSON.stringify(left.paths) === JSON.stringify(right.paths);
|
|
98
|
+
}
|
|
99
|
+
export { checkpointIntentDigest, intentPath, intentRoot, isIntent, readCheckpointIntent, removeCheckpointIntent, sameCheckpointIntent, updateCheckpointIntent, writeCheckpointIntent };
|
|
100
|
+
//# sourceMappingURL=commit-intent.js.map
|