@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.
Files changed (280) hide show
  1. package/bin/cli.ts +26 -9
  2. package/dist/bin/cli.js +173 -157
  3. package/dist/bin/internal-cli.js +42 -21
  4. package/dist/lib/agent-client.js +5 -0
  5. package/dist/lib/internal/agent-client.js +5 -2
  6. package/dist/lib/internal/cli-route-inventory.js +152 -0
  7. package/dist/lib/internal/codex-lifecycle.js +9 -6
  8. package/dist/lib/internal/codex-sandbox-controller.js +8 -2
  9. package/dist/lib/internal/git-workflow.js +10 -6
  10. package/dist/lib/internal/platform-checks.js +16 -4
  11. package/dist/lib/internal/platform-comment.js +16 -4
  12. package/dist/lib/internal/platform-context.js +4 -1
  13. package/dist/lib/internal/platform-issue.js +12 -4
  14. package/dist/lib/internal/platform-metadata.js +88 -0
  15. package/dist/lib/internal/platform-pr-review.js +16 -3
  16. package/dist/lib/internal/platform-pr.js +24 -10
  17. package/dist/lib/internal/platform-release-notes.js +6 -3
  18. package/dist/lib/internal/platform-security.js +93 -0
  19. package/dist/lib/internal/pr-review-grade.js +14 -3
  20. package/dist/lib/internal/release-workflow.js +19 -5
  21. package/dist/lib/internal/sandbox-control.js +22 -5
  22. package/dist/lib/internal/task-activity.js +13 -4
  23. package/dist/lib/internal/task-artifact.js +186 -27
  24. package/dist/lib/internal/task-context.js +4 -1
  25. package/dist/lib/internal/task-create.js +48 -15
  26. package/dist/lib/internal/task-delivery.js +4 -1
  27. package/dist/lib/internal/task-event.js +4 -1
  28. package/dist/lib/internal/task-finalization.js +4 -1
  29. package/dist/lib/internal/task-invalidation.js +4 -1
  30. package/dist/lib/internal/task-ledger.js +12 -1
  31. package/dist/lib/internal/task-lifecycle.js +4 -1
  32. package/dist/lib/internal/task-operation-registry.js +421 -0
  33. package/dist/lib/internal/task-orchestration.js +12 -0
  34. package/dist/lib/internal/task-override.js +10 -3
  35. package/dist/lib/internal/task-qualification.js +90 -0
  36. package/dist/lib/internal/task-review.js +4 -1
  37. package/dist/lib/internal/task-short-id.js +11 -1
  38. package/dist/lib/internal/task-snapshot.js +4 -1
  39. package/dist/lib/internal/task-validate.js +7 -2
  40. package/dist/lib/internal/task-verify.js +5 -1
  41. package/dist/lib/internal/task-warning.js +8 -1
  42. package/dist/lib/platform/comment-safety.js +226 -0
  43. package/dist/lib/platform/github-provider.js +233 -6
  44. package/dist/lib/platform/issue-comments.js +146 -34
  45. package/dist/lib/platform/pr-change-report.js +6 -12
  46. package/dist/lib/platform/pr-summary.js +28 -7
  47. package/dist/lib/platform/provider-contract.d.ts +67 -1
  48. package/dist/lib/platform/provider-contract.js +6 -2
  49. package/dist/lib/platform/provider-validation.js +76 -3
  50. package/dist/lib/platform/pull-requests.js +115 -170
  51. package/dist/lib/platform/repository-metadata.js +377 -0
  52. package/dist/lib/platform/security-alerts.js +155 -0
  53. package/dist/lib/platform/verification-sync.js +33 -26
  54. package/dist/lib/process-data/index.js +7 -0
  55. package/dist/lib/run/index.js +5 -0
  56. package/dist/lib/sandbox/commands/control-status.js +22 -0
  57. package/dist/lib/sandbox/commands/create.js +32 -6
  58. package/dist/lib/sandbox/commands/ls.js +5 -0
  59. package/dist/lib/sandbox/commands/rm.js +827 -120
  60. package/dist/lib/sandbox/commands/show.js +16 -0
  61. package/dist/lib/sandbox/control/client.js +83 -9
  62. package/dist/lib/sandbox/control/completed-reentry.js +85 -0
  63. package/dist/lib/sandbox/control/container-identity.js +28 -31
  64. package/dist/lib/sandbox/control/executor.js +149 -14
  65. package/dist/lib/sandbox/control/lifecycle.js +621 -127
  66. package/dist/lib/sandbox/control/native-file-lock.js +177 -0
  67. package/dist/lib/sandbox/control/server.js +305 -35
  68. package/dist/lib/sandbox/control/state.js +5 -3
  69. package/dist/lib/sandbox/control/task-view.js +183 -0
  70. package/dist/lib/sandbox/engines/authority.js +289 -0
  71. package/dist/lib/sandbox/engines/docker-exact-discovery.js +97 -0
  72. package/dist/lib/sandbox/index.js +5 -0
  73. package/dist/lib/sandbox/recovery.js +21 -1
  74. package/dist/lib/sandbox/workspace-view.js +2 -1
  75. package/dist/lib/sandbox/worktree-safety.js +4 -1
  76. package/dist/lib/server/index.js +8 -0
  77. package/dist/lib/task/artifact-lifecycle.js +42 -13
  78. package/dist/lib/task/artifact-operations.js +520 -0
  79. package/dist/lib/task/artifact-repair-intent.js +59 -0
  80. package/dist/lib/task/artifact-schema.js +135 -0
  81. package/dist/lib/task/capabilities.js +72 -1
  82. package/dist/lib/task/control-authority.js +4 -0
  83. package/dist/lib/task/create-service.js +103 -4
  84. package/dist/lib/task/create.js +25 -0
  85. package/dist/lib/task/events.js +186 -67
  86. package/dist/lib/task/index.js +11 -3
  87. package/dist/lib/task/local-artifact-finalization.js +75 -150
  88. package/dist/lib/task/orchestration.js +192 -52
  89. package/dist/lib/task/qualification-audit.js +490 -0
  90. package/dist/lib/task/qualification-confirmation.js +109 -0
  91. package/dist/lib/task/qualification-intents.js +148 -0
  92. package/dist/lib/task/review-artifacts.js +22 -23
  93. package/dist/lib/task/review-finalization.js +121 -4
  94. package/dist/lib/task/sections.js +6 -4
  95. package/dist/lib/task/verification-config.js +11 -0
  96. package/dist/lib/task/verification-engine.js +54 -4
  97. package/dist/lifecycle-build-manifest.json +3 -3
  98. package/lib/agent-client.ts +9 -0
  99. package/lib/internal/agent-client.ts +4 -2
  100. package/lib/internal/cli-route-inventory.ts +140 -0
  101. package/lib/internal/codex-lifecycle.ts +8 -6
  102. package/lib/internal/codex-sandbox-controller.ts +7 -2
  103. package/lib/internal/git-workflow.ts +9 -6
  104. package/lib/internal/platform-checks.ts +12 -4
  105. package/lib/internal/platform-comment.ts +12 -4
  106. package/lib/internal/platform-context.ts +3 -1
  107. package/lib/internal/platform-issue.ts +11 -4
  108. package/lib/internal/platform-metadata.ts +70 -0
  109. package/lib/internal/platform-pr-review.ts +14 -3
  110. package/lib/internal/platform-pr.ts +23 -10
  111. package/lib/internal/platform-release-notes.ts +5 -3
  112. package/lib/internal/platform-security.ts +83 -0
  113. package/lib/internal/pr-review-grade.ts +10 -3
  114. package/lib/internal/release-workflow.ts +17 -5
  115. package/lib/internal/sandbox-control.ts +19 -5
  116. package/lib/internal/task-activity.ts +12 -4
  117. package/lib/internal/task-artifact.ts +164 -25
  118. package/lib/internal/task-context.ts +3 -1
  119. package/lib/internal/task-create.ts +76 -15
  120. package/lib/internal/task-delivery.ts +3 -1
  121. package/lib/internal/task-event.ts +3 -1
  122. package/lib/internal/task-finalization.ts +3 -1
  123. package/lib/internal/task-invalidation.ts +3 -1
  124. package/lib/internal/task-ledger.ts +11 -1
  125. package/lib/internal/task-lifecycle.ts +3 -1
  126. package/lib/internal/task-operation-registry.ts +482 -0
  127. package/lib/internal/task-orchestration.ts +12 -0
  128. package/lib/internal/task-override.ts +9 -3
  129. package/lib/internal/task-qualification.ts +61 -0
  130. package/lib/internal/task-review.ts +3 -1
  131. package/lib/internal/task-short-id.ts +10 -1
  132. package/lib/internal/task-snapshot.ts +3 -1
  133. package/lib/internal/task-validate.ts +6 -2
  134. package/lib/internal/task-verify.ts +4 -1
  135. package/lib/internal/task-warning.ts +7 -1
  136. package/lib/platform/comment-safety.ts +250 -0
  137. package/lib/platform/github-provider.ts +229 -7
  138. package/lib/platform/issue-comments.ts +160 -35
  139. package/lib/platform/pr-change-report.ts +6 -12
  140. package/lib/platform/pr-summary.ts +27 -6
  141. package/lib/platform/provider-contract.ts +78 -3
  142. package/lib/platform/provider-validation.ts +85 -3
  143. package/lib/platform/pull-requests.ts +126 -178
  144. package/lib/platform/repository-metadata.ts +453 -0
  145. package/lib/platform/security-alerts.ts +191 -0
  146. package/lib/platform/verification-sync.ts +32 -28
  147. package/lib/process-data/index.ts +7 -0
  148. package/lib/run/index.ts +5 -0
  149. package/lib/sandbox/commands/control-status.ts +26 -0
  150. package/lib/sandbox/commands/create.ts +46 -6
  151. package/lib/sandbox/commands/ls.ts +7 -0
  152. package/lib/sandbox/commands/rm.ts +1000 -87
  153. package/lib/sandbox/commands/show.ts +16 -0
  154. package/lib/sandbox/control/client.ts +103 -9
  155. package/lib/sandbox/control/completed-reentry.ts +98 -0
  156. package/lib/sandbox/control/container-identity.ts +27 -43
  157. package/lib/sandbox/control/executor.ts +177 -12
  158. package/lib/sandbox/control/lifecycle.ts +629 -17
  159. package/lib/sandbox/control/native-file-lock.ts +209 -0
  160. package/lib/sandbox/control/protocol.ts +5 -2
  161. package/lib/sandbox/control/server.ts +319 -37
  162. package/lib/sandbox/control/state.ts +6 -3
  163. package/lib/sandbox/control/task-view.ts +240 -0
  164. package/lib/sandbox/engines/authority.ts +365 -0
  165. package/lib/sandbox/engines/docker-exact-discovery.ts +132 -0
  166. package/lib/sandbox/index.ts +7 -0
  167. package/lib/sandbox/recovery.ts +21 -1
  168. package/lib/sandbox/workspace-view.ts +9 -3
  169. package/lib/sandbox/worktree-safety.ts +4 -1
  170. package/lib/server/index.ts +10 -0
  171. package/lib/task/artifact-lifecycle.ts +38 -16
  172. package/lib/task/artifact-operations.ts +626 -0
  173. package/lib/task/artifact-repair-intent.ts +71 -0
  174. package/lib/task/artifact-schema.ts +192 -0
  175. package/lib/task/capabilities.ts +70 -1
  176. package/lib/task/control-authority.ts +11 -1
  177. package/lib/task/create-service.ts +131 -6
  178. package/lib/task/create.ts +27 -0
  179. package/lib/task/events.ts +161 -65
  180. package/lib/task/index.ts +16 -3
  181. package/lib/task/local-artifact-finalization.ts +87 -218
  182. package/lib/task/orchestration.ts +172 -49
  183. package/lib/task/qualification-audit.ts +599 -0
  184. package/lib/task/qualification-confirmation.ts +117 -0
  185. package/lib/task/qualification-intents.ts +150 -0
  186. package/lib/task/review-artifacts.ts +21 -22
  187. package/lib/task/review-finalization.ts +133 -4
  188. package/lib/task/sections.ts +6 -4
  189. package/lib/task/verification-config.ts +12 -0
  190. package/lib/task/verification-engine.ts +55 -4
  191. package/package.json +6 -1
  192. package/templates/.agents/rules/README.en.md +2 -0
  193. package/templates/.agents/rules/README.zh-CN.md +2 -0
  194. package/templates/.agents/rules/decision-qualification.en.md +22 -0
  195. package/templates/.agents/rules/decision-qualification.zh-CN.md +22 -0
  196. package/templates/.agents/rules/evidence-reporting.en.md +28 -0
  197. package/templates/.agents/rules/evidence-reporting.zh-CN.md +28 -0
  198. package/templates/.agents/rules/label-milestone-setup.en.md +7 -7
  199. package/templates/.agents/rules/label-milestone-setup.zh-CN.md +7 -7
  200. package/templates/.agents/rules/local-artifact-repair.en.md +5 -1
  201. package/templates/.agents/rules/local-artifact-repair.zh-CN.md +5 -1
  202. package/templates/.agents/rules/security-alerts.en.md +8 -8
  203. package/templates/.agents/rules/security-alerts.zh-CN.md +8 -8
  204. package/templates/.agents/skills/analyze-task/SKILL.en.md +15 -2
  205. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +19 -2
  206. package/templates/.agents/skills/analyze-task/config/verify.en.json +1 -12
  207. package/templates/.agents/skills/analyze-task/config/verify.zh-CN.json +1 -12
  208. package/templates/.agents/skills/close-codescan/SKILL.en.md +2 -2
  209. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +2 -2
  210. package/templates/.agents/skills/close-dependabot/SKILL.en.md +2 -2
  211. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +2 -2
  212. package/templates/.agents/skills/code-task/SKILL.en.md +14 -1
  213. package/templates/.agents/skills/code-task/SKILL.zh-CN.md +14 -1
  214. package/templates/.agents/skills/code-task/config/verify.en.json +5 -14
  215. package/templates/.agents/skills/code-task/config/verify.zh-CN.json +5 -14
  216. package/templates/.agents/skills/code-task/reference/code-rules.en.md +5 -4
  217. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +5 -4
  218. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +1 -1
  219. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +1 -1
  220. package/templates/.agents/skills/code-task/reference/fix-mode.en.md +3 -1
  221. package/templates/.agents/skills/code-task/reference/fix-mode.zh-CN.md +3 -1
  222. package/templates/.agents/skills/code-task/reference/report-template.en.md +42 -15
  223. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +39 -12
  224. package/templates/.agents/skills/complete-manual-validation/SKILL.en.md +5 -1
  225. package/templates/.agents/skills/complete-manual-validation/SKILL.zh-CN.md +5 -1
  226. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +2 -0
  227. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +2 -0
  228. package/templates/.agents/skills/complete-task/SKILL.en.md +9 -22
  229. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +9 -22
  230. package/templates/.agents/skills/create-task/SKILL.en.md +8 -0
  231. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -0
  232. package/templates/.agents/skills/import-codescan/SKILL.en.md +1 -1
  233. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +1 -1
  234. package/templates/.agents/skills/import-dependabot/SKILL.en.md +1 -1
  235. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +1 -1
  236. package/templates/.agents/skills/init-labels/SKILL.en.md +8 -8
  237. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -8
  238. package/templates/.agents/skills/init-milestones/SKILL.en.md +9 -11
  239. package/templates/.agents/skills/init-milestones/SKILL.zh-CN.md +9 -11
  240. package/templates/.agents/skills/plan-task/SKILL.en.md +14 -1
  241. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +16 -1
  242. package/templates/.agents/skills/plan-task/config/verify.en.json +4 -14
  243. package/templates/.agents/skills/plan-task/config/verify.zh-CN.json +4 -14
  244. package/templates/.agents/skills/review-analysis/SKILL.en.md +14 -1
  245. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +14 -1
  246. package/templates/.agents/skills/review-analysis/config/verify.en.json +1 -18
  247. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +1 -18
  248. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +50 -23
  249. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +45 -18
  250. package/templates/.agents/skills/review-code/SKILL.en.md +14 -1
  251. package/templates/.agents/skills/review-code/SKILL.zh-CN.md +14 -1
  252. package/templates/.agents/skills/review-code/config/verify.en.json +1 -23
  253. package/templates/.agents/skills/review-code/config/verify.zh-CN.json +1 -23
  254. package/templates/.agents/skills/review-code/reference/report-template.en.md +49 -22
  255. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +45 -18
  256. package/templates/.agents/skills/review-plan/SKILL.en.md +14 -1
  257. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +14 -1
  258. package/templates/.agents/skills/review-plan/config/verify.en.json +1 -18
  259. package/templates/.agents/skills/review-plan/config/verify.zh-CN.json +1 -18
  260. package/templates/.agents/skills/review-plan/reference/report-template.en.md +49 -22
  261. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +45 -18
  262. package/templates/.agents/skills/review-pr/SKILL.en.md +5 -1
  263. package/templates/.agents/skills/review-pr/SKILL.zh-CN.md +5 -1
  264. package/templates/.agents/skills/review-pr/reference/report-template.en.md +4 -3
  265. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +4 -3
  266. package/templates/.agents/skills/run-manual-validation/SKILL.en.md +5 -1
  267. package/templates/.agents/skills/run-manual-validation/SKILL.zh-CN.md +5 -1
  268. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +3 -1
  269. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +3 -1
  270. package/templates/.agents/skills/test/SKILL.en.md +13 -2
  271. package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -2
  272. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +14 -0
  273. package/templates/.agents/templates/task.en.md +6 -0
  274. package/templates/.agents/templates/task.zh-CN.md +6 -0
  275. package/templates/.agents/scripts/security-alerts.github.sh +0 -151
  276. package/templates/.agents/scripts/security-alerts.sh +0 -31
  277. package/templates/.agents/skills/init-labels/scripts/init-labels.github.sh +0 -146
  278. package/templates/.agents/skills/init-labels/scripts/init-labels.sh +0 -32
  279. package/templates/.agents/skills/init-milestones/scripts/init-milestones.github.sh +0 -294
  280. package/templates/.agents/skills/init-milestones/scripts/init-milestones.sh +0 -6
