@fitlab-ai/agent-infra 0.11.4 → 0.11.5

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 (111) hide show
  1. package/dist/bin/internal-cli.js +0 -5
  2. package/dist/lib/decide.js +4 -41
  3. package/dist/lib/git/branch-worktree.js +45 -0
  4. package/dist/lib/internal/cli-route-inventory.js +0 -3
  5. package/dist/lib/internal/task-activity.js +7 -40
  6. package/dist/lib/internal/task-event.js +4 -37
  7. package/dist/lib/internal/task-finalization.js +9 -2
  8. package/dist/lib/internal/task-ledger.js +5 -43
  9. package/dist/lib/internal/task-lifecycle.js +1 -1
  10. package/dist/lib/internal/task-operation-registry.js +1 -4
  11. package/dist/lib/internal/task-review.js +5 -37
  12. package/dist/lib/internal/task-verify.js +3 -47
  13. package/dist/lib/internal/task-warning.js +4 -40
  14. package/dist/lib/platform/pr-summary.js +4 -23
  15. package/dist/lib/platform/verification-sync.js +12 -49
  16. package/dist/lib/sandbox/control/client.js +4 -1
  17. package/dist/lib/sandbox/control/executor.js +12 -4
  18. package/dist/lib/sandbox/control/protocol.js +2 -1
  19. package/dist/lib/sandbox/removal.js +15 -8
  20. package/dist/lib/task/activity-intent.js +1 -2
  21. package/dist/lib/task/artifact-operations.js +36 -2
  22. package/dist/lib/task/artifact-schema.js +7 -7
  23. package/dist/lib/task/control-authority.js +9 -166
  24. package/dist/lib/task/decision-intents.js +2 -4
  25. package/dist/lib/task/events.js +7 -28
  26. package/dist/lib/task/finalization-handoff.js +92 -0
  27. package/dist/lib/task/finalization.js +123 -12
  28. package/dist/lib/task/intermediate-cleanup.js +9 -148
  29. package/dist/lib/task/ledger-intents.js +3 -6
  30. package/dist/lib/task/lifecycle.js +50 -11
  31. package/dist/lib/task/local-artifact-finalization.js +13 -28
  32. package/dist/lib/task/review-command.js +1 -2
  33. package/dist/lib/task/review-finalization.js +1 -2
  34. package/dist/lib/task/snapshot.js +6 -6
  35. package/dist/lib/task/verification-engine.js +16 -11
  36. package/dist/lib/task/verification.js +1 -13
  37. package/dist/lib/task/workflow-warning-intents.js +2 -4
  38. package/dist/lib/task/write.js +1 -2
  39. package/dist/lifecycle-build-manifest.json +3 -3
  40. package/lib/decide.ts +5 -35
  41. package/lib/git/branch-worktree.ts +41 -0
  42. package/lib/internal/cli-route-inventory.ts +0 -2
  43. package/lib/internal/task-activity.ts +6 -34
  44. package/lib/internal/task-event.ts +4 -37
  45. package/lib/internal/task-finalization.ts +9 -2
  46. package/lib/internal/task-ledger.ts +5 -38
  47. package/lib/internal/task-lifecycle.ts +2 -2
  48. package/lib/internal/task-operation-registry.ts +1 -4
  49. package/lib/internal/task-review.ts +5 -31
  50. package/lib/internal/task-verify.ts +3 -39
  51. package/lib/internal/task-warning.ts +3 -32
  52. package/lib/platform/pr-summary.ts +4 -25
  53. package/lib/platform/verification-sync.ts +13 -53
  54. package/lib/sandbox/control/client.ts +5 -1
  55. package/lib/sandbox/control/executor.ts +13 -4
  56. package/lib/sandbox/control/protocol.ts +3 -2
  57. package/lib/sandbox/removal.ts +23 -7
  58. package/lib/task/activity-intent.ts +1 -2
  59. package/lib/task/artifact-operations.ts +58 -2
  60. package/lib/task/artifact-schema.ts +9 -7
  61. package/lib/task/control-authority.ts +14 -188
  62. package/lib/task/decision-intents.ts +2 -4
  63. package/lib/task/events.ts +8 -27
  64. package/lib/task/finalization-handoff.ts +104 -0
  65. package/lib/task/finalization.ts +120 -12
  66. package/lib/task/intermediate-cleanup.ts +9 -125
  67. package/lib/task/ledger-intents.ts +3 -6
  68. package/lib/task/lifecycle.ts +45 -13
  69. package/lib/task/local-artifact-finalization.ts +16 -35
  70. package/lib/task/review-command.ts +2 -5
  71. package/lib/task/review-finalization.ts +1 -4
  72. package/lib/task/snapshot.ts +6 -6
  73. package/lib/task/verification-engine.ts +20 -10
  74. package/lib/task/verification.ts +1 -15
  75. package/lib/task/workflow-warning-intents.ts +2 -4
  76. package/lib/task/write.ts +1 -4
  77. package/package.json +1 -1
  78. package/templates/.agents/skills/analyze-task/SKILL.en.md +11 -2
  79. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +11 -2
  80. package/templates/.agents/skills/code-task/reference/report-template.en.md +6 -6
  81. package/templates/.agents/skills/code-task/reference/report-template.zh-CN.md +6 -6
  82. package/templates/.agents/skills/complete-manual-validation/config/verify.en.json +2 -2
  83. package/templates/.agents/skills/complete-manual-validation/config/verify.zh-CN.json +2 -2
  84. package/templates/.agents/skills/complete-manual-validation/reference/report-template.en.md +1 -3
  85. package/templates/.agents/skills/complete-manual-validation/reference/report-template.zh-CN.md +1 -3
  86. package/templates/.agents/skills/complete-task/config/verify.en.json +2 -2
  87. package/templates/.agents/skills/complete-task/config/verify.zh-CN.json +2 -2
  88. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +3 -3
  89. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +3 -3
  90. package/templates/.agents/skills/review-code/reference/report-template.en.md +3 -3
  91. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +3 -3
  92. package/templates/.agents/skills/review-plan/reference/report-template.en.md +3 -3
  93. package/templates/.agents/skills/review-plan/reference/report-template.zh-CN.md +3 -3
  94. package/templates/.agents/skills/review-pr/config/verify.en.json +3 -1
  95. package/templates/.agents/skills/review-pr/config/verify.zh-CN.json +3 -1
  96. package/templates/.agents/skills/review-pr/reference/report-template.en.md +3 -3
  97. package/templates/.agents/skills/review-pr/reference/report-template.zh-CN.md +3 -3
  98. package/templates/.agents/skills/run-manual-validation/config/verify.en.json +2 -2
  99. package/templates/.agents/skills/run-manual-validation/config/verify.zh-CN.json +2 -2
  100. package/templates/.agents/skills/run-manual-validation/reference/report-template.en.md +2 -2
  101. package/templates/.agents/skills/run-manual-validation/reference/report-template.zh-CN.md +2 -2
  102. package/dist/lib/internal/task-override.js +0 -138
  103. package/dist/lib/task/artifact-recovery.js +0 -476
  104. package/dist/lib/task/artifact-repair-intent.js +0 -181
  105. package/dist/lib/task/guard-override.js +0 -31
  106. package/dist/lib/task/human-override.js +0 -1259
  107. package/lib/internal/task-override.ts +0 -144
  108. package/lib/task/artifact-recovery.ts +0 -572
  109. package/lib/task/artifact-repair-intent.ts +0 -227
  110. package/lib/task/guard-override.ts +0 -50
  111. package/lib/task/human-override.ts +0 -1522
