@fitlab-ai/agent-infra 0.9.13 → 0.9.14
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/bin/cli.ts +26 -9
- package/dist/bin/cli.js +173 -157
- package/dist/bin/internal-cli.js +42 -21
- package/dist/lib/agent-client.js +5 -0
- package/dist/lib/internal/agent-client.js +5 -2
- package/dist/lib/internal/cli-route-inventory.js +152 -0
- package/dist/lib/internal/codex-lifecycle.js +9 -6
- package/dist/lib/internal/codex-sandbox-controller.js +8 -2
- package/dist/lib/internal/git-workflow.js +10 -6
- package/dist/lib/internal/platform-checks.js +16 -4
- package/dist/lib/internal/platform-comment.js +16 -4
- package/dist/lib/internal/platform-context.js +4 -1
- package/dist/lib/internal/platform-issue.js +12 -4
- package/dist/lib/internal/platform-metadata.js +88 -0
- package/dist/lib/internal/platform-pr-review.js +16 -3
- package/dist/lib/internal/platform-pr.js +24 -10
- package/dist/lib/internal/platform-release-notes.js +6 -3
- package/dist/lib/internal/platform-security.js +93 -0
- package/dist/lib/internal/pr-review-grade.js +14 -3
- package/dist/lib/internal/release-workflow.js +19 -5
- package/dist/lib/internal/sandbox-control.js +22 -5
- package/dist/lib/internal/task-activity.js +13 -4
- package/dist/lib/internal/task-artifact.js +186 -27
- package/dist/lib/internal/task-context.js +4 -1
- package/dist/lib/internal/task-create.js +48 -15
- package/dist/lib/internal/task-delivery.js +4 -1
- package/dist/lib/internal/task-event.js +4 -1
- package/dist/lib/internal/task-finalization.js +4 -1
- package/dist/lib/internal/task-invalidation.js +4 -1
- package/dist/lib/internal/task-ledger.js +12 -1
- package/dist/lib/internal/task-lifecycle.js +4 -1
- package/dist/lib/internal/task-operation-registry.js +421 -0
- package/dist/lib/internal/task-orchestration.js +12 -0
- package/dist/lib/internal/task-override.js +10 -3
- package/dist/lib/internal/task-qualification.js +90 -0
- package/dist/lib/internal/task-review.js +4 -1
- package/dist/lib/internal/task-short-id.js +11 -1
- package/dist/lib/internal/task-snapshot.js +4 -1
- package/dist/lib/internal/task-validate.js +7 -2
- package/dist/lib/internal/task-verify.js +5 -1
- package/dist/lib/internal/task-warning.js +8 -1
- package/dist/lib/platform/comment-safety.js +226 -0
- package/dist/lib/platform/github-provider.js +233 -6
- package/dist/lib/platform/issue-comments.js +146 -34
- package/dist/lib/platform/pr-change-report.js +6 -12
- package/dist/lib/platform/pr-summary.js +28 -7
- package/dist/lib/platform/provider-contract.d.ts +67 -1
- package/dist/lib/platform/provider-contract.js +6 -2
- package/dist/lib/platform/provider-validation.js +76 -3
- package/dist/lib/platform/pull-requests.js +115 -170
- package/dist/lib/platform/repository-metadata.js +377 -0
- package/dist/lib/platform/security-alerts.js +155 -0
- package/dist/lib/platform/verification-sync.js +33 -26
- package/dist/lib/process-data/index.js +7 -0
- package/dist/lib/run/index.js +5 -0
- package/dist/lib/sandbox/commands/control-status.js +22 -0
- package/dist/lib/sandbox/commands/create.js +32 -6
- package/dist/lib/sandbox/commands/ls.js +5 -0
- package/dist/lib/sandbox/commands/rm.js +827 -120
- package/dist/lib/sandbox/commands/show.js +16 -0
- package/dist/lib/sandbox/control/client.js +83 -9
- package/dist/lib/sandbox/control/completed-reentry.js +85 -0
- package/dist/lib/sandbox/control/container-identity.js +28 -31
- package/dist/lib/sandbox/control/executor.js +149 -14
- package/dist/lib/sandbox/control/lifecycle.js +621 -127
- package/dist/lib/sandbox/control/native-file-lock.js +177 -0
- package/dist/lib/sandbox/control/server.js +305 -35
- package/dist/lib/sandbox/control/state.js +5 -3
- package/dist/lib/sandbox/control/task-view.js +183 -0
- package/dist/lib/sandbox/engines/authority.js +289 -0
- package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
- package/dist/lib/sandbox/index.js +5 -0
- package/dist/lib/sandbox/recovery.js +21 -1
- package/dist/lib/sandbox/workspace-view.js +2 -1
- package/dist/lib/sandbox/worktree-safety.js +4 -1
- package/dist/lib/server/index.js +8 -0
- package/dist/lib/task/artifact-lifecycle.js +42 -13
- package/dist/lib/task/artifact-operations.js +520 -0
- package/dist/lib/task/artifact-repair-intent.js +59 -0
- package/dist/lib/task/artifact-schema.js +135 -0
- package/dist/lib/task/capabilities.js +72 -1
- package/dist/lib/task/control-authority.js +4 -0
- package/dist/lib/task/create-service.js +103 -4
- package/dist/lib/task/create.js +25 -0
- package/dist/lib/task/events.js +186 -67
- package/dist/lib/task/index.js +11 -3
- package/dist/lib/task/local-artifact-finalization.js +75 -150
- package/dist/lib/task/orchestration.js +192 -52
- package/dist/lib/task/qualification-audit.js +490 -0
- package/dist/lib/task/qualification-confirmation.js +109 -0
- package/dist/lib/task/qualification-intents.js +148 -0
- package/dist/lib/task/review-artifacts.js +22 -23
- package/dist/lib/task/review-finalization.js +121 -4
- package/dist/lib/task/sections.js +6 -4
- package/dist/lib/task/verification-config.js +11 -0
- package/dist/lib/task/verification-engine.js +54 -4
- package/dist/lifecycle-build-manifest.json +3 -3
- package/lib/agent-client.ts +9 -0
- package/lib/internal/agent-client.ts +4 -2
- package/lib/internal/cli-route-inventory.ts +140 -0
- package/lib/internal/codex-lifecycle.ts +8 -6
- package/lib/internal/codex-sandbox-controller.ts +7 -2
- package/lib/internal/git-workflow.ts +9 -6
- package/lib/internal/platform-checks.ts +12 -4
- package/lib/internal/platform-comment.ts +12 -4
- package/lib/internal/platform-context.ts +3 -1
- package/lib/internal/platform-issue.ts +11 -4
- package/lib/internal/platform-metadata.ts +70 -0
- package/lib/internal/platform-pr-review.ts +14 -3
- package/lib/internal/platform-pr.ts +23 -10
- package/lib/internal/platform-release-notes.ts +5 -3
- package/lib/internal/platform-security.ts +83 -0
- package/lib/internal/pr-review-grade.ts +10 -3
- package/lib/internal/release-workflow.ts +17 -5
- package/lib/internal/sandbox-control.ts +19 -5
- package/lib/internal/task-activity.ts +12 -4
- package/lib/internal/task-artifact.ts +164 -25
- package/lib/internal/task-context.ts +3 -1
- package/lib/internal/task-create.ts +76 -15
- package/lib/internal/task-delivery.ts +3 -1
- package/lib/internal/task-event.ts +3 -1
- package/lib/internal/task-finalization.ts +3 -1
- package/lib/internal/task-invalidation.ts +3 -1
- package/lib/internal/task-ledger.ts +11 -1
- package/lib/internal/task-lifecycle.ts +3 -1
- package/lib/internal/task-operation-registry.ts +482 -0
- package/lib/internal/task-orchestration.ts +12 -0
- package/lib/internal/task-override.ts +9 -3
- package/lib/internal/task-qualification.ts +61 -0
- package/lib/internal/task-review.ts +3 -1
- package/lib/internal/task-short-id.ts +10 -1
- package/lib/internal/task-snapshot.ts +3 -1
- package/lib/internal/task-validate.ts +6 -2
- package/lib/internal/task-verify.ts +4 -1
- package/lib/internal/task-warning.ts +7 -1
- package/lib/platform/comment-safety.ts +250 -0
- package/lib/platform/github-provider.ts +229 -7
- package/lib/platform/issue-comments.ts +160 -35
- package/lib/platform/pr-change-report.ts +6 -12
- package/lib/platform/pr-summary.ts +27 -6
- package/lib/platform/provider-contract.ts +78 -3
- package/lib/platform/provider-validation.ts +85 -3
- package/lib/platform/pull-requests.ts +126 -178
- package/lib/platform/repository-metadata.ts +453 -0
- package/lib/platform/security-alerts.ts +191 -0
- package/lib/platform/verification-sync.ts +32 -28
- package/lib/process-data/index.ts +7 -0
- package/lib/run/index.ts +5 -0
- package/lib/sandbox/commands/control-status.ts +26 -0
- package/lib/sandbox/commands/create.ts +46 -6
- package/lib/sandbox/commands/ls.ts +7 -0
- package/lib/sandbox/commands/rm.ts +1000 -87
- package/lib/sandbox/commands/show.ts +16 -0
- package/lib/sandbox/control/client.ts +103 -9
- package/lib/sandbox/control/completed-reentry.ts +98 -0
- package/lib/sandbox/control/container-identity.ts +27 -43
- package/lib/sandbox/control/executor.ts +177 -12
- package/lib/sandbox/control/lifecycle.ts +629 -17
- package/lib/sandbox/control/native-file-lock.ts +209 -0
- package/lib/sandbox/control/protocol.ts +5 -2
- package/lib/sandbox/control/server.ts +319 -37
- package/lib/sandbox/control/state.ts +6 -3
- package/lib/sandbox/control/task-view.ts +240 -0
- package/lib/sandbox/engines/authority.ts +365 -0
- package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
- package/lib/sandbox/index.ts +7 -0
- package/lib/sandbox/recovery.ts +21 -1
- package/lib/sandbox/workspace-view.ts +9 -3
- package/lib/sandbox/worktree-safety.ts +4 -1
- package/lib/server/index.ts +10 -0
- package/lib/task/artifact-lifecycle.ts +38 -16
- package/lib/task/artifact-operations.ts +626 -0
- package/lib/task/artifact-repair-intent.ts +71 -0
- package/lib/task/artifact-schema.ts +192 -0
- package/lib/task/capabilities.ts +70 -1
- package/lib/task/control-authority.ts +11 -1
- package/lib/task/create-service.ts +131 -6
- package/lib/task/create.ts +27 -0
- package/lib/task/events.ts +161 -65
- package/lib/task/index.ts +16 -3
- package/lib/task/local-artifact-finalization.ts +87 -218
- package/lib/task/orchestration.ts +172 -49
- package/lib/task/qualification-audit.ts +599 -0
- package/lib/task/qualification-confirmation.ts +117 -0
- package/lib/task/qualification-intents.ts +150 -0
- package/lib/task/review-artifacts.ts +21 -22
- package/lib/task/review-finalization.ts +133 -4
- package/lib/task/sections.ts +6 -4
- package/lib/task/verification-config.ts +12 -0
- package/lib/task/verification-engine.ts +55 -4
- package/package.json +6 -1
- package/templates/.agents/rules/README.en.md +2 -0
- package/templates/.agents/rules/README.zh-CN.md +2 -0
- package/templates/.agents/rules/decision-qualification.en.md +22 -0
- package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
- package/templates/.agents/rules/evidence-reporting.en.md +28 -0
- package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
- package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
- package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
- package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
- package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
- package/templates/.agents/rules/security-alerts.en.md +8 -8
- package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
- package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
- package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
- package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
- package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
- 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 +14 -1
- package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
- package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
- package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
- package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
- 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/fix-mode.en.md +3 -1
- package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
- package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
- package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
- package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -1
- package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
- package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
- package/templates/.agents/skills/complete-task/SKILL.en.md +9 -22
- package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +9 -22
- package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
- package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -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 +8 -8
- package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
- package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
- package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
- package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
- package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
- package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
- package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
- package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
- package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
- package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
- package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
- package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
- package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
- package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
- package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
- package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
- package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
- package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
- package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
- package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -1
- package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
- package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
- package/templates/.agents/skills/test/SKILL.en.md +13 -2
- package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
- package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
- package/templates/.agents/templates/task.en.md +6 -0
- package/templates/.agents/templates/task.zh-CN.md +6 -0
- package/templates/.agents/scripts/security-alerts.github.sh +0 -151
- package/templates/.agents/scripts/security-alerts.sh +0 -31
- package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
- package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
- package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
function intentRoot(repoRoot) {
|
|
4
|
+
return path.join(repoRoot, '.agents', 'workspace', '.local-artifact-finalization-intents');
|
|
5
|
+
}
|
|
6
|
+
function intentPath(repoRoot, taskId, family, artifact) {
|
|
7
|
+
return path.join(intentRoot(repoRoot), `${taskId}-${family}-${artifact}.json`);
|
|
8
|
+
}
|
|
9
|
+
function isArtifactRepairIntent(value) {
|
|
10
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
11
|
+
return false;
|
|
12
|
+
const intent = value;
|
|
13
|
+
return intent.version === 1
|
|
14
|
+
&& typeof intent.taskId === 'string' && /^TASK-\d{8}-\d{6}$/.test(intent.taskId)
|
|
15
|
+
&& typeof intent.family === 'string' && ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code'].includes(intent.family)
|
|
16
|
+
&& typeof intent.artifact === 'string' && intent.artifact.length > 0
|
|
17
|
+
&& ['awaiting-repair', 'passed', 'consumed'].includes(String(intent.state))
|
|
18
|
+
&& (intent.baselineSemanticDigest === null || (typeof intent.baselineSemanticDigest === 'string' && /^[a-f0-9]{64}$/.test(intent.baselineSemanticDigest)))
|
|
19
|
+
&& typeof intent.artifactSha256 === 'string' && /^[a-f0-9]{64}$/.test(intent.artifactSha256)
|
|
20
|
+
&& typeof intent.semanticDigest === 'string' && /^[a-f0-9]{64}$/.test(intent.semanticDigest)
|
|
21
|
+
&& (intent.state === 'awaiting-repair' ? intent.baselineSemanticDigest === intent.semanticDigest : true);
|
|
22
|
+
}
|
|
23
|
+
function readArtifactRepairIntent(repoRoot, taskId, family, artifact) {
|
|
24
|
+
const target = intentPath(repoRoot, taskId, family, artifact);
|
|
25
|
+
if (!fs.existsSync(target))
|
|
26
|
+
return null;
|
|
27
|
+
let value;
|
|
28
|
+
try {
|
|
29
|
+
value = JSON.parse(fs.readFileSync(target, 'utf8'));
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new Error(`ARTIFACT_REPAIR_INTENT_INVALID: ${String(error)}`);
|
|
33
|
+
}
|
|
34
|
+
if (!isArtifactRepairIntent(value) || value.taskId !== taskId || value.family !== family || value.artifact !== artifact) {
|
|
35
|
+
throw new Error('ARTIFACT_REPAIR_INTENT_INVALID: repair provenance schema is invalid');
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
function writeArtifactRepairIntent(repoRoot, value) {
|
|
40
|
+
if (!isArtifactRepairIntent(value))
|
|
41
|
+
throw new Error('ARTIFACT_REPAIR_INTENT_INVALID: repair provenance schema is invalid');
|
|
42
|
+
const directory = intentRoot(repoRoot);
|
|
43
|
+
fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
44
|
+
const target = intentPath(repoRoot, value.taskId, value.family, value.artifact);
|
|
45
|
+
const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
|
|
46
|
+
fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
|
|
47
|
+
try {
|
|
48
|
+
fs.renameSync(temporary, target);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
try {
|
|
52
|
+
fs.unlinkSync(temporary);
|
|
53
|
+
}
|
|
54
|
+
catch { /* preserve primary error */ }
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export { readArtifactRepairIntent, writeArtifactRepairIntent };
|
|
59
|
+
//# sourceMappingURL=artifact-repair-intent.js.map
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const ARTIFACT_FAMILY_CATALOG = [
|
|
2
|
+
{ family: 'analysis', sectionAliases: ['分析', 'Analysis'], heading: '分析', labels: ['需求分析报告', 'Requirements Analysis'] },
|
|
3
|
+
{ family: 'review-analysis', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['需求分析审查', 'Analysis Review'] },
|
|
4
|
+
{ family: 'plan', sectionAliases: ['设计', 'Design'], heading: '设计', labels: ['技术方案', 'Technical Plan'] },
|
|
5
|
+
{ family: 'review-plan', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['技术方案审查', 'Plan Review'] },
|
|
6
|
+
{ family: 'code', sectionAliases: ['实现备注', 'Implementation Notes'], heading: '实现备注', labels: ['实现报告', 'Implementation Report'] },
|
|
7
|
+
{ family: 'review-code', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['代码审查', 'Code Review'] },
|
|
8
|
+
{ family: 'manual-validation', sectionAliases: ['实现备注', 'Implementation Notes'], heading: '实现备注', labels: ['人工验证', 'Manual Validation'] },
|
|
9
|
+
{ family: 'validation-run', sectionAliases: ['实现备注', 'Implementation Notes'], heading: '实现备注', labels: ['验证运行证据', 'Validation Run Evidence'] },
|
|
10
|
+
{ family: 'pr-review', sectionAliases: ['审查反馈', 'Review Feedback'], heading: '审查反馈', labels: ['PR 审查报告', 'PR Review Report'] }
|
|
11
|
+
];
|
|
12
|
+
const LOCAL_SECTIONS = {
|
|
13
|
+
analysis: [
|
|
14
|
+
['source', '需求来源', 'Requirements Source'],
|
|
15
|
+
['understanding', '需求理解', 'Requirements Understanding'],
|
|
16
|
+
['files', '相关文件', 'Related Files'],
|
|
17
|
+
['impact', '影响评估', 'Impact Assessment'],
|
|
18
|
+
['risks', '技术风险', 'Technical Risks'],
|
|
19
|
+
['effort', '工作量和复杂度评估', 'Effort and Complexity Assessment'],
|
|
20
|
+
['state-check', '状态核对', 'State Check']
|
|
21
|
+
],
|
|
22
|
+
plan: [
|
|
23
|
+
['understanding', '问题理解', 'Problem Understanding'],
|
|
24
|
+
['constraints', '约束条件', 'Constraints'],
|
|
25
|
+
['options', '方案对比', 'Options Comparison'],
|
|
26
|
+
['approach', '技术方法', 'Technical Approach'],
|
|
27
|
+
['steps', '实施步骤', 'Implementation Steps'],
|
|
28
|
+
['files', '文件清单', 'File List'],
|
|
29
|
+
['verification', '验证策略', 'Verification Strategy'],
|
|
30
|
+
['state-check', '状态核对', 'State Check']
|
|
31
|
+
],
|
|
32
|
+
code: [
|
|
33
|
+
['input', '实现输入', 'Implementation Input'],
|
|
34
|
+
['files', '变更文件', 'Changed Files'],
|
|
35
|
+
['key-code', '关键代码说明', 'Key Code Notes'],
|
|
36
|
+
['tests', '测试结果', 'Test Results'],
|
|
37
|
+
['deviations', '与方案的差异', 'Differences from Plan'],
|
|
38
|
+
['review-focus', '供审查关注的内容', 'Review Focus'],
|
|
39
|
+
['state-check', '状态核对', 'State Check'],
|
|
40
|
+
['evidence', '证据原文', 'Raw Evidence']
|
|
41
|
+
],
|
|
42
|
+
'review-analysis': [
|
|
43
|
+
['summary', '审查摘要', 'Review Summary'],
|
|
44
|
+
['coverage', '检视覆盖声明', 'Inspection Coverage'],
|
|
45
|
+
['specialized-coverage', '需求分析专项覆盖', 'Requirements Analysis Coverage'],
|
|
46
|
+
['traceability', '追踪矩阵', 'Traceability Matrix'],
|
|
47
|
+
['issues', '问题清单', 'Findings'],
|
|
48
|
+
['non-blocking', '非阻塞建议', 'Non-blocking Suggestions'],
|
|
49
|
+
['manual-validation', '人工校验项', 'Manual Validation Items'],
|
|
50
|
+
['conclusion', '结论与建议', 'Conclusion and Recommendation'],
|
|
51
|
+
['state-check', '状态核对', 'State Check'],
|
|
52
|
+
['evidence', '证据原文', 'Raw Evidence'],
|
|
53
|
+
['self-critique', '自我质疑', 'Self-critique'],
|
|
54
|
+
['ledger-writeback', '审查分歧账本回写', 'Review Disagreement Ledger Write-back']
|
|
55
|
+
],
|
|
56
|
+
'review-plan': [
|
|
57
|
+
['summary', '审查摘要', 'Review Summary'],
|
|
58
|
+
['coverage', '检视覆盖声明', 'Inspection Coverage'],
|
|
59
|
+
['specialized-coverage', '技术方案架构覆盖', 'Technical Plan Architecture Coverage'],
|
|
60
|
+
['traceability', '追踪矩阵', 'Traceability Matrix'],
|
|
61
|
+
['issues', '问题清单', 'Findings'],
|
|
62
|
+
['non-blocking', '非阻塞建议', 'Non-blocking Suggestions'],
|
|
63
|
+
['manual-validation', '人工校验项', 'Manual Validation Items'],
|
|
64
|
+
['conclusion', '结论与建议', 'Conclusion and Recommendation'],
|
|
65
|
+
['state-check', '状态核对', 'State Check'],
|
|
66
|
+
['evidence', '证据原文', 'Raw Evidence'],
|
|
67
|
+
['self-critique', '自我质疑', 'Self-critique'],
|
|
68
|
+
['ledger-writeback', '审查分歧账本回写', 'Review Disagreement Ledger Write-back']
|
|
69
|
+
],
|
|
70
|
+
'review-code': [
|
|
71
|
+
['summary', '审查摘要', 'Review Summary'],
|
|
72
|
+
['coverage', '检视覆盖声明', 'Inspection Coverage'],
|
|
73
|
+
['specialized-coverage', '代码实现专项覆盖', 'Code Implementation Coverage'],
|
|
74
|
+
['traceability', '追踪矩阵', 'Traceability Matrix'],
|
|
75
|
+
['issues', '问题清单', 'Findings'],
|
|
76
|
+
['non-blocking', '非阻塞建议', 'Non-blocking Suggestions'],
|
|
77
|
+
['manual-validation', '人工校验项', 'Manual Validation Items'],
|
|
78
|
+
['conclusion', '结论与建议', 'Conclusion and Recommendation'],
|
|
79
|
+
['state-check', '状态核对', 'State Check'],
|
|
80
|
+
['evidence', '证据原文', 'Raw Evidence'],
|
|
81
|
+
['self-critique', '自我质疑', 'Self-critique'],
|
|
82
|
+
['ledger-writeback', '审查分歧账本回写', 'Review Disagreement Ledger Write-back']
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
function buildSections(family) {
|
|
86
|
+
return LOCAL_SECTIONS[family].map(([id, zh, en], index) => ({
|
|
87
|
+
id,
|
|
88
|
+
order: index + 1,
|
|
89
|
+
headings: { zh, en },
|
|
90
|
+
marker: `artifact-section:${family}:${id}`
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
const ARTIFACT_SCHEMAS = [
|
|
94
|
+
{ family: 'analysis', title: { zh: '需求分析报告', en: 'Requirements Analysis' }, sections: buildSections('analysis'), requiredPatterns: ['^\\$ '] },
|
|
95
|
+
{ family: 'review-analysis', title: { zh: '需求分析审查报告', en: 'Analysis Review Report' }, sections: buildSections('review-analysis'), requiredPatterns: ['^### (?:审查决定|Approval Decision)$', '^\\$ '] },
|
|
96
|
+
{ family: 'plan', title: { zh: '技术方案', en: 'Technical Plan' }, sections: buildSections('plan'), requiredPatterns: ['^\\$ '] },
|
|
97
|
+
{ family: 'review-plan', title: { zh: '技术方案审查报告', en: 'Plan Review Report' }, sections: buildSections('review-plan'), requiredPatterns: ['^### (?:审查决定|Approval Decision)$', '^\\$ '] },
|
|
98
|
+
{ family: 'code', title: { zh: '实现报告', en: 'Implementation Report' }, sections: buildSections('code'), requiredPatterns: ['^\\$ '] },
|
|
99
|
+
{ family: 'review-code', title: { zh: '代码审查报告', en: 'Code Review Report' }, sections: buildSections('review-code'), requiredPatterns: [
|
|
100
|
+
'^### (?:审查决定|Approval Decision)$',
|
|
101
|
+
'^\\$ ',
|
|
102
|
+
'^- \\*\\*(?:总体结论|Overall Verdict)\\*\\*[::]\\s*(?:通过|需要修改|拒绝|Approved|Changes Requested|Rejected)\\s*$',
|
|
103
|
+
'^- \\*\\*(?:审查基线提交|Review Baseline Commit)\\*\\*[::]\\s*\\S',
|
|
104
|
+
'^- \\*\\*(?:审查差异基线|Reviewed Diff Base)\\*\\*[::]\\s*[0-9a-f]{40,64}\\s*$',
|
|
105
|
+
'^- \\*\\*(?:审查差异指纹|Reviewed Diff Fingerprint)\\*\\*[::]\\s*sha256:[0-9a-f]{64}\\s*$',
|
|
106
|
+
'^- \\*\\*(?:审查快照树|Reviewed Snapshot Tree)\\*\\*[::]\\s*[0-9a-f]{40,64}\\s*$'
|
|
107
|
+
] }
|
|
108
|
+
];
|
|
109
|
+
function getArtifactSchema(family) {
|
|
110
|
+
return ARTIFACT_SCHEMAS.find((schema) => schema.family === family) ?? null;
|
|
111
|
+
}
|
|
112
|
+
function renderArtifactSkeleton(input) {
|
|
113
|
+
const schema = getArtifactSchema(input.family);
|
|
114
|
+
if (!schema)
|
|
115
|
+
throw new Error(`unknown artifact schema family '${input.family}'`);
|
|
116
|
+
const locale = input.locale ?? 'zh-CN';
|
|
117
|
+
const roundMatch = input.artifact.match(/-r(\d+)\.md$/);
|
|
118
|
+
const round = roundMatch ? Number(roundMatch[1]) : 1;
|
|
119
|
+
const title = schema.title[locale === 'en' ? 'en' : 'zh'];
|
|
120
|
+
const headings = locale === 'en' ? 'en' : 'zh';
|
|
121
|
+
const lines = [
|
|
122
|
+
`<!-- artifact-context:${input.taskId}:${input.family}:${round} -->`,
|
|
123
|
+
`# ${title}`,
|
|
124
|
+
''
|
|
125
|
+
];
|
|
126
|
+
for (const section of schema.sections) {
|
|
127
|
+
lines.push(`## ${section.headings[headings]}`);
|
|
128
|
+
lines.push(`<!-- ${section.marker} -->`);
|
|
129
|
+
lines.push('<!-- artifact-slot:empty -->');
|
|
130
|
+
lines.push('');
|
|
131
|
+
}
|
|
132
|
+
return `${lines.join('\n').trimEnd()}\n`;
|
|
133
|
+
}
|
|
134
|
+
export { ARTIFACT_FAMILY_CATALOG, ARTIFACT_SCHEMAS, getArtifactSchema, renderArtifactSkeleton };
|
|
135
|
+
//# sourceMappingURL=artifact-schema.js.map
|
|
@@ -8,6 +8,8 @@ import { parseReviewSummary, resolveCanonicalVerdict } from './review-artifacts.
|
|
|
8
8
|
import { parseReworkIntentDocument } from './rework-intent.js';
|
|
9
9
|
import { sha256File } from './artifact-receipts.js';
|
|
10
10
|
import { hasOpenLifecycleExecution } from './activity-log.js';
|
|
11
|
+
import { parseQualificationAudit, parseTaskQualification } from './qualification-audit.js';
|
|
12
|
+
const ARTIFACT_AUDIT_FAMILIES = new Set(['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code']);
|
|
11
13
|
const REASONS = new Set([
|
|
12
14
|
'user-request', 'new-requirement', 'upstream-fact-doubt', 'review-finding', 'retry', 'validation-rerun'
|
|
13
15
|
]);
|
|
@@ -42,6 +44,9 @@ function canStart(action, facts, trigger) {
|
|
|
42
44
|
return deny('TASK_NOT_ACTIVE', `state=${facts.taskState}`);
|
|
43
45
|
if (invalidationBlocks(facts.invalidation))
|
|
44
46
|
return deny('INVALIDATION_INCOMPLETE');
|
|
47
|
+
if (facts.qualificationStale && facts.recommendedAction !== action) {
|
|
48
|
+
return deny('QUALIFICATION_STALE', ...(facts.qualificationStaleArtifacts ?? ['qualification audit is stale']));
|
|
49
|
+
}
|
|
45
50
|
if (facts.executionBusy)
|
|
46
51
|
return deny('EXECUTION_BUSY');
|
|
47
52
|
const implicit = trigger.explicitRequest === false;
|
|
@@ -122,9 +127,37 @@ function reviewMatchesLatest(facts, source, review) {
|
|
|
122
127
|
const latestSource = latestArtifact(facts.artifacts[source] ?? []);
|
|
123
128
|
return Boolean(latestSource && facts.reviewedInputs?.[review] === latestSource);
|
|
124
129
|
}
|
|
130
|
+
function qualificationCandidateSnapshotMatches(audit, qualification) {
|
|
131
|
+
const current = new Map(qualification.candidates.map((candidate) => [candidate.candidateId, candidate]));
|
|
132
|
+
return audit.candidateQualifications.length === current.size && audit.candidateQualifications.every((row) => {
|
|
133
|
+
const candidate = current.get(row.candidateId);
|
|
134
|
+
return Boolean(candidate && candidate.status === row.status && candidate.impact === row.impact
|
|
135
|
+
&& candidate.evidence === row.evidence && candidate.constraintIds.join(',') === row.constraintIds.join(','));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
const QUALIFICATION_RECOVERY_ORDER = [
|
|
139
|
+
{ action: 'analysis', pattern: /^analysis(?:-r\d+)?\.md$/ },
|
|
140
|
+
{ action: 'review-analysis', pattern: /^review-analysis(?:-r\d+)?\.md$/ },
|
|
141
|
+
{ action: 'plan', pattern: /^plan(?:-r\d+)?\.md$/ },
|
|
142
|
+
{ action: 'review-plan', pattern: /^review-plan(?:-r\d+)?\.md$/ },
|
|
143
|
+
{ action: 'code', pattern: /^code(?:-r\d+)?\.md$/ },
|
|
144
|
+
{ action: 'review-code', pattern: /^review-code(?:-r\d+)?\.md$/ }
|
|
145
|
+
];
|
|
146
|
+
function qualificationRecoveryAction(facts) {
|
|
147
|
+
const stale = facts.qualificationStaleArtifacts ?? [];
|
|
148
|
+
return QUALIFICATION_RECOVERY_ORDER.find(({ pattern }) => stale.some((name) => pattern.test(name)))?.action ?? null;
|
|
149
|
+
}
|
|
125
150
|
function recommendNext(facts) {
|
|
126
151
|
if (invalidationBlocks(facts.invalidation))
|
|
127
152
|
return { action: null, reasonCode: 'INVALIDATION_INCOMPLETE', evidence: ['reconcile task invalidation before routing'] };
|
|
153
|
+
if (facts.qualificationStale) {
|
|
154
|
+
const action = qualificationRecoveryAction(facts);
|
|
155
|
+
return {
|
|
156
|
+
action,
|
|
157
|
+
reasonCode: 'QUALIFICATION_RECOVERY_REQUIRED',
|
|
158
|
+
evidence: facts.qualificationStaleArtifacts ?? ['qualification audit is stale']
|
|
159
|
+
};
|
|
160
|
+
}
|
|
128
161
|
const pendingIntent = (facts.reworkIntents ?? []).find((intent) => intent.status === 'pending');
|
|
129
162
|
if (pendingIntent)
|
|
130
163
|
return { action: pendingIntent.target, reasonCode: 'REWORK_INTENT_PENDING', evidence: [pendingIntent.intentId, pendingIntent.findingId] };
|
|
@@ -198,6 +231,40 @@ function buildLifecycleFacts(taskDir, content, taskState = 'active', executionBu
|
|
|
198
231
|
const staleArtifacts = Object.fromEntries(Object.keys(artifactFamilies).map((family) => [
|
|
199
232
|
family, files.filter((name) => artifactFamilies[family].test(name) && isArtifactInvalidated(invalidation.document, family, name))
|
|
200
233
|
]));
|
|
234
|
+
const qualification = parseTaskQualification(content);
|
|
235
|
+
if (!qualification.ok)
|
|
236
|
+
return { ok: false, code: 'TASK_CAPABILITY_FACTS_INVALID', message: qualification.message };
|
|
237
|
+
const qualificationStaleArtifacts = [];
|
|
238
|
+
if (qualification.qualification.present) {
|
|
239
|
+
const constraints = new Map(qualification.qualification.constraints.map((row) => [row.constraintId, row.digest]));
|
|
240
|
+
for (const family of Object.keys(artifactFamilies)) {
|
|
241
|
+
if (!ARTIFACT_AUDIT_FAMILIES.has(family))
|
|
242
|
+
continue;
|
|
243
|
+
const name = latestArtifact(artifacts[family] ?? []);
|
|
244
|
+
if (!name)
|
|
245
|
+
continue;
|
|
246
|
+
let auditContent;
|
|
247
|
+
try {
|
|
248
|
+
auditContent = fs.readFileSync(path.join(taskDir, name), 'utf8');
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
qualificationStaleArtifacts.push(name);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const audit = parseQualificationAudit(auditContent);
|
|
255
|
+
if (!audit.ok || !audit.audit.present || !audit.audit.snapshot) {
|
|
256
|
+
qualificationStaleArtifacts.push(name);
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const constraintsChanged = audit.audit.constraintDependencies.some((dependency) => constraints.get(dependency.constraintId) !== dependency.constraintDigest);
|
|
260
|
+
const taskInputChanged = audit.audit.snapshot.taskInputDigest !== qualification.qualification.taskInputDigest;
|
|
261
|
+
if (audit.audit.snapshot.nonConstraintInputDigest !== qualification.qualification.nonConstraintInputDigest
|
|
262
|
+
|| constraintsChanged
|
|
263
|
+
|| (taskInputChanged && !constraintsChanged)
|
|
264
|
+
|| (taskInputChanged && !qualificationCandidateSnapshotMatches(audit.audit, qualification.qualification)))
|
|
265
|
+
qualificationStaleArtifacts.push(name);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
201
268
|
const reviews = {};
|
|
202
269
|
const reviewedInputs = {};
|
|
203
270
|
for (const family of ['review-analysis', 'review-plan', 'review-code']) {
|
|
@@ -226,7 +293,11 @@ function buildLifecycleFacts(taskDir, content, taskState = 'active', executionBu
|
|
|
226
293
|
taskState, currentStep: String(metadata.current_step ?? ''), artifacts, reviews,
|
|
227
294
|
staleArtifacts, reviewedInputs, artifactHashes,
|
|
228
295
|
invalidation: invalidation.document, reworkIntents: rework.intents,
|
|
229
|
-
unresolvedLedger,
|
|
296
|
+
unresolvedLedger,
|
|
297
|
+
executionBusy: executionBusy || hasOpenLifecycleExecution(content),
|
|
298
|
+
recommendedAction: null,
|
|
299
|
+
qualificationStale: qualificationStaleArtifacts.length > 0,
|
|
300
|
+
qualificationStaleArtifacts
|
|
230
301
|
};
|
|
231
302
|
facts.recommendedAction = recommendNext(facts).action;
|
|
232
303
|
return { ok: true, facts };
|
|
@@ -52,6 +52,7 @@ export function createSandboxExecutorExecutionContext(params) {
|
|
|
52
52
|
generation: params.generation,
|
|
53
53
|
manifestPath: absolute('manifestPath', params.manifestPath),
|
|
54
54
|
requestId: params.requestId,
|
|
55
|
+
...(params.diagnosticLog === undefined ? {} : { diagnosticLog: params.diagnosticLog }),
|
|
55
56
|
...(params.controllerBinding === undefined ? {} : { controllerBinding: binding(params.controllerBinding) })
|
|
56
57
|
};
|
|
57
58
|
}
|
|
@@ -87,6 +88,9 @@ function domainOptions(context, options) {
|
|
|
87
88
|
return {
|
|
88
89
|
...options,
|
|
89
90
|
repoRoot: context.repoRoot,
|
|
91
|
+
...(context.source === 'sandbox-executor' && context.diagnosticLog !== undefined
|
|
92
|
+
? { diagnosticLog: context.diagnosticLog }
|
|
93
|
+
: {}),
|
|
90
94
|
...(context.source === 'sandbox-executor' ? { gitWorktreeRoot: context.worktreeRoot } : {})
|
|
91
95
|
};
|
|
92
96
|
}
|
|
@@ -12,6 +12,108 @@ const DEFAULT_DEPENDENCIES = {
|
|
|
12
12
|
syncComment: syncPlatformComment,
|
|
13
13
|
addWarning: applyWorkflowWarningIntent
|
|
14
14
|
};
|
|
15
|
+
function invalidTaskCreateResult() {
|
|
16
|
+
throw new Error('TASK_CREATE_RESULT_INVALID');
|
|
17
|
+
}
|
|
18
|
+
function exactKeys(value, expected) {
|
|
19
|
+
return Object.keys(value).sort().join(',') === [...expected].sort().join(',');
|
|
20
|
+
}
|
|
21
|
+
function validTaskReference(value) {
|
|
22
|
+
return value === null || (typeof value === 'string' && value.length > 0);
|
|
23
|
+
}
|
|
24
|
+
function validTaskCreateError(value) {
|
|
25
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
26
|
+
return false;
|
|
27
|
+
const error = value;
|
|
28
|
+
return exactKeys(error, ['code', 'message', 'retryable'])
|
|
29
|
+
&& typeof error.code === 'string' && /^[A-Z][A-Z0-9_]+$/u.test(error.code)
|
|
30
|
+
&& typeof error.message === 'string'
|
|
31
|
+
&& typeof error.retryable === 'boolean';
|
|
32
|
+
}
|
|
33
|
+
function validTaskCreateControl(value) {
|
|
34
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
35
|
+
return false;
|
|
36
|
+
const control = value;
|
|
37
|
+
return exactKeys(control, ['accepted', 'recovery', 'requestId'])
|
|
38
|
+
&& validTaskReference(control.requestId)
|
|
39
|
+
&& typeof control.accepted === 'boolean'
|
|
40
|
+
&& ['none', 'same-request-id', 'new-request-id', 'inspect-domain-state'].includes(control.recovery);
|
|
41
|
+
}
|
|
42
|
+
export function parseTaskCreateResult(value) {
|
|
43
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
44
|
+
return invalidTaskCreateResult();
|
|
45
|
+
const result = value;
|
|
46
|
+
if (!exactKeys(result, ['changed', 'control', 'error', 'issue', 'operations', 'status', 'task', 'warnings'])
|
|
47
|
+
&& !exactKeys(result, ['changed', 'error', 'issue', 'operations', 'status', 'task', 'warnings'])) {
|
|
48
|
+
return invalidTaskCreateResult();
|
|
49
|
+
}
|
|
50
|
+
if (!['applied', 'no-op', 'degraded', 'failed', 'blocked'].includes(result.status)
|
|
51
|
+
|| typeof result.changed !== 'boolean'
|
|
52
|
+
|| !result.task || typeof result.task !== 'object' || Array.isArray(result.task)
|
|
53
|
+
|| !exactKeys(result.task, ['id', 'shortId'])
|
|
54
|
+
|| !validTaskReference(result.task.id)
|
|
55
|
+
|| !validTaskReference(result.task.shortId)
|
|
56
|
+
|| !Array.isArray(result.operations)
|
|
57
|
+
|| !result.operations.every((operation) => {
|
|
58
|
+
if (!operation || typeof operation !== 'object' || Array.isArray(operation))
|
|
59
|
+
return false;
|
|
60
|
+
const value = operation;
|
|
61
|
+
return exactKeys(value, ['name', 'reasonCode', 'status'])
|
|
62
|
+
&& typeof value.name === 'string' && typeof value.status === 'string'
|
|
63
|
+
&& (value.reasonCode === null || typeof value.reasonCode === 'string');
|
|
64
|
+
})
|
|
65
|
+
|| !Array.isArray(result.warnings)
|
|
66
|
+
|| !result.warnings.every((warning) => {
|
|
67
|
+
if (!warning || typeof warning !== 'object' || Array.isArray(warning))
|
|
68
|
+
return false;
|
|
69
|
+
const value = warning;
|
|
70
|
+
return exactKeys(value, ['action', 'code', 'severity'])
|
|
71
|
+
&& typeof value.action === 'string' && typeof value.code === 'string' && typeof value.severity === 'string';
|
|
72
|
+
})
|
|
73
|
+
|| (result.issue !== null && (!result.issue || typeof result.issue !== 'object' || Array.isArray(result.issue)
|
|
74
|
+
|| !exactKeys(result.issue, ['number', 'url'])
|
|
75
|
+
|| !Number.isSafeInteger(result.issue.number)
|
|
76
|
+
|| (result.issue.number) <= 0
|
|
77
|
+
|| typeof result.issue.url !== 'string'))
|
|
78
|
+
|| (result.error !== null && !validTaskCreateError(result.error))
|
|
79
|
+
|| ('control' in result && !validTaskCreateControl(result.control))) {
|
|
80
|
+
return invalidTaskCreateResult();
|
|
81
|
+
}
|
|
82
|
+
if (result.status === 'blocked' && !result.error?.retryable)
|
|
83
|
+
return invalidTaskCreateResult();
|
|
84
|
+
if (result.status === 'failed' && !result.error)
|
|
85
|
+
return invalidTaskCreateResult();
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
export function projectTaskCreateResult(result, control) {
|
|
89
|
+
return { ...result, control };
|
|
90
|
+
}
|
|
91
|
+
export function taskCreateExitCode(result) {
|
|
92
|
+
return result.status === 'blocked' ? 2 : result.status === 'failed' ? 1 : 0;
|
|
93
|
+
}
|
|
94
|
+
export function taskCreateFailure(error, control) {
|
|
95
|
+
return {
|
|
96
|
+
status: error.retryable ? 'blocked' : 'failed',
|
|
97
|
+
changed: false,
|
|
98
|
+
task: { id: null, shortId: null },
|
|
99
|
+
issue: null,
|
|
100
|
+
operations: [],
|
|
101
|
+
warnings: [],
|
|
102
|
+
error,
|
|
103
|
+
...(control ? { control } : {})
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export function taskCreateOutputUnavailableResult(requestId) {
|
|
107
|
+
return taskCreateFailure({
|
|
108
|
+
code: 'SANDBOX_CONTROL_OUTPUT_UNAVAILABLE',
|
|
109
|
+
message: 'SANDBOX_CONTROL_OUTPUT_UNAVAILABLE: task-create result output was not retained; inspect domain state before retrying',
|
|
110
|
+
retryable: false
|
|
111
|
+
}, {
|
|
112
|
+
requestId,
|
|
113
|
+
accepted: true,
|
|
114
|
+
recovery: 'inspect-domain-state'
|
|
115
|
+
});
|
|
116
|
+
}
|
|
15
117
|
async function verifyCreatedTask(repoRoot, taskId) {
|
|
16
118
|
const verification = await verifyTaskEvent({ taskRef: taskId, event: 'create-task.completed' }, { repoRoot });
|
|
17
119
|
if (verification.status === 'pass') {
|
|
@@ -56,10 +158,7 @@ async function createTask(value, options) {
|
|
|
56
158
|
catch (error) {
|
|
57
159
|
const message = error instanceof Error ? error.message : String(error);
|
|
58
160
|
const code = /^([A-Z][A-Z0-9_]+)/.exec(message)?.[1] ?? 'TASK_CREATE_FAILED';
|
|
59
|
-
return {
|
|
60
|
-
status: 'failed', changed: false, task: { id: null, shortId: null }, issue: null,
|
|
61
|
-
operations: [], warnings: [], error: { code, message, retryable: code === 'TASK_CREATE_LOCK_TIMEOUT' }
|
|
62
|
-
};
|
|
161
|
+
return taskCreateFailure({ code, message, retryable: code === 'TASK_CREATE_LOCK_TIMEOUT' });
|
|
63
162
|
}
|
|
64
163
|
const operations = [{
|
|
65
164
|
name: 'task:local', status: local.status, reasonCode: null
|
package/dist/lib/task/create.js
CHANGED
|
@@ -6,6 +6,7 @@ import { loadShortIdByTaskId, mutateShortIdRegistry } from './short-id.js';
|
|
|
6
6
|
import { TaskExecutionLockError, withTaskExecutionLock } from './task-execution-lock.js';
|
|
7
7
|
import { readDeliveryDefaults, validateBaseRef, validateRemote } from './delivery-target.js';
|
|
8
8
|
import { buildUnboundFact, encodePrDeliveryFact } from './pr-delivery-fact.js';
|
|
9
|
+
import { CANDIDATE_COLUMNS, CONSTRAINT_COLUMNS } from './qualification-audit.js';
|
|
9
10
|
const AGENTS = ['claude', 'codex', 'antigravity', 'opencode', 'cursor'];
|
|
10
11
|
const TYPES = ['feature', 'bugfix', 'refactor', 'docs', 'chore'];
|
|
11
12
|
const PRIORITIES = ['Urgent', 'High', 'Medium', 'Low'];
|
|
@@ -139,6 +140,23 @@ function markdownBlock(value) {
|
|
|
139
140
|
function renderList(items) {
|
|
140
141
|
return items.map((item) => `- ${item}`).join('\n');
|
|
141
142
|
}
|
|
143
|
+
function tableCell(value) {
|
|
144
|
+
return value.replace(/\\/g, '\\\\').replace(/\|/g, '\\|').replace(/[\r\n]/g, ' ');
|
|
145
|
+
}
|
|
146
|
+
function renderTable(columns, rows) {
|
|
147
|
+
return [
|
|
148
|
+
`| ${columns.join(' | ')} |`,
|
|
149
|
+
`| ${columns.map(() => '---').join(' | ')} |`,
|
|
150
|
+
...rows.map((row) => `| ${row.map(tableCell).join(' | ')} |`)
|
|
151
|
+
].join('\n');
|
|
152
|
+
}
|
|
153
|
+
function appendCanonicalRows(content, columns, rows) {
|
|
154
|
+
if (rows.length === 0)
|
|
155
|
+
return content;
|
|
156
|
+
const table = renderTable(columns, rows);
|
|
157
|
+
const separator = `| ${columns.map(() => '---').join(' | ')} |`;
|
|
158
|
+
return content.replace(separator, `${separator}\n${table.split('\n').slice(2).join('\n')}`);
|
|
159
|
+
}
|
|
142
160
|
function replaceEmptySubsection(content, heading, items) {
|
|
143
161
|
if (items.length === 0)
|
|
144
162
|
return content;
|
|
@@ -183,6 +201,13 @@ function renderTask(params) {
|
|
|
183
201
|
];
|
|
184
202
|
for (const [heading, key] of sections)
|
|
185
203
|
content = replaceEmptySubsection(content, heading, candidate.taskInput[key]);
|
|
204
|
+
const constraintIds = candidate.taskInput.constraints.map((_, index) => `C-${index + 1}`);
|
|
205
|
+
content = appendCanonicalRows(content, CONSTRAINT_COLUMNS, candidate.taskInput.constraints.map((statement, index) => [
|
|
206
|
+
constraintIds[index], statement, 'assumption', 'create-task', 'taskInput', 'create-task input', '', ''
|
|
207
|
+
]));
|
|
208
|
+
content = appendCanonicalRows(content, CANDIDATE_COLUMNS, candidate.taskInput.alternatives.map((statement, index) => [
|
|
209
|
+
String.fromCharCode(65 + index), statement, 'pending', constraintIds.join(','), 'requires qualification', 'create-task input'
|
|
210
|
+
]));
|
|
186
211
|
content = content.replace('- **关联 Issue**:#XXX', '- **关联 Issue**:N/A');
|
|
187
212
|
content = content.replace('- **关联 PR**:#XXX', '- **关联 PR**:N/A');
|
|
188
213
|
content = content.replace('- **分支**:`feature/xxx`', `- **分支**:\`${branch}\``);
|