@@ -1,37 +1,25 @@
1
1
  import fs from 'node:fs';
2
- import { createHash } from 'node:crypto';
3
- import path from 'node:path';
4
2
 
5
- import {
6
- inspectDecisionDetailDuplicates,
7
- scanVisibleMarkdown
8
- } from './decision-details.ts';
9
- import type { VisibleHeading } from './decision-details.ts';
3
+ import { inspectDecisionDetailDuplicates, scanVisibleMarkdown } from './decision-details.ts';
10
4
  import {
11
5
  parseArtifactName,
12
6
  validateCompletedArtifact
13
7
  } from './artifact-lifecycle.ts';
14
8
  import { resolveTaskRef } from './resolve-ref.ts';
9
+ import { expectedQualificationRelations, validateQualificationAudit } from './qualification-audit.ts';
10
+ import { canonicalSemanticDigest, inspectArtifactPatterns, inspectArtifactStructure, sha256Content } from './artifact-operations.ts';
11
+ import { getArtifactSchema } from './artifact-schema.ts';
12
+ import { readArtifactRepairIntent, writeArtifactRepairIntent } from './artifact-repair-intent.ts';
13
+ import type { ArtifactRepairIntent } from './artifact-repair-intent.ts';
15
14
 
16
15
  type LocalArtifactFamily = 'analysis' | 'plan' | 'code';
