@fitlab-ai/agent-infra 0.11.0 → 0.11.1
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/dist/lib/internal/manual-validation.js +6 -2
- package/dist/lib/platform/issues.js +3 -4
- package/dist/lib/platform/verification-sync.js +142 -154
- package/dist/lib/sandbox/control/workflow-executor.js +7 -1
- package/dist/lib/task/artifact-lifecycle.js +15 -52
- package/dist/lib/task/artifact-operations.js +27 -1
- package/dist/lib/task/capabilities.js +0 -2
- package/dist/lib/task/events.js +60 -43
- package/dist/lib/task/gate-policy.js +94 -0
- package/dist/lib/task/local-artifact-finalization.js +7 -4
- package/dist/lib/task/orchestration.js +8 -6
- package/dist/lib/task/review-artifacts.js +12 -6
- package/dist/lib/task/review-finalization.js +3 -9
- package/dist/lib/task/verification-engine.js +28 -17
- package/dist/lib/task/verification.js +25 -9
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/internal/manual-validation.ts +6 -2
- package/lib/platform/issues.ts +3 -4
- package/lib/platform/verification-sync.ts +159 -177
- package/lib/sandbox/control/workflow-executor.ts +11 -1
- package/lib/task/artifact-lifecycle.ts +12 -49
- package/lib/task/artifact-operations.ts +27 -1
- package/lib/task/capabilities.ts +0 -1
- package/lib/task/events.ts +49 -32
- package/lib/task/gate-policy.ts +133 -0
- package/lib/task/local-artifact-finalization.ts +6 -4
- package/lib/task/orchestration.ts +12 -7
- package/lib/task/review-artifacts.ts +8 -2
- package/lib/task/review-finalization.ts +3 -9
- package/lib/task/verification-engine.ts +24 -14
- package/lib/task/verification-types.ts +7 -0
- package/lib/task/verification.ts +25 -9
- package/package.json +1 -1
- package/templates/.agents/rules/issue-sync.en.md +2 -0
- package/templates/.agents/rules/issue-sync.zh-CN.md +5 -8
- package/templates/.agents/rules/local-artifact-repair.en.md +11 -3
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +11 -3
- package/templates/.agents/skills/analyze-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -10
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/block-task/config/verify.json +1 -3
- package/templates/.agents/skills/cancel-task/config/verify.json +1 -4
- package/templates/.agents/skills/code-task/SKILL.en.md +3 -3
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +3 -3
- package/templates/.agents/skills/code-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +1 -12
- package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
- package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +11 -0
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +11 -0
- package/templates/.agents/skills/commit/config/verify.json +1 -5
- package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +6 -6
- package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +6 -6
- package/templates/.agents/skills/complete-task/config/verify.en.json +3 -14
- package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +3 -14
- package/templates/.agents/skills/create-pr/config/verify.json +1 -10
- package/templates/.agents/skills/create-task/config/verify.json +1 -4
- package/templates/.agents/skills/import-issue/config/verify.json +1 -2
- package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
- package/templates/.agents/skills/plan-task/config/verify.en.json +1 -10
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +4 -4
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-code/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -10
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -10
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/review-pr/config/verify.en.json +1 -8
- package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +1 -8
- package/templates/.agents/skills/run-manual-validation/config/verify.en.json +38 -13
- package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +38 -13
|
@@ -163,7 +163,6 @@ function preflightReviewSummaryUnlocked(
|
|
|
163
163
|
let taskContent: string;
|
|
164
164
|
let content: string;
|
|
165
165
|
let recovery: ArtifactRecoveryContext | undefined;
|
|
166
|
-
let existingIntent;
|
|
167
166
|
try {
|
|
168
167
|
taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8');
|
|
169
168
|
if (request.recoveryId) {
|
|
@@ -179,7 +178,6 @@ function preflightReviewSummaryUnlocked(
|
|
|
179
178
|
if (!validated.ok) return preflightFailed(request, validated.error.code === 'ARTIFACT_NOT_REGULAR' ? 'REVIEW_ARTIFACT_NOT_REGULAR' : 'REVIEW_ARTIFACT_IDENTITY_INVALID', validated.error.message, resolved.taskId);
|
|
180
179
|
content = fs.readFileSync(validated.artifact.path, 'utf8');
|
|
181
180
|
const intent = readArtifactRecoveryIntent(resolved.repoRoot, resolved.taskId, spec.family, request.artifact);
|
|
182
|
-
existingIntent = intent;
|
|
183
181
|
if (intent?.state === 'preflight-ready') recovery = recoveryContextFromIntent(resolved.repoRoot, resolved.taskDir, intent);
|
|
184
182
|
if (intent?.state === 'consumed') return preflightFailed(request, 'REVIEW_PROVENANCE_INVALID', 'review artifact was already finalized', resolved.taskId);
|
|
185
183
|
}
|
|
@@ -224,12 +222,6 @@ function preflightReviewSummaryUnlocked(
|
|
|
224
222
|
...(recovery ? { recovery: recoveryInfo(recovery) } : {})
|
|
225
223
|
});
|
|
226
224
|
}
|
|
227
|
-
if (!recovery && existingIntent?.state === 'passed') {
|
|
228
|
-
return {
|
|
229
|
-
...preflightFailed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, { artifactSha256, semanticDigest }),
|
|
230
|
-
status: 'passed', changed: false, error: null
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
225
|
if (request.dryRun || recovery && readArtifactRecoveryIntent(resolved.repoRoot, resolved.taskId, spec.family, request.artifact)?.state === 'preflight-ready') {
|
|
234
226
|
return {
|
|
235
227
|
...preflightFailed(request, 'REVIEW_ARTIFACT_CONFLICT', '', resolved.taskId, { artifactSha256, semanticDigest, ...(recovery ? { recovery: recoveryInfo(recovery) } : {}) }),
|
|
@@ -385,7 +377,9 @@ function prepareReviewSummaryCandidate(
|
|
|
385
377
|
...(recovery ? { recovery } : {})
|
|
386
378
|
};
|
|
387
379
|
}
|
|
388
|
-
const transformed = finalizeReviewSummaryContent(artifactContent, stageStatus.unresolvedFindingCounts
|
|
380
|
+
const transformed = finalizeReviewSummaryContent(artifactContent, stageStatus.unresolvedFindingCounts, {
|
|
381
|
+
refreshNumericCounts: Boolean(request.recoveryId && recovery)
|
|
382
|
+
});
|
|
389
383
|
if (!transformed.ok) return reject(transformed.code, transformed.message);
|
|
390
384
|
const finalDigests = { artifactSha256: sha256Content(transformed.content), semanticDigest: canonicalSemanticDigest(transformed.content) };
|
|
391
385
|
if (!recovery && repairIntent?.state === 'commit-started') {
|
|
@@ -44,6 +44,7 @@ import { validateQualificationAudit } from "./qualification-audit.ts";
|
|
|
44
44
|
import { getArtifactSchema } from "./artifact-schema.ts";
|
|
45
45
|
import { inspectArtifactContract } from "./artifact-operations.ts";
|
|
46
46
|
import type { VerificationShared } from "./verification-types.ts";
|
|
47
|
+
import { normalizeVerificationRecord } from './gate-policy.ts';
|
|
47
48
|
import { manualValidationFinalSummaryProjectionMatches } from "./manual-validation-receipt.ts";
|
|
48
49
|
import { readManualValidationCompletion } from "./manual-validation-completion.ts";
|
|
49
50
|
import { sha256File } from "./artifact-receipts.ts";
|
|
@@ -1392,11 +1393,11 @@ function interpolate(template: any, taskDir: any, artifactFile: any): any {
|
|
|
1392
1393
|
}
|
|
1393
1394
|
|
|
1394
1395
|
function summarizeGate(checks: any): any {
|
|
1395
|
-
if (checks.some((check: any) => check.
|
|
1396
|
+
if (checks.some((check: any) => check.effectiveStatus === "blocked")) {
|
|
1396
1397
|
return "blocked";
|
|
1397
1398
|
}
|
|
1398
1399
|
|
|
1399
|
-
if (checks.some((check: any) => check.
|
|
1400
|
+
if (checks.some((check: any) => check.effectiveStatus === "fail")) {
|
|
1400
1401
|
return "fail";
|
|
1401
1402
|
}
|
|
1402
1403
|
|
|
@@ -1405,9 +1406,9 @@ function summarizeGate(checks: any): any {
|
|
|
1405
1406
|
|
|
1406
1407
|
function summarizeChecks(checks: any): any {
|
|
1407
1408
|
const counts = {
|
|
1408
|
-
pass: checks.filter((check: any) => check.
|
|
1409
|
-
fail: checks.filter((check: any) => check.
|
|
1410
|
-
blocked: checks.filter((check: any) => check.
|
|
1409
|
+
pass: checks.filter((check: any) => check.effectiveStatus === "pass").length,
|
|
1410
|
+
fail: checks.filter((check: any) => check.effectiveStatus === "fail").length,
|
|
1411
|
+
blocked: checks.filter((check: any) => check.effectiveStatus === "blocked").length
|
|
1411
1412
|
};
|
|
1412
1413
|
|
|
1413
1414
|
if (counts.blocked > 0) {
|
|
@@ -1422,7 +1423,7 @@ function buildAction(gate: any, checks: any): any {
|
|
|
1422
1423
|
return "All declared checks passed";
|
|
1423
1424
|
}
|
|
1424
1425
|
|
|
1425
|
-
const firstFailure = checks.find((check: any) => check.
|
|
1426
|
+
const firstFailure = checks.find((check: any) => check.effectiveStatus !== "pass");
|
|
1426
1427
|
if (!firstFailure) {
|
|
1427
1428
|
return "Review validation output";
|
|
1428
1429
|
}
|
|
@@ -1484,16 +1485,16 @@ async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks:
|
|
|
1484
1485
|
const checks = [];
|
|
1485
1486
|
for (const [type, checkConfig] of Object.entries(verifyConfig.checks || {})) {
|
|
1486
1487
|
if (checkConfig === null) continue;
|
|
1487
|
-
const result = await runCheck(type, {
|
|
1488
|
+
const result = normalizeVerificationRecord(await runCheck(type, {
|
|
1488
1489
|
mode,
|
|
1489
1490
|
skillName,
|
|
1490
1491
|
taskDir: path.resolve(taskDir),
|
|
1491
1492
|
artifactFile,
|
|
1492
1493
|
repositoryRoot: repoRoot,
|
|
1493
1494
|
config: checkConfig
|
|
1494
|
-
}, shared);
|
|
1495
|
-
checks.push(result);
|
|
1496
|
-
if (
|
|
1495
|
+
}, shared));
|
|
1496
|
+
checks.push(...(result.subchecks?.map(normalizeVerificationRecord) ?? [result]));
|
|
1497
|
+
if (checks.at(-1)?.effectiveStatus === "blocked") break;
|
|
1497
1498
|
}
|
|
1498
1499
|
const gate = summarizeGate(checks);
|
|
1499
1500
|
return { gate, skill: skillName, checks, summary: summarizeChecks(checks), action: buildAction(gate, checks) };
|
|
@@ -1502,15 +1503,24 @@ async function verifyInProcess({ mode, skillName, taskDir, artifactFile, checks:
|
|
|
1502
1503
|
const config = (verifyConfig.checks || {})[type];
|
|
1503
1504
|
if (config === undefined) return { skill: skillName, ...failResult(type, `Unknown check type '${type}' for skill '${skillName}'.`) };
|
|
1504
1505
|
if (config === null) return { skill: skillName, ...passResult(type, `Check '${type}' is disabled for skill '${skillName}'.`) };
|
|
1505
|
-
|
|
1506
|
-
skill: skillName,
|
|
1507
|
-
...await runCheck(type, {
|
|
1506
|
+
const result = normalizeVerificationRecord(await runCheck(type, {
|
|
1508
1507
|
skillName,
|
|
1509
1508
|
taskDir: path.resolve(taskDir),
|
|
1510
1509
|
artifactFile,
|
|
1511
1510
|
repositoryRoot: repoRoot,
|
|
1512
1511
|
config
|
|
1513
|
-
}, shared)
|
|
1512
|
+
}, shared));
|
|
1513
|
+
if (!result.subchecks?.length) return { skill: skillName, ...result };
|
|
1514
|
+
const checks = result.subchecks.map(normalizeVerificationRecord);
|
|
1515
|
+
const gate = summarizeGate(checks);
|
|
1516
|
+
return {
|
|
1517
|
+
skill: skillName,
|
|
1518
|
+
...result,
|
|
1519
|
+
status: gate,
|
|
1520
|
+
effectiveStatus: gate,
|
|
1521
|
+
reason: gate === 'pass' ? 'OK' : checks.find((check: any) => check.effectiveStatus !== 'pass')?.reason ?? 'CHECK_FAILED',
|
|
1522
|
+
action: buildAction(gate, checks),
|
|
1523
|
+
checks
|
|
1514
1524
|
};
|
|
1515
1525
|
}
|
|
1516
1526
|
|
|
@@ -20,6 +20,13 @@ type VerificationCheckResult = {
|
|
|
20
20
|
message: string;
|
|
21
21
|
fail_type?: string;
|
|
22
22
|
warnings?: string[];
|
|
23
|
+
checkId?: string;
|
|
24
|
+
classification?: 'hard' | 'soft' | 'info';
|
|
25
|
+
effectiveStatus?: VerificationStatus;
|
|
26
|
+
reason?: string;
|
|
27
|
+
action?: string;
|
|
28
|
+
dependsOn?: string;
|
|
29
|
+
subchecks?: VerificationCheckResult[];
|
|
23
30
|
};
|
|
24
31
|
type VerificationContext = {
|
|
25
32
|
skillName: string;
|
package/lib/task/verification.ts
CHANGED
|
@@ -126,7 +126,7 @@ async function verifyTaskEvent(request: { taskRef: string; event: string; artifa
|
|
|
126
126
|
} else {
|
|
127
127
|
for (const check of spec.checks ?? []) {
|
|
128
128
|
const payload = await engine({ mode: 'checks', skillName: spec.skill, taskDir: resolved.taskDir, artifactFile: request.artifact, checks: [check], repositoryRoot: resolved.repoRoot });
|
|
129
|
-
const status = payload.status as 'pass' | 'fail' | 'blocked';
|
|
129
|
+
const status = (payload.effectiveStatus ?? payload.status) as 'pass' | 'fail' | 'blocked';
|
|
130
130
|
if (status !== 'pass' && allowsManualOverride(options.manualOverride, 'verification-engine', status === 'blocked' ? 'CHECK_BLOCKED' : 'CHECK_FAILED')) {
|
|
131
131
|
invocations.push({ status: 'pass', exitCode: 0, payload: { ...payload, status: 'pass', humanOverride: 'human-approved', originalStatus: status } });
|
|
132
132
|
break;
|
|
@@ -150,18 +150,34 @@ function statusLabel(status: unknown): string {
|
|
|
150
150
|
function renderPayload(payload: Record<string, unknown>): string {
|
|
151
151
|
const lines: string[] = [];
|
|
152
152
|
if (Array.isArray(payload.checks)) {
|
|
153
|
-
|
|
153
|
+
const gateMode = typeof payload.gate === 'string';
|
|
154
|
+
lines.push(gateMode
|
|
155
|
+
? `Verification: ${payload.gate} | Skill: ${payload.skill}`
|
|
156
|
+
: `Check: ${payload.status} | Skill: ${payload.skill} | Type: ${payload.type}`, '');
|
|
154
157
|
for (const check of payload.checks as Array<Record<string, unknown>>) {
|
|
155
|
-
|
|
158
|
+
const raw = statusLabel(check.status);
|
|
159
|
+
const effective = statusLabel(check.effectiveStatus ?? check.status);
|
|
160
|
+
const reason = check.reason ?? 'CHECK_FAILED';
|
|
161
|
+
const message = check.message ?? reason;
|
|
162
|
+
lines.push(` [${effective}] ${check.checkId ?? check.type} (${check.classification ?? 'hard'}; raw ${raw}; reason ${reason}) - ${message}; ${check.action ?? 'Review validation output'}`);
|
|
156
163
|
}
|
|
157
|
-
|
|
164
|
+
const summary = payload.summary ?? (() => {
|
|
165
|
+
const checks = payload.checks as Array<Record<string, unknown>>;
|
|
166
|
+
const statuses = checks.map((check) => check.effectiveStatus ?? check.status);
|
|
167
|
+
return `${statuses.filter((status) => status === 'pass').length} passed, ${statuses.filter((status) => status === 'fail').length} failed${statuses.includes('blocked') ? `, ${statuses.filter((status) => status === 'blocked').length} blocked` : ''}`;
|
|
168
|
+
})();
|
|
169
|
+
lines.push('', `Result: ${summary} - ${payload.action}`);
|
|
158
170
|
} else {
|
|
159
171
|
lines.push(`Check: ${payload.status} | Skill: ${payload.skill} | Type: ${payload.type}`, '');
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
172
|
+
const raw = statusLabel(payload.status);
|
|
173
|
+
const effective = statusLabel(payload.effectiveStatus ?? payload.status);
|
|
174
|
+
const reason = payload.reason ?? 'CHECK_FAILED';
|
|
175
|
+
lines.push(` [${effective}] ${payload.checkId ?? payload.type} (${payload.classification ?? 'hard'}; raw ${raw}; reason ${reason}) - ${payload.message ?? reason}; ${payload.action ?? 'Review validation output'}`);
|
|
176
|
+
const status = payload.effectiveStatus ?? payload.status;
|
|
177
|
+
const summary = status === 'pass' ? '1 passed, 0 failed'
|
|
178
|
+
: status === 'blocked' ? '0 passed, 0 failed, 1 blocked' : '0 passed, 1 failed';
|
|
179
|
+
const action = status === 'pass' ? 'Requested check passed'
|
|
180
|
+
: status === 'blocked' ? `Resolve blocked ${payload.type} check and re-run check`
|
|
165
181
|
: `Fix ${payload.type} issues and re-run check`;
|
|
166
182
|
lines.push('', `Result: ${summary} - ${action}`);
|
|
167
183
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fitlab-ai/agent-infra",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Antigravity CLI, and OpenCode",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,6 +39,8 @@ PR event `in:` synchronization uses `agent-infra-internal platform-pr sync-in-la
|
|
|
39
39
|
|
|
40
40
|
`planned|applied|no-op|degraded` exit 0; `failed` exits 1; `blocked` exits 2.
|
|
41
41
|
|
|
42
|
+
Lifecycle verification treats Issue Type, milestones, labels, requirement anchors, and noncritical comments as platform audits. Each audit retains its check id, raw status, reason, and action; missing structure, unavailable optional capability, or a value mismatch does not block a gate. Identity ambiguity, protocol conflicts, actual write failures, and unknown post-write state remain hard failures.
|
|
43
|
+
|
|
42
44
|
Map material degraded/failed/blocked results to workflow warnings through the structured intent; callers must not edit warning rows directly:
|
|
43
45
|
|
|
44
46
|
```bash
|
|
@@ -13,9 +13,6 @@
|
|
|
13
13
|
| `artifactChunk` | `<!-- sync-issue:{task-id}:{artifact-stem}:{part}/{total} -->` |
|
|
14
14
|
| `summary` | `<!-- sync-issue:{task-id}:summary -->` |
|
|
15
15
|
| `cancel` | `<!-- sync-issue:{task-id}:cancel -->` |
|
|
16
|
-
| `recoveryAction` | `<!-- sync-issue:{task-id}:recovery-action:{action-id} -->` |
|
|
17
|
-
| `recoveryPrepare` | `<!-- sync-issue:{task-id}:recovery-prepare:{commit-id} -->` |
|
|
18
|
-
| `recoveryCommit` | `<!-- sync-issue:{task-id}:recovery-commit:{commit-id} -->` |
|
|
19
16
|
|
|
20
17
|
`prSummary` 属于 `.agents/rules/pr-sync.md`,本规则不实现 PR 聚合。
|
|
21
18
|
|
|
@@ -32,15 +29,15 @@ agent-infra-internal platform-comment recover --issue <issue-token> --task-id <T
|
|
|
32
29
|
--output <.agents/workspace/.restore-staging-*/task.md> [--cwd <path>]
|
|
33
30
|
agent-infra-internal platform-comment owner <task-ref>
|
|
34
31
|
agent-infra-internal platform-comment sync <task-ref> \
|
|
35
|
-
--kind task|artifact|summary|cancel
|
|
32
|
+
--kind task|artifact|summary|cancel --agent {standard-agent-token} \
|
|
36
33
|
[--artifact <canonical.md>] [--body-file <path|->] [--backfill]
|
|
37
34
|
```
|
|
38
35
|
|
|
39
36
|
- `applied|no-op|degraded` → exit 0;`failed` → exit 1;`blocked` → exit 2。
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
- 生命周期验证把 Issue Type、milestone、labels、需求锚点和非关键评论作为平台审计。每条审计保留 check id、原始状态、reason 和 action;缺失、权限不足或值不一致不会阻塞 gate。身份歧义、协议冲突、实际写入失败和写后状态未知仍为硬失败。
|
|
38
|
+
- task 评论保持 `<details>` frontmatter 可逆格式,只同步确定性的当前任务投影,并折叠保留创建任务、人工决策等关联动作。artifact 评论在正文前折叠显示该产物动作及其提交记录;交付摘要保留创建 PR 与完成任务记录。每条评论的元数据可包含多条日志。恢复核心从这些元数据重建活动日志,绝不把完整 `task.md` 作为评论载荷保存。artifact 原文内联并在超过 profile 上限时使用 `artifactChunk`。
|
|
39
|
+
- 长度预检与 platform verification 使用同一最终渲染正文的 UTF-8 字节数。正文超限时失败关闭;本地 `task.md` 不会被截断。
|
|
40
|
+
- 恢复元数据包含动作关联的日志条目和校验摘要。restore 只接受与 task 评论同作者、任务身份匹配且校验通过的元数据;缺失或损坏的记录不得推测。
|
|
44
41
|
- 相同 intent 重放必须收敛为 `no-op`;重复 marker 返回 `COMMENT_MARKER_CONFLICT` 且不写入。
|
|
45
42
|
- 外部贡献者锁定统一使用 `platform-comment owner`;不同作者且无 triage 时返回 `COMMENT_OWNER_CONFLICT`。
|
|
46
43
|
|
|
@@ -11,6 +11,14 @@ This rule covers the pre-completion gate for `analyze-task`, `plan-task`, and `c
|
|
|
11
11
|
- Preflight publishes active `R` through `preflight-ready → preflight-commit-started → preflight-passed`; the business finalizer publishes `F` through `full-finalizer-ready → commit-started → passed` and reuses `R` when `F=R`.
|
|
12
12
|
- Candidate-only is a protocol authorization boundary, not OS isolation: a same-UID process with arbitrary host filesystem write access may tamper with recovery internals. Identity, fingerprint, and state checks detect such anomalies and fail closed, but the protocol does not claim an independent security principal or cross-platform isolation.
|
|
13
13
|
|
|
14
|
+
## Recovery continuation context
|
|
15
|
+
|
|
16
|
+
Whenever a preflight or finalizer returns `recovery`, bind the complete continuation context from that response for the current execution: `taskRef`, `stage/family`, `artifact`, `recoveryId`, `candidatePath`, baseline digests, and the original entry point. These fields belong to one controlled transaction; do not regenerate, guess, or mix any of them for a later call.
|
|
17
|
+
|
|
18
|
+
- For a preflight failure, edit only that `candidatePath`, then rerun the same preflight entry point with the same `--recovery-id`. Only the successful response's recovery context may proceed to ledger writes or summary/finalization.
|
|
19
|
+
- For a finalizer failure, edit only that `candidatePath`, then rerun that same finalizer entry point with the same `--recovery-id`.
|
|
20
|
+
- Stop when the context is lost, the tuple differs, or the formal artifact was edited directly. A fresh invocation without `--recovery-id` cannot replace recovery, and a formal artifact is never a candidate.
|
|
21
|
+
|
|
14
22
|
## Authorization boundary
|
|
15
23
|
|
|
16
24
|
- The finalizer and recovery core validate identity, state, permissions, stable reads, complete artifact semantics, and fingerprints. They do not infer repairability or expose a text-operation allow-list.
|
|
@@ -45,9 +53,9 @@ The intent is current-only schema version 4. Legacy schemas fail closed; do not
|
|
|
45
53
|
## Dynamic convergence loop
|
|
46
54
|
|
|
47
55
|
1. Run the finalizer with the fixed invocation.
|
|
48
|
-
2.
|
|
49
|
-
3. Confirm byte-level progress and rerun every finalizer check with the same `--recovery-id
|
|
50
|
-
4. Stop on repeated diagnostics or fingerprints, no byte progress, unknown recovery state, or the eight-edit limit for the current invocation. Do not publish a completed event or generate a cross-stage next step.
|
|
56
|
+
2. On every failure that passes the gates, read the structured diagnostic and `candidatePath`, then make only one minimal, explainable candidate edit.
|
|
57
|
+
3. Confirm byte-level progress and rerun every finalizer check with the same `--recovery-id`; if it still fails with a new diagnostic and fingerprint, return to step 2.
|
|
58
|
+
4. Stop on repeated diagnostics or fingerprints, no byte progress, unknown recovery state, an unsafe repair, or the eight-edit limit for the current invocation. Do not publish a completed event or generate a cross-stage next step.
|
|
51
59
|
|
|
52
60
|
## Shared entry points
|
|
53
61
|
|
|
@@ -12,6 +12,14 @@
|
|
|
12
12
|
- preflight-ready 后 publish 只读取 active/pending generation,绝不再读取可编辑 candidate。
|
|
13
13
|
- candidate-only 是协议授权边界,不是操作系统隔离:拥有同一 UID 且可任意写入宿主文件系统的进程可能篡改 recovery 内部文件;协议会通过身份、指纹和状态校验发现异常并失败关闭,但不承诺独立权限主体或跨平台隔离。
|
|
14
14
|
|
|
15
|
+
## 恢复续办上下文
|
|
16
|
+
|
|
17
|
+
任一 preflight 或 finalizer 返回 `recovery` 时,立即在本次执行中绑定该响应的完整续办上下文:`taskRef`、`stage/family`、`artifact`、`recoveryId`、`candidatePath`、baseline digest 和原入口。它们属于同一受控事务,后续调用不得重新生成、猜测或混用其中任一字段。
|
|
18
|
+
|
|
19
|
+
- 失败来自 preflight:只编辑该 `candidatePath` 后,以相同入口和同一 `--recovery-id` 重跑 preflight;只有成功响应中的 recovery context 才能进入后续账本写入或 summary/finalizer。
|
|
20
|
+
- 失败来自 finalizer:只编辑该 `candidatePath` 后,以相同入口和同一 `--recovery-id` 重跑该 finalizer。
|
|
21
|
+
- 上下文丢失、tuple 不匹配或正式 artifact 已被直接修改时停止;不得以省略 `--recovery-id` 的新调用替代恢复,也不得把正式 artifact 当作 candidate。
|
|
22
|
+
|
|
15
23
|
## 授权边界
|
|
16
24
|
|
|
17
25
|
- finalizer 和 recovery core 只校验身份、状态、权限、稳定读取、完整 artifact 语义和指纹;不根据错误码猜测“可修复”,也不提供文本操作白名单。
|
|
@@ -46,9 +54,9 @@ intent 使用 current-only schema version 4。旧 schema 直接失败关闭;
|
|
|
46
54
|
## 动态收敛循环
|
|
47
55
|
|
|
48
56
|
1. 用固定 invocation 运行 finalizer。
|
|
49
|
-
2.
|
|
50
|
-
3. 确认字节变化后,使用同一 `--recovery-id` 完整重跑全部 finalizer
|
|
51
|
-
4.
|
|
57
|
+
2. 每次失败且安全门通过时,读取结构化诊断和 `candidatePath`,仅作一次最小、可解释的候选编辑。
|
|
58
|
+
3. 确认字节变化后,使用同一 `--recovery-id` 完整重跑全部 finalizer 校验;仍失败但诊断和指纹均未重复时,回到第 2 步。
|
|
59
|
+
4. 诊断或指纹重复、无字节进展、恢复状态未知、无法安全修复或达到当前 invocation 的 8 次编辑上限时停止;不发布 completed,不生成跨阶段 next-step。
|
|
52
60
|
|
|
53
61
|
## 共享入口
|
|
54
62
|
|
|
@@ -223,8 +223,8 @@ agent-infra-internal task-artifact {task-id} finalize-local --family analysis --
|
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
- On `status=passed`, save that result's `artifactSha256` and `semanticDigest`; the finalizer has recorded the matching one-shot local provenance intent.
|
|
226
|
-
- On `status=failed` with recovery context, edit
|
|
227
|
-
- The recovery candidate must match the recorded task, round, artifact, baseline, and request identity. On baseline conflict, unknown state, no progress, or
|
|
226
|
+
- On `status=failed` with recovery context, after the completion gates pass, edit the returned `candidatePath` only once for this attempt, then rerun the finalizer completely with the same `recoveryId`; if it still fails with a new diagnostic and fingerprint while the gates continue to pass, continue to the next attempt; the formal artifact must remain unchanged until commit.
|
|
227
|
+
- The recovery candidate must match the recorded task, round, artifact, baseline, and request identity. On baseline conflict, unknown state, an unsafe repair, repeated diagnostics or fingerprints, no progress, or the shared edit limit, stop without publishing a completed event.
|
|
228
228
|
|
|
229
229
|
Use the digests from that same `status=passed` result in `agent-infra-internal task-event {task-id} analyze.completed --agent {standard-agent-token} --initiator {trigger-initiator} --request-id {request-id} --reason-code {reason-code} --artifact {analysis-artifact} --artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest} {execution-flag}` so the core records the link, stage, agent, metadata, and Activity Log atomically.
|
|
230
230
|
- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Analyze Task (Round {N})** by {agent} — Analysis completed → {analysis-artifact}
|
|
@@ -226,8 +226,8 @@ agent-infra-internal task-artifact {task-id} init --family analysis --artifact {
|
|
|
226
226
|
agent-infra-internal task-artifact {task-id} finalize-local --family analysis --artifact {analysis-artifact}
|
|
227
227
|
```
|
|
228
228
|
- `status=passed`:保存本次返回的 `artifactSha256` 和 `semanticDigest`;finalizer 已记录对应的一次性本地 provenance intent。
|
|
229
|
-
- `status=failed` 且返回 recovery context
|
|
230
|
-
- recovery candidate 必须与记录的任务、轮次、产物、baseline 和 request identity
|
|
229
|
+
- `status=failed` 且返回 recovery context:完成门禁通过后,本次只编辑返回的 `candidatePath` 一次,然后使用同一个 `recoveryId` 完整重跑 finalizer;若仍失败但诊断和指纹均未重复且安全门继续通过,继续下一轮;formal artifact 在 commit 前必须保持不变。
|
|
230
|
+
- recovery candidate 必须与记录的任务、轮次、产物、baseline 和 request identity 匹配;基线冲突、未知状态、无法安全修复、诊断或指纹重复、无进展,或达到共享规则的编辑上限时停止,不发布 completed 事件。
|
|
231
231
|
- 使用同一次 `status=passed` 返回的摘要执行 `agent-infra-internal task-event {task-id} analyze.completed --agent {standard-agent-token} --initiator {trigger-initiator} --request-id {request-id} --reason-code {reason-code} --artifact {analysis-artifact} --artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest} {execution-flag}`,由核心登记链接、阶段、代理、时间、版本和 Activity Log。
|
|
232
232
|
|
|
233
233
|
如果 task.md 中存在有效的 `platform_issue_identity`,执行以下同步操作(任一失败则跳过并继续):
|
|
@@ -24,16 +24,7 @@
|
|
|
24
24
|
"expected_action_pattern": "(Analyze Task|Requirement Analysis) \\(Round \\d+\\)"
|
|
25
25
|
},
|
|
26
26
|
"platform-sync": {
|
|
27
|
-
"when": "platform_issue_identity_exists"
|
|
28
|
-
"expected_status_label": "status: pending-design-work",
|
|
29
|
-
"expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
|
|
30
|
-
"verify_comment_content": true,
|
|
31
|
-
"verify_task_comment_content": true,
|
|
32
|
-
"verify_issue_type": true,
|
|
33
|
-
"verify_issue_fields": false,
|
|
34
|
-
"verify_milestone": true,
|
|
35
|
-
"expected_status_label_key": "pendingDesignWork",
|
|
36
|
-
"expected_comment_marker_key": "artifact"
|
|
27
|
+
"when": "platform_issue_identity_exists"
|
|
37
28
|
}
|
|
38
29
|
}
|
|
39
30
|
}
|
|
@@ -24,16 +24,7 @@
|
|
|
24
24
|
"expected_action_pattern": "(Analyze Task|Requirement Analysis) \\(Round \\d+\\)"
|
|
25
25
|
},
|
|
26
26
|
"platform-sync": {
|
|
27
|
-
"when": "platform_issue_identity_exists"
|
|
28
|
-
"expected_status_label": "status: pending-design-work",
|
|
29
|
-
"expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
|
|
30
|
-
"verify_comment_content": true,
|
|
31
|
-
"verify_task_comment_content": true,
|
|
32
|
-
"verify_issue_type": true,
|
|
33
|
-
"verify_issue_fields": false,
|
|
34
|
-
"verify_milestone": true,
|
|
35
|
-
"expected_status_label_key": "pendingDesignWork",
|
|
36
|
-
"expected_comment_marker_key": "artifact"
|
|
27
|
+
"when": "platform_issue_identity_exists"
|
|
37
28
|
}
|
|
38
29
|
}
|
|
39
30
|
}
|
|
@@ -21,9 +21,7 @@
|
|
|
21
21
|
"expected_action_pattern": "(Block Task|Blocked)"
|
|
22
22
|
},
|
|
23
23
|
"platform-sync": {
|
|
24
|
-
"when": "platform_issue_identity_exists"
|
|
25
|
-
"expected_status_label": "status: blocked",
|
|
26
|
-
"expected_status_label_key": "blocked"
|
|
24
|
+
"when": "platform_issue_identity_exists"
|
|
27
25
|
}
|
|
28
26
|
}
|
|
29
27
|
}
|
|
@@ -22,10 +22,7 @@
|
|
|
22
22
|
"expected_action_pattern": "(Cancel Task|Cancelled)"
|
|
23
23
|
},
|
|
24
24
|
"platform-sync": {
|
|
25
|
-
"when": "platform_issue_identity_exists"
|
|
26
|
-
"expected_comment_marker": "<!-- sync-issue:{task-id}:cancel -->",
|
|
27
|
-
"verify_task_comment_content": true,
|
|
28
|
-
"expected_comment_marker_key": "cancel"
|
|
25
|
+
"when": "platform_issue_identity_exists"
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
28
|
}
|
|
@@ -122,7 +122,7 @@ Before writing this round's `{code-artifact}`, create the controlled report skel
|
|
|
122
122
|
agent-infra-internal task-artifact {task-id} init --family code --artifact {code-artifact} --locale en
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
The skeleton contains identity metadata, stable section markers, and required headings only; real implementation and verification content is required before the completion gate can pass.
|
|
125
|
+
The skeleton contains identity metadata, stable section markers, and required headings only; real implementation and verification content is required before the completion gate can pass. When preflight or finalization returns one provably safe structural error, it returns a controlled recovery candidate; edit only its `candidatePath`, then retain the same recovery context and rerun the entry point that returned it, as specified by `.agents/rules/local-artifact-repair.md`. Candidate-only is a protocol authorization boundary, not OS isolation; arbitrary same-UID host writers are outside the protocol's protection claim, and fingerprint/state checks fail closed on anomalies.
|
|
126
126
|
|
|
127
127
|
Create `.agents/workspace/active/{task-id}/{code-artifact}`.
|
|
128
128
|
|
|
@@ -139,8 +139,8 @@ echo "$finalizer"
|
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
- `status=0` with `finalizer.status="passed"`: bind `{artifact-sha256}` and `{semantic-digest}` from this result.
|
|
142
|
-
- `status=1` with recovery context: confirm task, round, artifact, baseline, and request identity are unchanged; edit
|
|
143
|
-
- For any other failure, external formal-artifact change, lack of progress, or recovery identity mismatch, stop without publishing `code.completed`.
|
|
142
|
+
- `status=1` with recovery context: confirm task, round, artifact, baseline, and request identity are unchanged; edit the returned `candidatePath` only once for this attempt, confirm the bytes changed, then rerun the entry point that returned the context completely with the same `recoveryId`; a failed preflight reruns preflight and a failed finalizer reruns that finalizer. If it still fails with a new diagnostic and fingerprint while the gates continue to pass, continue to the next attempt; `baseline`, `final`, `publish`, and `intent` remain framework-internal state and must not be edited.
|
|
143
|
+
- For any other failure, external formal-artifact change, an unsafe repair, repeated diagnostics or fingerprints, lack of progress, the shared edit limit, or recovery identity mismatch, stop without publishing `code.completed`.
|
|
144
144
|
|
|
145
145
|
Do not rescan or manually write digest data; the completion event must include `--artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest}` from the successful finalizer result.
|
|
146
146
|
|
|
@@ -162,7 +162,7 @@ checkpoint 成功后,若任务存在 `platform_issue_identity`,调用 `agent
|
|
|
162
162
|
agent-infra-internal task-artifact {task-id} init --family code --artifact {code-artifact}
|
|
163
163
|
```
|
|
164
164
|
|
|
165
|
-
骨架只包含身份元数据、稳定 section marker 和必需标题;必须填入真实实现与验证内容后才能通过完成门禁。finalizer 返回可证明的单个结构错误时,会返回受控 recovery candidate;只能编辑返回的 `candidatePath
|
|
165
|
+
骨架只包含身份元数据、稳定 section marker 和必需标题;必须填入真实实现与验证内容后才能通过完成门禁。preflight 或 finalizer 返回可证明的单个结构错误时,会返回受控 recovery candidate;只能编辑返回的 `candidatePath`,并按 `.agents/rules/local-artifact-repair.md` 保持同一 recovery context 后重跑返回该 context 的原入口。candidate-only 是协议授权边界,不是操作系统隔离;同 UID 的任意宿主写入者不在本协议的防护承诺内,异常由指纹/状态校验失败关闭。
|
|
166
166
|
|
|
167
167
|
创建 `.agents/workspace/active/{task-id}/{code-artifact}`。
|
|
168
168
|
|
|
@@ -179,8 +179,8 @@ echo "$finalizer"
|
|
|
179
179
|
```
|
|
180
180
|
|
|
181
181
|
- `status=0` 且 `finalizer.status="passed"`:绑定这一次返回的 `{artifact-sha256}` 和 `{semantic-digest}`。
|
|
182
|
-
- `status=1` 且返回 recovery context:确认任务、轮次、产物、baseline 和 request identity
|
|
183
|
-
- 其他失败、formal artifact
|
|
182
|
+
- `status=1` 且返回 recovery context:确认任务、轮次、产物、baseline 和 request identity 未变化后,本次只编辑返回的 `candidatePath` 一次,确认字节确实变化,再使用同一个 `recoveryId` 完整重跑返回该 context 的同一入口;preflight 失败必须重跑 preflight,finalizer 失败必须重跑 finalizer。若仍失败但诊断和指纹均未重复且安全门继续通过,继续下一轮;baseline、final、publish 和 intent 均属于框架内部状态,不得编辑。
|
|
183
|
+
- 其他失败、formal artifact 外部变化、无法安全修复、诊断或指纹重复、无进展、达到共享规则的编辑上限或 recovery identity 不匹配:停止,不发布 `code.completed`。
|
|
184
184
|
|
|
185
185
|
不得重新扫描或手工补写摘要;完成事件必须携带本次 `passed` 结果的 `--artifact-sha256 {artifact-sha256} --semantic-digest {semantic-digest}`。
|
|
186
186
|
|
|
@@ -30,18 +30,7 @@
|
|
|
30
30
|
]
|
|
31
31
|
},
|
|
32
32
|
"platform-sync": {
|
|
33
|
-
"when": "platform_issue_identity_exists"
|
|
34
|
-
"expected_status_label": "status: in-progress",
|
|
35
|
-
"expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
|
|
36
|
-
"verify_comment_content": true,
|
|
37
|
-
"verify_task_comment_content": true,
|
|
38
|
-
"verify_issue_type": true,
|
|
39
|
-
"verify_issue_fields": false,
|
|
40
|
-
"verify_in_labels_computed": true,
|
|
41
|
-
"verify_milestone": true,
|
|
42
|
-
"verify_milestone_specific": true,
|
|
43
|
-
"expected_status_label_key": "inProgress",
|
|
44
|
-
"expected_comment_marker_key": "artifact"
|
|
33
|
+
"when": "platform_issue_identity_exists"
|
|
45
34
|
}
|
|
46
35
|
}
|
|
47
36
|
}
|
|
@@ -30,18 +30,7 @@
|
|
|
30
30
|
]
|
|
31
31
|
},
|
|
32
32
|
"platform-sync": {
|
|
33
|
-
"when": "platform_issue_identity_exists"
|
|
34
|
-
"expected_status_label": "status: in-progress",
|
|
35
|
-
"expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
|
|
36
|
-
"verify_comment_content": true,
|
|
37
|
-
"verify_task_comment_content": true,
|
|
38
|
-
"verify_issue_type": true,
|
|
39
|
-
"verify_issue_fields": false,
|
|
40
|
-
"verify_in_labels_computed": true,
|
|
41
|
-
"verify_milestone": true,
|
|
42
|
-
"verify_milestone_specific": true,
|
|
43
|
-
"expected_status_label_key": "inProgress",
|
|
44
|
-
"expected_comment_marker_key": "artifact"
|
|
33
|
+
"when": "platform_issue_identity_exists"
|
|
45
34
|
}
|
|
46
35
|
}
|
|
47
36
|
}
|
|
@@ -10,7 +10,7 @@ agent-infra-internal task-artifact {task-id} inspect --family code
|
|
|
10
10
|
|
|
11
11
|
The core scans `plan.md` / `plan-r{N}.md`, `review-plan.md` / `review-plan-r{N}.md`, `code.md` / `code-r{N}.md`, and `review-code.md` / `review-code-r{N}.md` in the task directory.
|
|
12
12
|
|
|
13
|
-
`code.started` persists the plan identity and SHA-256 for the round in task.md frontmatter. `code.completed`
|
|
13
|
+
`code.started` persists the plan identity and SHA-256 for the round in task.md frontmatter. `code.completed` uses that start context and verifies the current latest plan; changed input fails closed. The implementation report's `Plan Input` field is reader-facing traceability, not lifecycle identity validation.
|
|
14
14
|
|
|
15
15
|
## Eight Branches
|
|
16
16
|
|
|
@@ -10,7 +10,7 @@ agent-infra-internal task-artifact {task-id} inspect --family code
|
|
|
10
10
|
|
|
11
11
|
核心扫描任务目录中的 `plan.md` / `plan-r{N}.md`、`review-plan.md` / `review-plan-r{N}.md`、`code.md` / `code-r{N}.md` 和 `review-code.md` / `review-code-r{N}.md`。
|
|
12
12
|
|
|
13
|
-
`code.started` 会在 task.md frontmatter 中绑定本轮方案文件及其 SHA-256。`code.completed`
|
|
13
|
+
`code.started` 会在 task.md frontmatter 中绑定本轮方案文件及其 SHA-256。`code.completed` 使用该开始上下文并校验当前最新 plan;内容变化失败关闭。实现报告的“方案输入”/“Plan Input”仅供读者追溯,不参与生命周期身份校验。
|
|
14
14
|
|
|
15
15
|
## 8 个分支
|
|
16
16
|
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Use this structure when creating `code.md` or `code-r{N}.md`.
|
|
6
6
|
|
|
7
|
+
> Implementation-input fields provide reader-facing traceability. Lifecycle identity uses the input frozen by `code.started` and the completion receipt; it is not parsed from this report body.
|
|
8
|
+
|
|
7
9
|
## Output Template
|
|
8
10
|
|
|
9
11
|
```markdown
|
|
@@ -103,6 +105,15 @@ Use this structure when creating `code.md` or `code-r{N}.md`.
|
|
|
103
105
|
> Record the state-check command, task/artifact scope, key result, and uncovered parts; each command starts with `$ `.
|
|
104
106
|
> Follow `.agents/rules/evidence-reporting.md`: record task/artifact scope, key result, and uncovered parts; do not paste complete successful stdout.
|
|
105
107
|
|
|
108
|
+
Record at least one actually executed `$ ` command and its result summary; prose-only status is insufficient. An implementation-stage report normally includes:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
$ agent-infra-internal task-snapshot {task-id} --format text
|
|
112
|
+
{task state, implementation-artifact scope, and uncovered-area summary}
|
|
113
|
+
$ agent-infra-internal task-artifact {task-id} inspect --family code
|
|
114
|
+
{code artifact, upstream input, and next-step summary}
|
|
115
|
+
```
|
|
116
|
+
|
|
106
117
|
## Raw Evidence
|
|
107
118
|
|
|
108
119
|
> Follow `.agents/rules/evidence-reporting.md`: pair each claim with a `$ ` command and proportionate result summary; include a decisive raw excerpt only for failures, blocking conditions, or disputes.
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
创建 `code.md` 或 `code-r{N}.md` 时,使用以下结构。
|
|
6
6
|
|
|
7
|
+
> “实现输入”字段用于读者追溯。生命周期身份以 `code.started` 冻结的输入和完成 receipt 为准,不从本报告正文解析。
|
|
8
|
+
|
|
7
9
|
## 输出模板
|
|
8
10
|
|
|
9
11
|
```markdown
|
|
@@ -103,6 +105,15 @@
|
|
|
103
105
|
> 记录状态核对命令、任务/产物范围、关键结果和未覆盖部分;每条命令以 `$ ` 开头。
|
|
104
106
|
> 按 `.agents/rules/evidence-reporting.md` 同时记录任务/产物范围、关键结果和未覆盖部分;正常成功不粘贴完整 stdout。
|
|
105
107
|
|
|
108
|
+
必须记录至少一条实际执行的 `$ ` 命令及其结果摘要,不能只写自然语言状态。实现阶段通常包括:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
$ agent-infra-internal task-snapshot {task-id} --format text
|
|
112
|
+
{任务状态、实现产物范围和未覆盖项摘要}
|
|
113
|
+
$ agent-infra-internal task-artifact {task-id} inspect --family code
|
|
114
|
+
{code artifact、上游输入和下一步摘要}
|
|
115
|
+
```
|
|
116
|
+
|
|
106
117
|
## 证据原文
|
|
107
118
|
|
|
108
119
|
> 遵循 `.agents/rules/evidence-reporting.md`:每条断言配对 `$ ` 命令和相称结果摘要;仅为失败、阻塞或争议附决定性原文摘录。
|
|
@@ -18,11 +18,7 @@
|
|
|
18
18
|
"expected_action_pattern": "Commit"
|
|
19
19
|
},
|
|
20
20
|
"platform-sync": {
|
|
21
|
-
"when": "pr_fact_bound"
|
|
22
|
-
"expected_pr_comment_marker": "<!-- sync-pr:{task-id}:summary -->",
|
|
23
|
-
"verify_in_labels_computed": true,
|
|
24
|
-
"verify_pr_comment_last_commit_matches_head": true,
|
|
25
|
-
"expected_pr_comment_marker_key": "prSummary"
|
|
21
|
+
"when": "pr_fact_bound"
|
|
26
22
|
}
|
|
27
23
|
}
|
|
28
24
|
}
|
|
@@ -31,17 +31,17 @@
|
|
|
31
31
|
"expected_action_pattern": "Complete Manual Validation"
|
|
32
32
|
},
|
|
33
33
|
"review-ledger": {
|
|
34
|
-
"stage_scope": [
|
|
34
|
+
"stage_scope": [
|
|
35
|
+
"analysis",
|
|
36
|
+
"plan",
|
|
37
|
+
"code"
|
|
38
|
+
]
|
|
35
39
|
},
|
|
36
40
|
"platform-sync": {
|
|
37
41
|
"when": "pr_fact_bound",
|
|
38
|
-
"expected_pr_comment_marker_key": "prSummary",
|
|
39
42
|
"expected_pr_comment_required_patterns": [
|
|
40
43
|
"^### ✅ (?:人工验证已通过|Manual Validation Passed)$"
|
|
41
|
-
]
|
|
42
|
-
"verify_task_comment_content": true,
|
|
43
|
-
"verify_issue_type": true,
|
|
44
|
-
"verify_issue_fields": false
|
|
44
|
+
]
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|