@@ -1,227 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { isDeepStrictEqual } from 'node:util';
4
-
5
- import type { ArtifactSchemaFamily } from './artifact-schema.ts';
6
- import { parseArtifactName } from './artifact-name.ts';
7
-
8
- export type ArtifactRecoveryPhase =
9
- | 'orchestration.prepare'
10
- | 'artifact.finalize-local'
11
- | 'task-event.completed';
12
- export type ArtifactRecoveryState =
13
- | 'awaiting-preflight-recovery'
14
- | 'preflight-ready'
15
- | 'preflight-commit-started'
16
- | 'preflight-passed'
17
- | 'full-finalizer-ready'
18
- | 'commit-started'
19
- | 'passed'
20
- | 'consumption-started'
21
- | 'consumed'
22
- | 'aborted';
23
-
24
- export type ArtifactRecoveryIntent = Readonly<{
25
- version: 4;
26
- taskId: string;
27
- family: ArtifactSchemaFamily;
28
- artifact: string;
29
- round: number;
30
- state: ArtifactRecoveryState;
31
- baselineSha256: string;
32
- baselineSemanticDigest: string;
33
- stagingId: string;
34
- candidateSha256: string | null;
35
- preflightArtifactSha256: string | null;
36
- preflightSemanticDigest: string | null;
37
- activeGenerationSha256: string | null;
38
- activeGenerationSemanticDigest: string | null;
39
- pendingGenerationSha256: string | null;
40
- pendingGenerationSemanticDigest: string | null;
41
- finalArtifactSha256: string | null;
42
- finalSemanticDigest: string | null;
43
- recoveryOperationId: string;
44
- phase: ArtifactRecoveryPhase | null;
45
- authorityDigest: string | null;
46
- requestId: string;
47
- errorCode: string | null;
48
- errorMessage: string | null;
49
- createdAt: number;
50
- updatedAt: number;
51
- }>;
52
-
53
- export function artifactRecoveryIntentRoot(repoRoot: string): string {
54
- return path.join(repoRoot, '.agents', 'workspace', '.local-artifact-finalization-intents');
55
- }
56
-
57
- export function artifactRecoveryRoot(taskDir: string, stagingId: string): string {
58
- return path.join(taskDir, '.local-artifact-recovery', stagingId);
59
- }
60
-
61
- function intentPath(repoRoot: string, taskId: string, family: ArtifactSchemaFamily, artifact: string): string {
62
- return path.join(artifactRecoveryIntentRoot(repoRoot), `${taskId}-${family}-${artifact}.json`);
63
- }
64
-
65
- function validDigest(value: unknown): value is string {
66
- return typeof value === 'string' && /^[a-f0-9]{64}$/u.test(value);
67
- }
68
-
69
- function validTaskId(value: unknown): value is string {
70
- return typeof value === 'string' && /^TASK-\d{8}-\d{6}$/u.test(value);
71
- }
72
-
73
- function validToken(value: unknown): value is string {
74
- return typeof value === 'string' && value.length > 0 && !/[\r\n]/u.test(value);
75
- }
76
-
77
- function validRecoveryId(value: unknown): value is string {
78
- return typeof value === 'string' && /^[a-f0-9-]{16,64}$/u.test(value);
79
- }
80
-
81
- function validArtifact(value: unknown, family: unknown, round: unknown): value is string {
82
- if (typeof value !== 'string' || path.basename(value) !== value || !value.endsWith('.md')) return false;
83
- const parsed = parseArtifactName(value);
84
- return Boolean(parsed && parsed.family === family && parsed.round === round);
85
- }
86
-
87
- function exactKeys(value: Record<string, unknown>, keys: readonly string[]): boolean {
88
- return Object.keys(value).sort().join(',') === [...keys].sort().join(',');
89
- }
90
-
91
- export function isArtifactRecoveryIntent(value: unknown): value is ArtifactRecoveryIntent {
92
- if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
93
- const intent = value as Record<string, unknown>;
94
- return exactKeys(intent, [
95
- 'activeGenerationSemanticDigest', 'activeGenerationSha256', 'artifact', 'authorityDigest', 'baselineSemanticDigest', 'baselineSha256', 'candidateSha256',
96
- 'createdAt', 'errorCode', 'errorMessage', 'family', 'finalArtifactSha256', 'finalSemanticDigest',
97
- 'pendingGenerationSemanticDigest', 'pendingGenerationSha256', 'phase', 'preflightArtifactSha256', 'preflightSemanticDigest', 'recoveryOperationId', 'requestId', 'round', 'stagingId', 'state', 'taskId', 'updatedAt',
98
- 'version'
99
- ])
100
- && intent.version === 4
101
- && validTaskId(intent.taskId)
102
- && typeof intent.family === 'string'
103
- && ['analysis', 'review-analysis', 'plan', 'review-plan', 'code', 'review-code'].includes(intent.family)
104
- && Number.isSafeInteger(intent.round) && (intent.round as number) > 0
105
- && validArtifact(intent.artifact, intent.family, intent.round)
106
- && ['awaiting-preflight-recovery', 'preflight-ready', 'preflight-commit-started', 'preflight-passed', 'full-finalizer-ready', 'commit-started', 'passed', 'consumption-started', 'consumed', 'aborted'].includes(String(intent.state))
107
- && validDigest(intent.baselineSha256)
108
- && validDigest(intent.baselineSemanticDigest)
109
- && validRecoveryId(intent.stagingId)
110
- && (intent.candidateSha256 === null || validDigest(intent.candidateSha256))
111
- && (intent.preflightArtifactSha256 === null || validDigest(intent.preflightArtifactSha256))
112
- && (intent.preflightSemanticDigest === null || validDigest(intent.preflightSemanticDigest))
113
- && (intent.activeGenerationSha256 === null || validDigest(intent.activeGenerationSha256))
114
- && (intent.activeGenerationSemanticDigest === null || validDigest(intent.activeGenerationSemanticDigest))
115
- && (intent.pendingGenerationSha256 === null || validDigest(intent.pendingGenerationSha256))
116
- && (intent.pendingGenerationSemanticDigest === null || validDigest(intent.pendingGenerationSemanticDigest))
117
- && (intent.finalArtifactSha256 === null || validDigest(intent.finalArtifactSha256))
118
- && (intent.finalSemanticDigest === null || validDigest(intent.finalSemanticDigest))
119
- && validRecoveryId(intent.recoveryOperationId)
120
- && intent.stagingId === intent.recoveryOperationId
121
- && (intent.phase === null || ['orchestration.prepare', 'artifact.finalize-local', 'task-event.completed'].includes(String(intent.phase)))
122
- && (intent.authorityDigest === null || validDigest(intent.authorityDigest))
123
- && validToken(intent.requestId)
124
- && (intent.errorCode === null || validToken(intent.errorCode))
125
- && (intent.errorMessage === null || validToken(intent.errorMessage))
126
- && Number.isSafeInteger(intent.createdAt)
127
- && Number.isSafeInteger(intent.updatedAt)
128
- && (intent.state === 'awaiting-preflight-recovery'
129
- ? intent.preflightArtifactSha256 === null && intent.preflightSemanticDigest === null
130
- && intent.activeGenerationSha256 === null && intent.activeGenerationSemanticDigest === null
131
- && intent.pendingGenerationSha256 === null && intent.pendingGenerationSemanticDigest === null
132
- && intent.finalArtifactSha256 === null && intent.finalSemanticDigest === null
133
- : true)
134
- && (intent.state === 'preflight-ready' || intent.state === 'preflight-commit-started' || intent.state === 'preflight-passed' || intent.state === 'full-finalizer-ready' || intent.state === 'commit-started' || intent.state === 'passed' || intent.state === 'consumed'
135
- ? validDigest(intent.candidateSha256) && validDigest(intent.preflightArtifactSha256) && validDigest(intent.preflightSemanticDigest)
136
- && validDigest(intent.activeGenerationSha256) && validDigest(intent.activeGenerationSemanticDigest)
137
- : true)
138
- && (intent.state === 'full-finalizer-ready' || intent.state === 'commit-started'
139
- ? validDigest(intent.pendingGenerationSha256) && validDigest(intent.pendingGenerationSemanticDigest)
140
- && validDigest(intent.finalArtifactSha256) && validDigest(intent.finalSemanticDigest)
141
- : true)
142
- && (intent.state === 'passed' || intent.state === 'consumption-started' || intent.state === 'consumed'
143
- ? validDigest(intent.finalArtifactSha256) && validDigest(intent.finalSemanticDigest)
144
- : true)
145
- && (intent.state === 'aborted' ? intent.errorCode !== null && intent.errorMessage !== null : true);
146
- }
147
-
148
- export function readArtifactRecoveryIntent(
149
- repoRoot: string,
150
- taskId: string,
151
- family: ArtifactSchemaFamily,
152
- artifact: string
153
- ): ArtifactRecoveryIntent | null {
154
- if (!validTaskId(taskId) || !validArtifact(artifact, family, parseArtifactName(artifact)?.round)) {
155
- throw new Error('ARTIFACT_RECOVERY_INTENT_INVALID: recovery journal identity is invalid');
156
- }
157
- const target = intentPath(repoRoot, taskId, family, artifact);
158
- if (!fs.existsSync(target)) return null;
159
- let value: unknown;
160
- try { value = JSON.parse(fs.readFileSync(target, 'utf8')) as unknown; }
161
- catch (error) { throw new Error(`ARTIFACT_RECOVERY_INTENT_INVALID: ${String(error)}`); }
162
- if (!isArtifactRecoveryIntent(value) || value.taskId !== taskId || value.family !== family || value.artifact !== artifact) {
163
- throw new Error('ARTIFACT_RECOVERY_INTENT_INVALID: recovery journal schema is invalid');
164
- }
165
- return value;
166
- }
167
-
168
- export function writeArtifactRecoveryIntent(
169
- repoRoot: string,
170
- value: unknown,
171
- options: Readonly<{ expected?: ArtifactRecoveryIntent | null }> = {}
172
- ): void {
173
- if (!isArtifactRecoveryIntent(value)) throw new Error('ARTIFACT_RECOVERY_INTENT_INVALID: recovery journal schema is invalid');
174
- const intent = value;
175
- const directory = artifactRecoveryIntentRoot(repoRoot);
176
- fs.mkdirSync(directory, { recursive: true, mode: 0o700 });
177
- const target = intentPath(repoRoot, intent.taskId, intent.family, intent.artifact);
178
- const lock = `${target}.lock`;
179
- let descriptor: number;
180
- try { descriptor = fs.openSync(lock, 'wx', 0o600); }
181
- catch (error) {
182
- if ((error as NodeJS.ErrnoException).code === 'EEXIST') {
183
- throw new Error('ARTIFACT_RECOVERY_INTENT_CONFLICT: another journal writer owns the intent');
184
- }
185
- throw error;
186
- }
187
- try {
188
- const current = fs.existsSync(target)
189
- ? readArtifactRecoveryIntent(repoRoot, intent.taskId, intent.family, intent.artifact)
190
- : null;
191
- if (!isDeepStrictEqual(current, options.expected ?? null)) {
192
- throw new Error('ARTIFACT_RECOVERY_INTENT_CONFLICT: recovery journal changed during finalization');
193
- }
194
- const temporary = `${target}.${process.pid}.${Date.now()}.tmp`;
195
- fs.writeFileSync(temporary, `${JSON.stringify(intent)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
196
- try { fs.renameSync(temporary, target); }
197
- catch (error) {
198
- try { fs.unlinkSync(temporary); } catch { /* preserve the primary error */ }
199
- throw error;
200
- }
201
- } finally {
202
- fs.closeSync(descriptor);
203
- try { fs.unlinkSync(lock); } catch { /* preserve the primary result */ }
204
- }
205
- }
206
-
207
- export function findArtifactRecoveryIntentsByOperation(
208
- repoRoot: string,
209
- operationId: string
210
- ): readonly ArtifactRecoveryIntent[] {
211
- if (!validToken(operationId)) throw new Error('ARTIFACT_RECOVERY_OPERATION_INVALID: recovery operation id is invalid');
212
- const directory = artifactRecoveryIntentRoot(repoRoot);
213
- if (!fs.existsSync(directory)) return Object.freeze([]);
214
- return Object.freeze(fs.readdirSync(directory)
215
- .filter((name) => name.endsWith('.json'))
216
- .map((name) => {
217
- const target = path.join(directory, name);
218
- let value: unknown;
219
- try { value = JSON.parse(fs.readFileSync(target, 'utf8')) as unknown; }
220
- catch (error) { throw new Error(`ARTIFACT_RECOVERY_INTENT_INVALID: ${String(error)}`); }
221
- if (!isArtifactRecoveryIntent(value)) throw new Error('ARTIFACT_RECOVERY_INTENT_INVALID: recovery journal schema is invalid');
222
- return value;
223
- })
224
- .filter((value) => value.recoveryOperationId === operationId));
225
- }
226
-
227
- export { intentPath as artifactRecoveryIntentPath };
@@ -1,50 +0,0 @@
1
- type ManualOverrideCapability = Readonly<{
2
- failureId: string;
3
- operator: string;
4
- reason: string;
5
- }>;
6
-
7
- type GuardProducer = Readonly<{
8
- producerId: string;
9
- guardId: `G-${string}`;
10
- code: string;
11
- }>;
12
-
13
- const guardProducerCatalog: readonly GuardProducer[] = [
14
- { producerId: 'task.resolve', guardId: 'G-01', code: 'TASK_NOT_FOUND' },
15
- { producerId: 'task.resolve', guardId: 'G-01', code: 'TASK_IDENTITY_CONFLICT' },
16
- { producerId: 'task.write', guardId: 'G-02', code: 'TASK_STATE_MISMATCH' },
17
- { producerId: 'task-event', guardId: 'G-04', code: 'TASK_STATE_MISMATCH' },
18
- { producerId: 'task-event', guardId: 'G-04', code: 'EVENT_TRANSITION_INVALID' },
19
- { producerId: 'task-event', guardId: 'G-04', code: 'EVENT_START_MISSING' },
20
- { producerId: 'task-verify', guardId: 'G-05', code: 'VERIFY_TASK_STATE_MISMATCH' },
21
- { producerId: 'task-verify', guardId: 'G-05', code: 'VERIFY_ARTIFACT_INVALID' },
22
- { producerId: 'verification-engine', guardId: 'G-06', code: 'CHECK_FAILED' },
23
- { producerId: 'verification-engine', guardId: 'G-06', code: 'CHECK_BLOCKED' },
24
- { producerId: 'activity-intent', guardId: 'G-07', code: 'TASK_STATE_MISMATCH' },
25
- { producerId: 'ledger-intent', guardId: 'G-07', code: 'TASK_STATE_MISMATCH' },
26
- { producerId: 'decision-intent', guardId: 'G-07', code: 'TASK_STATE_MISMATCH' },
27
- { producerId: 'workflow-warning', guardId: 'G-07', code: 'TASK_STATE_MISMATCH' },
28
- { producerId: 'review-finalization', guardId: 'G-07', code: 'TASK_STATE_MISMATCH' },
29
- { producerId: 'ledger-intent', guardId: 'G-08', code: 'LEDGER_TRANSITION_INVALID' },
30
- { producerId: 'lifecycle-execution', guardId: 'G-09', code: 'ORCHESTRATION_STANDALONE_BUSY' },
31
- { producerId: 'lifecycle-execution', guardId: 'G-09', code: 'ORCHESTRATION_PROVENANCE_MISMATCH' },
32
- { producerId: 'lifecycle-execution', guardId: 'G-09', code: 'ORCHESTRATION_STATE_INVALID' },
33
- { producerId: 'platform.issue', guardId: 'G-10', code: 'PLATFORM_BIND_FAILED' },
34
- { producerId: 'platform.pull-request', guardId: 'G-10', code: 'PLATFORM_BIND_FAILED' }
35
- ];
36
-
37
- function guardFailureId(producerId: string, code: string): string {
38
- return `${producerId}:${code}`;
39
- }
40
-
41
- function allowsManualOverride(
42
- capability: ManualOverrideCapability | undefined,
43
- producerId: string,
44
- code: string
45
- ): boolean {
46
- return capability?.failureId === guardFailureId(producerId, code);
47
- }
48
-
49
- export { allowsManualOverride, guardFailureId, guardProducerCatalog };
50
- export type { GuardProducer, ManualOverrideCapability };