17
16
 
18
17
  const LOCAL_ARTIFACT_REQUIRED_SECTIONS: Readonly<Record<LocalArtifactFamily, readonly string[]>> = {
19
- analysis: [
20
- '需求来源', '需求理解', '相关文件', '影响评估', '技术风险',
21
- '工作量和复杂度评估', '状态核对'
22
- ],
23
- plan: [
24
- '问题理解', '约束条件', '方案对比', '技术方法', '实施步骤',
25
- '文件清单', '验证策略', '状态核对'
26
- ],
27
- code: [
28
- '实现输入', '变更文件', '关键代码说明', '测试结果', '与方案的差异',
29
- '供审查关注的内容', '状态核对', '证据原文'
30
- ]
18
+ analysis: getArtifactSchema('analysis')!.sections.map((section) => section.headings.zh),
19
+ plan: getArtifactSchema('plan')!.sections.map((section) => section.headings.zh),
20
+ code: getArtifactSchema('code')!.sections.map((section) => section.headings.zh)
31
21
  };
32
22
 
33
- const LOCAL_ARTIFACT_REQUIRED_PATTERNS = ['^\\$ '];
34
-
35
23
  type LocalArtifactDiagnosticCode =
36
24
  | 'LOCAL_ARTIFACT_EMPTY'
37
25
  | 'LOCAL_ARTIFACT_MISSING_SECTION'
@@ -39,9 +27,11 @@ type LocalArtifactDiagnosticCode =
39
27
  | 'LOCAL_STATUS_COMMAND_MISSING'
40
28
  | 'LOCAL_DECISION_DETAIL_DUPLICATE'
41
29
  | 'LOCAL_REQUIRED_PATTERN_MISSING'
30
+ | 'LOCAL_STRUCTURAL_INVALID'
42
31
  | 'LOCAL_SECTION_HEADING_TRAILING_PUNCTUATION'
43
32
  | 'LOCAL_REPAIR_PROVENANCE_CONFLICT'
44
- | 'LOCAL_REPAIR_BASELINE_MISMATCH';
33
+ | 'LOCAL_REPAIR_BASELINE_MISMATCH'
34
+ | 'LOCAL_QUALIFICATION_AUDIT_INVALID';
45
35
 
46
36
  type LocalArtifactDiagnostic = {
47
37
  code: LocalArtifactDiagnosticCode;
@@ -56,7 +46,8 @@ type LocalArtifactDiagnostic = {
56
46
  type LocalArtifactValidationOptions = {
57
47
  family: LocalArtifactFamily;
58
48
  requiredSections?: readonly string[];
59
- requiredPatterns?: readonly string[];
49
+ taskContent?: string;
50
+ artifact?: string;
60
51
  };
61
52
 
62
53
  type LocalArtifactValidationResult = {
@@ -73,7 +64,6 @@ type LocalArtifactFinalizationRequest = {
73
64
  artifact: string;
74
65
  repoRoot?: string;
75
66
  requiredSections?: readonly string[];
76
- requiredPatterns?: readonly string[];
77
67
  };
78
68
 
79
69
  type LocalArtifactFinalizationResult = {
@@ -90,38 +80,7 @@ type LocalArtifactFinalizationResult = {
90
80
  error: { code: string; message: string } | null;
91
81
  };
92
82
 
93
- type LocalArtifactFinalizationIntent = Readonly<{
94
- version: 1;
95
- taskId: string;
96
- family: LocalArtifactFamily;
97
- artifact: string;
98
- state: 'awaiting-repair' | 'passed' | 'consumed';
99
- baselineSemanticDigest: string | null;
100
- artifactSha256: string;
101
- semanticDigest: string;
102
- }>;
103
-
104
- function finalizationIntentRoot(repoRoot: string): string {
105
- return path.join(repoRoot, '.agents', 'workspace', '.local-artifact-finalization-intents');
106
- }
107
-
108
- function finalizationIntentPath(repoRoot: string, taskId: string, family: LocalArtifactFamily, artifact: string): string {
109
- return path.join(finalizationIntentRoot(repoRoot), `${taskId}-${family}-${artifact}.json`);
110
- }
111
-
112
- function isFinalizationIntent(value: unknown): value is LocalArtifactFinalizationIntent {
113
- if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
114
- const intent = value as Record<string, unknown>;
115
- return intent.version === 1
116
- && typeof intent.taskId === 'string' && intent.taskId.length > 0
117
- && (intent.family === 'analysis' || intent.family === 'plan' || intent.family === 'code')
118
- && typeof intent.artifact === 'string' && intent.artifact.length > 0
119
- && (intent.state === 'awaiting-repair' || intent.state === 'passed' || intent.state === 'consumed')
120
- && (intent.baselineSemanticDigest === null || (typeof intent.baselineSemanticDigest === 'string' && /^[a-f0-9]{64}$/.test(intent.baselineSemanticDigest)))
121
- && typeof intent.artifactSha256 === 'string' && /^[a-f0-9]{64}$/.test(intent.artifactSha256)
122
- && typeof intent.semanticDigest === 'string' && /^[a-f0-9]{64}$/.test(intent.semanticDigest)
123
- && (intent.state === 'awaiting-repair' ? intent.baselineSemanticDigest === intent.semanticDigest : true);
124
- }
83
+ type LocalArtifactFinalizationIntent = ArtifactRepairIntent;
125
84
 
126
85
  function readLocalArtifactFinalizationIntent(
127
86
  repoRoot: string,
@@ -129,27 +88,11 @@ function readLocalArtifactFinalizationIntent(
129
88
  family: LocalArtifactFamily,
130
89
  artifact: string
131
90
  ): LocalArtifactFinalizationIntent | null {
132
- const target = finalizationIntentPath(repoRoot, taskId, family, artifact);
133
- if (!fs.existsSync(target)) return null;
134
- const value = JSON.parse(fs.readFileSync(target, 'utf8')) as unknown;
135
- if (!isFinalizationIntent(value) || value.taskId !== taskId || value.family !== family || value.artifact !== artifact) {
136
- throw new Error('LOCAL_FINALIZATION_INTENT_INVALID: finalization provenance schema is invalid');
137
- }
138
- return value;
91
+ return readArtifactRepairIntent(repoRoot, taskId, family, artifact);
139
92
  }
140
93
 
141
94
  function writeLocalArtifactFinalizationIntent(repoRoot: string, value: LocalArtifactFinalizationIntent): void {
142
- if (!isFinalizationIntent(value)) throw new Error('LOCAL_FINALIZATION_INTENT_INVALID: finalization provenance schema is invalid');
143
- const directory = finalizationIntentRoot(repoRoot);
144
- fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
145
- const target = finalizationIntentPath(repoRoot, value.taskId, value.family, value.artifact);
146
- const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
147
- fs.writeFileSync(temporary, `${JSON.stringify(value)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
148
- try { fs.renameSync(temporary, target); }
149
- catch (error) {
150
- try { fs.unlinkSync(temporary); } catch { /* preserve primary error */ }
151
- throw error;
152
- }
95
+ writeArtifactRepairIntent(repoRoot, value);
153
96
  }
154
97
 
155
98
  function consumeLocalArtifactFinalizationIntent(
@@ -163,63 +106,29 @@ function consumeLocalArtifactFinalizationIntent(
163
106
  return consumed;
164
107
  }
165
108
 
166
- function requiredSections(family: LocalArtifactFamily): readonly string[] {
167
- return LOCAL_ARTIFACT_REQUIRED_SECTIONS[family];
168
- }
169
-
170
- function lineNumber(content: string, offset: number): number {
171
- return content.slice(0, offset).split('\n').length;
172
- }
173
-
174
- function sectionBody(content: string, heading: VisibleHeading): string {
175
- const next = scanVisibleMarkdown(content).headings.find((candidate) => (
176
- candidate.start > heading.start && candidate.level <= 2
177
- ));
178
- return content.slice(heading.end, next?.start ?? content.length);
179
- }
180
-
181
- function semanticDigest(content: string, candidate?: VisibleHeading): string {
182
- let normalized = content;
183
- if (candidate) {
184
- const raw = content.slice(candidate.start, candidate.end);
185
- const marker = raw.match(/([::])\s*$/);
186
- if (marker?.index !== undefined) {
187
- const canonical = raw.slice(0, marker.index) + raw.slice(marker.index + 1);
188
- normalized = `${content.slice(0, candidate.start)}${canonical}${content.slice(candidate.end)}`;
189
- }
190
- }
191
- return createHash('sha256').update(normalized, 'utf8').digest('hex');
192
- }
193
-
194
- function sha256Content(content: string): string {
195
- return createHash('sha256').update(content, 'utf8').digest('hex');
196
- }
197
-
198
- function visibleSectionHeadings(content: string, section: string): VisibleHeading[] {
199
- return scanVisibleMarkdown(content).headings.filter((heading) => (
200
- heading.level === 2 && heading.text === section
201
- ));
202
- }
203
-
204
- function trailingPunctuationCandidates(content: string, section: string): VisibleHeading[] {
205
- return scanVisibleMarkdown(content).headings.filter((heading) => (
206
- heading.level === 2 && (
207
- heading.text === `${section}:` || heading.text === `${section}:`
208
- )
209
- ));
109
+ function localDiagnosticCode(code: string): LocalArtifactDiagnosticCode | null {
110
+ const map: Record<string, LocalArtifactDiagnosticCode> = {
111
+ ARTIFACT_EMPTY: 'LOCAL_ARTIFACT_EMPTY',
112
+ ARTIFACT_MISSING_SECTION: 'LOCAL_ARTIFACT_MISSING_SECTION',
113
+ ARTIFACT_DUPLICATE_SECTION: 'LOCAL_ARTIFACT_DUPLICATE_SECTION',
114
+ ARTIFACT_HEADING_TRAILING_PUNCTUATION: 'LOCAL_SECTION_HEADING_TRAILING_PUNCTUATION'
115
+ };
116
+ return map[code] ?? 'LOCAL_STRUCTURAL_INVALID';
210
117
  }
211
118
 
212
- function diagnostic(
213
- code: LocalArtifactDiagnosticCode,
214
- message: string,
215
- content: string,
216
- heading?: VisibleHeading,
217
- extra: Partial<LocalArtifactDiagnostic> = {}
218
- ): LocalArtifactDiagnostic {
119
+ function localDiagnostic(
120
+ item: { code: string; message: string; line: number | null; repairable: boolean; operation?: { kind: string; from: string; to: string } }
121
+ ): LocalArtifactDiagnostic | null {
122
+ const code = localDiagnosticCode(item.code);
123
+ if (!code) return null;
219
124
  return {
220
- code, message, repairable: false,
221
- line: heading ? lineNumber(content, heading.start) : null,
222
- ...extra
125
+ code,
126
+ message: item.message,
127
+ repairable: item.repairable,
128
+ line: item.line,
129
+ ...(item.operation?.kind === 'replace-line'
130
+ ? { from: item.operation.from, to: item.operation.to, operation: 'replace-line' as const }
131
+ : {})
223
132
  };
224
133
  }
225
134
 
@@ -231,117 +140,70 @@ function validateLocalArtifact(
231
140
  content: string,
232
141
  options: LocalArtifactValidationOptions
233
142
  ): LocalArtifactValidationResult {
234
- const sections = options.requiredSections ?? requiredSections(options.family);
235
- const patterns = options.requiredPatterns ?? LOCAL_ARTIFACT_REQUIRED_PATTERNS;
143
+ const schema = getArtifactSchema(options.family)!;
144
+ const patterns = schema.requiredPatterns;
236
145
  const diagnostics: LocalArtifactDiagnostic[] = [];
237
- const candidates: VisibleHeading[] = [];
238
146
  const scanned = scanVisibleMarkdown(content);
239
-
240
- if (!content.trim()) {
241
- diagnostics.push(diagnostic('LOCAL_ARTIFACT_EMPTY', 'artifact is empty', content));
242
- }
243
-
244
- for (const section of sections) {
245
- const exact = scanned.headings.filter((heading) => heading.level === 2 && heading.text === section);
246
- const punctuated = trailingPunctuationCandidates(content, section);
247
- if (exact.length > 1 || punctuated.length > 0 && exact.length > 0 || punctuated.length > 1) {
248
- const first = exact[1] ?? punctuated[0] ?? exact[0];
249
- diagnostics.push(diagnostic(
250
- 'LOCAL_ARTIFACT_DUPLICATE_SECTION',
251
- `required section '${section}' is duplicated or has an ambiguous punctuation variant`,
252
- content, first
253
- ));
254
- } else if (exact.length === 0 && punctuated.length === 1) {
255
- candidates.push(punctuated[0]!);
256
- } else if (exact.length === 0) {
257
- diagnostics.push(diagnostic(
258
- 'LOCAL_ARTIFACT_MISSING_SECTION',
259
- `required section '${section}' is missing`,
260
- content
261
- ));
262
- }
147
+ const structure = inspectArtifactStructure(content, schema);
148
+ for (const item of structure.diagnostics) {
149
+ const mapped = localDiagnostic(item);
150
+ if (mapped) diagnostics.push(mapped);
263
151
  }
264
152
 
265
- const statusSection = sections.find((section) => section === '状态核对' || section.toLowerCase() === 'state check');
153
+ const statusSection = schema.sections.find((section) => section.id === 'state-check');
266
154
  if (statusSection) {
267
- const statusHeading = visibleSectionHeadings(content, statusSection)[0]
268
- ?? candidates.find((heading) => heading.text === `${statusSection}:` || heading.text === `${statusSection}:`);
155
+ const statusHeading = scanned.headings.find((heading) => (
156
+ heading.level === 2 && [statusSection.headings.zh, statusSection.headings.en].some((name) => (
157
+ heading.text === name || heading.text === `${name}:` || heading.text === `${name}:`
158
+ ))
159
+ ));
269
160
  if (statusHeading) {
270
- const body = sectionBody(content, statusHeading);
161
+ const next = scanned.headings.find((candidate) => candidate.start > statusHeading.start && candidate.level <= 2);
162
+ const body = content.slice(statusHeading.end, next?.start ?? content.length);
271
163
  for (const pattern of patterns.filter(isStatusPattern)) {
272
164
  if (!new RegExp(pattern, 'm').test(body)) {
273
- diagnostics.push(diagnostic(
274
- 'LOCAL_STATUS_COMMAND_MISSING',
275
- `status section '${statusSection}' is missing required command output`,
276
- content, statusHeading
277
- ));
165
+ diagnostics.push({ code: 'LOCAL_STATUS_COMMAND_MISSING', message: `status section '${statusHeading.text}' is missing required command output`, repairable: false, line: content.slice(0, statusHeading.start).split('\n').length });
278
166
  }
279
167
  }
280
168
  }
281
169
  }
282
170
 
283
- for (const pattern of patterns.filter((item) => !isStatusPattern(item))) {
284
- if (!new RegExp(pattern, 'm').test(content)) {
285
- diagnostics.push(diagnostic(
286
- 'LOCAL_REQUIRED_PATTERN_MISSING',
287
- `artifact is missing required pattern '${pattern}'`,
288
- content
289
- ));
290
- }
171
+ const patternInspection = inspectArtifactPatterns(content, {
172
+ ...schema,
173
+ requiredPatterns: patterns.filter((item) => !isStatusPattern(item))
174
+ });
175
+ for (const item of patternInspection.diagnostics) {
176
+ diagnostics.push({ code: 'LOCAL_REQUIRED_PATTERN_MISSING', message: item.message, repairable: false, line: null });
291
177
  }
292
178
 
293
179
  const decisionDetails = inspectDecisionDetailDuplicates(content);
294
180
  if (!decisionDetails.ok) {
295
- diagnostics.push(diagnostic(
296
- 'LOCAL_DECISION_DETAIL_DUPLICATE',
297
- decisionDetails.message,
298
- content,
299
- decisionDetails.duplicates[0]?.blocks[0]
300
- ? scanned.headings.find((heading) => heading.start === decisionDetails.duplicates[0]!.blocks[0]!.start)
301
- : undefined
302
- ));
181
+ diagnostics.push({ code: 'LOCAL_DECISION_DETAIL_DUPLICATE', message: decisionDetails.message, repairable: false, line: null });
303
182
  }
304
183
 
305
- if (candidates.length === 1 && diagnostics.length === 0) {
306
- const candidate = candidates[0]!;
307
- const section = candidate.text.slice(0, -1);
308
- const repair = diagnostic(
309
- 'LOCAL_SECTION_HEADING_TRAILING_PUNCTUATION',
310
- `visible required H2 '${candidate.text}' may be normalized to '${section}'`,
311
- content,
312
- candidate,
313
- {
314
- repairable: true,
315
- from: candidate.text,
316
- to: section,
317
- operation: 'replace-line'
318
- }
319
- );
320
- return {
321
- ok: false,
322
- family: options.family,
323
- semanticDigest: semanticDigest(content, candidate),
324
- repairable: true,
325
- diagnostics: [repair]
326
- };
327
- }
328
-
329
- if (candidates.length > 0) {
330
- for (const candidate of candidates) {
331
- const section = candidate.text.slice(0, -1);
332
- diagnostics.push(diagnostic(
333
- 'LOCAL_ARTIFACT_MISSING_SECTION',
334
- `required section '${section}' is missing and cannot be repaired while other structural defects exist`,
335
- content, candidate
336
- ));
184
+ if (options.taskContent !== undefined) {
185
+ const expected = expectedQualificationRelations(options.taskContent, options.family);
186
+ if (!expected.ok) {
187
+ diagnostics.push({ code: 'LOCAL_QUALIFICATION_AUDIT_INVALID', message: `${expected.code}: ${expected.message}`, repairable: false, line: null });
188
+ }
189
+ const qualification = validateQualificationAudit(options.taskContent, content, {
190
+ family: options.family === 'analysis' ? 'analysis' : options.family === 'plan' ? 'plan' : 'code',
191
+ artifact: options.artifact,
192
+ expectedUpstreamRelations: expected.ok ? expected.relations : undefined
193
+ });
194
+ if (!qualification.ok) {
195
+ diagnostics.push({ code: 'LOCAL_QUALIFICATION_AUDIT_INVALID', message: `${qualification.code}: ${qualification.message}`, repairable: false, line: null });
337
196
  }
338
197
  }
339
198
 
199
+ const repairable = structure.repair !== null && diagnostics.length === 1 && diagnostics[0]?.repairable === true;
200
+ const semanticDigestValue = canonicalSemanticDigest(content, structure.repair);
201
+
340
202
  return {
341
203
  ok: diagnostics.length === 0,
342
204
  family: options.family,
343
- semanticDigest: semanticDigest(content),
344
- repairable: false,
205
+ semanticDigest: semanticDigestValue,
206
+ repairable,
345
207
  diagnostics
346
208
  };
347
209
  }
@@ -374,7 +236,7 @@ function provenanceFailure(
374
236
  taskDir: resolved.taskDir,
375
237
  artifactSha256,
376
238
  semanticDigest: semanticDigestValue,
377
- diagnostics: [diagnostic(code, message, content)]
239
+ diagnostics: [{ code, message, repairable: false, line: null }]
378
240
  });
379
241
  }
380
242
 
@@ -399,10 +261,18 @@ function finalizeLocalArtifact(request: LocalArtifactFinalizationRequest): Local
399
261
  taskId: resolved.taskId, taskDir: resolved.taskDir
400
262
  });
401
263
  }
264
+ let taskContent: string;
265
+ try { taskContent = fs.readFileSync(resolved.taskMdPath, 'utf8'); }
266
+ catch (error) {
267
+ return failedFinalization(request, { code: 'TASK_READ_FAILED', message: error instanceof Error ? error.message : String(error) }, {
268
+ taskId: resolved.taskId, taskDir: resolved.taskDir
269
+ });
270
+ }
402
271
  const result = validateLocalArtifact(content, {
403
272
  family: request.family,
404
273
  requiredSections: request.requiredSections,
405
- requiredPatterns: request.requiredPatterns
274
+ taskContent,
275
+ artifact: request.artifact
406
276
  });
407
277
  const artifactSha256 = sha256Content(content);
408
278
  let intent: LocalArtifactFinalizationIntent | null;
@@ -542,12 +412,11 @@ function finalizeLocalArtifact(request: LocalArtifactFinalizationRequest): Local
542
412
  }
543
413
 
544
414
  export {
545
- LOCAL_ARTIFACT_REQUIRED_PATTERNS,
546
415
  LOCAL_ARTIFACT_REQUIRED_SECTIONS,
547
416
  consumeLocalArtifactFinalizationIntent,
548
417
  finalizeLocalArtifact,
549
418
  readLocalArtifactFinalizationIntent,
550
- semanticDigest,
419
+ canonicalSemanticDigest as semanticDigest,
551
420
  sha256Content,
552
421
  validateLocalArtifact
553
422
  };