@fitlab-ai/agent-infra 0.11.12 → 0.11.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 (120) hide show
  1. package/dist/bin/internal-cli.js +2 -7
  2. package/dist/lib/agent-clients/adapter.js +0 -3
  3. package/dist/lib/agent-clients/adapters/codex-lifecycle/app-server.js +5 -9
  4. package/dist/lib/agent-clients/adapters/codex-lifecycle/cli.js +1 -5
  5. package/dist/lib/agent-clients/adapters/codex-lifecycle/recovery.js +1 -5
  6. package/dist/lib/agent-clients/adapters/codex-lifecycle/store.js +11 -25
  7. package/dist/lib/agent-clients/adapters/codex-orchestration.js +1 -3
  8. package/dist/lib/agent-clients/adapters/codex.js +0 -2
  9. package/dist/lib/internal/cli-route-inventory.js +0 -1
  10. package/dist/lib/internal/sandbox-control.js +1 -81
  11. package/dist/lib/internal/task-finalization.js +29 -20
  12. package/dist/lib/internal/task-lifecycle.js +4 -2
  13. package/dist/lib/internal/task-operation-registry.js +1 -3
  14. package/dist/lib/internal/task-validate.js +14 -124
  15. package/dist/lib/platform/github-client.js +33 -3
  16. package/dist/lib/platform/release-notes.js +2 -2
  17. package/dist/lib/sandbox/commands/control-status.js +0 -1
  18. package/dist/lib/sandbox/commands/create.js +11 -6
  19. package/dist/lib/sandbox/commands/ls.js +4 -5
  20. package/dist/lib/sandbox/commands/rm.js +1 -1
  21. package/dist/lib/sandbox/config.js +12 -0
  22. package/dist/lib/sandbox/control/audit.js +1 -2
  23. package/dist/lib/sandbox/control/client.js +15 -110
  24. package/dist/lib/sandbox/control/executor.js +9 -59
  25. package/dist/lib/sandbox/control/host-recovery.js +89 -27
  26. package/dist/lib/sandbox/control/lifecycle.js +75 -9
  27. package/dist/lib/sandbox/control/protocol.js +11 -50
  28. package/dist/lib/sandbox/control/server.js +203 -253
  29. package/dist/lib/sandbox/control/task-view.js +0 -13
  30. package/dist/lib/sandbox/environment.js +7 -8
  31. package/dist/lib/sandbox/mounts.js +71 -52
  32. package/dist/lib/sandbox/recovery.js +30 -12
  33. package/dist/lib/sandbox/removal.js +37 -3
  34. package/dist/lib/sandbox/workspace-identity.js +18 -6
  35. package/dist/lib/sandbox/workspace-view.js +89 -6
  36. package/dist/lib/task/commands/ls.js +3 -3
  37. package/dist/lib/task/control-authority.js +41 -17
  38. package/dist/lib/task/control-recovery.js +2 -4
  39. package/dist/lib/task/finalization.js +27 -2
  40. package/dist/lib/task/lifecycle.js +294 -63
  41. package/dist/lib/task/orchestration.js +26 -72
  42. package/dist/lib/task/short-id.js +37 -27
  43. package/dist/lib/task/verification-engine.js +4 -11
  44. package/dist/lifecycle-build-manifest.json +3 -3
  45. package/lib/agent-clients/adapter.ts +0 -27
  46. package/lib/agent-clients/adapters/codex-lifecycle/app-server.ts +6 -12
  47. package/lib/agent-clients/adapters/codex-lifecycle/cli.ts +1 -5
  48. package/lib/agent-clients/adapters/codex-lifecycle/manifest-files.json +0 -7
  49. package/lib/agent-clients/adapters/codex-lifecycle/recovery.ts +1 -5
  50. package/lib/agent-clients/adapters/codex-lifecycle/store.ts +21 -27
  51. package/lib/agent-clients/adapters/codex-orchestration.ts +1 -3
  52. package/lib/agent-clients/adapters/codex.ts +0 -2
  53. package/lib/internal/cli-route-inventory.ts +0 -1
  54. package/lib/internal/sandbox-control.ts +0 -97
  55. package/lib/internal/task-finalization.ts +33 -19
  56. package/lib/internal/task-lifecycle.ts +4 -2
  57. package/lib/internal/task-operation-registry.ts +1 -3
  58. package/lib/internal/task-validate.ts +13 -127
  59. package/lib/platform/github-client.ts +34 -3
  60. package/lib/platform/release-notes.ts +2 -2
  61. package/lib/sandbox/commands/control-status.ts +0 -1
  62. package/lib/sandbox/commands/create.ts +11 -5
  63. package/lib/sandbox/commands/ls.ts +4 -5
  64. package/lib/sandbox/commands/rm.ts +1 -1
  65. package/lib/sandbox/config.ts +13 -0
  66. package/lib/sandbox/control/audit.ts +1 -2
  67. package/lib/sandbox/control/client.ts +17 -138
  68. package/lib/sandbox/control/executor.ts +8 -65
  69. package/lib/sandbox/control/host-recovery.ts +94 -21
  70. package/lib/sandbox/control/lifecycle.ts +75 -10
  71. package/lib/sandbox/control/protocol.ts +12 -62
  72. package/lib/sandbox/control/server.ts +11 -61
  73. package/lib/sandbox/control/task-view.ts +0 -19
  74. package/lib/sandbox/environment.ts +7 -8
  75. package/lib/sandbox/mounts.ts +93 -68
  76. package/lib/sandbox/recovery.ts +37 -19
  77. package/lib/sandbox/removal.ts +36 -5
  78. package/lib/sandbox/workspace-identity.ts +16 -6
  79. package/lib/sandbox/workspace-view.ts +81 -7
  80. package/lib/task/commands/ls.ts +3 -3
  81. package/lib/task/control-authority.ts +41 -26
  82. package/lib/task/control-recovery.ts +3 -5
  83. package/lib/task/finalization.ts +29 -2
  84. package/lib/task/lifecycle.ts +282 -57
  85. package/lib/task/orchestration.ts +30 -68
  86. package/lib/task/short-id.ts +33 -40
  87. package/lib/task/verification-engine.ts +3 -9
  88. package/package.json +1 -1
  89. package/templates/.agents/rules/README.en.md +1 -0
  90. package/templates/.agents/rules/README.zh-CN.md +1 -0
  91. package/templates/.agents/rules/lifecycle-orchestration.en.md +3 -4
  92. package/templates/.agents/rules/lifecycle-orchestration.zh-CN.md +3 -4
  93. package/templates/.agents/rules/strategy-pattern.en.md +25 -0
  94. package/templates/.agents/rules/strategy-pattern.zh-CN.md +25 -0
  95. package/templates/.agents/rules/task-short-id.en.md +18 -12
  96. package/templates/.agents/rules/task-short-id.zh-CN.md +12 -7
  97. package/templates/.agents/skills/code-task/reference/code-rules.en.md +4 -0
  98. package/templates/.agents/skills/code-task/reference/code-rules.zh-CN.md +4 -0
  99. package/templates/.agents/skills/complete-task/SKILL.en.md +5 -26
  100. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +5 -23
  101. package/templates/.agents/skills/create-release-note/SKILL.en.md +3 -1
  102. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +3 -1
  103. package/templates/.agents/skills/plan-task/SKILL.en.md +7 -4
  104. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +7 -4
  105. package/templates/.agents/skills/run-task/SKILL.en.md +2 -2
  106. package/templates/.agents/skills/run-task/SKILL.zh-CN.md +2 -2
  107. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-client.js +0 -130
  108. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-context.js +0 -127
  109. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-operation.js +0 -131
  110. package/dist/lib/agent-clients/adapters/codex-lifecycle/controller-registration.js +0 -275
  111. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.js +0 -106
  112. package/dist/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.js +0 -345
  113. package/dist/lib/sandbox/control/agent-operation.js +0 -34
  114. package/lib/agent-clients/adapters/codex-lifecycle/controller-client.ts +0 -158
  115. package/lib/agent-clients/adapters/codex-lifecycle/controller-context.ts +0 -163
  116. package/lib/agent-clients/adapters/codex-lifecycle/controller-operation.ts +0 -151
  117. package/lib/agent-clients/adapters/codex-lifecycle/controller-registration.ts +0 -352
  118. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller-cli.ts +0 -109
  119. package/lib/agent-clients/adapters/codex-lifecycle/sandbox-controller.ts +0 -437
  120. package/lib/sandbox/control/agent-operation.ts +0 -49
@@ -1,6 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { normalizeAgentToken } from '../agent-clients/tokens.js';
3
3
  import { isAgentClientId } from '../agent-clients/types.js';
4
+ import { sandboxControlPaths } from '../sandbox/workspace-view.js';
4
5
  import { getAgentClientAdapter } from '../agent-clients/registry.js';
5
6
  import { activateMatchingOrchestrationDelegation, activateOrchestrationDelegation, advanceOrchestration, awaitOrchestrationDelegationActivation, beginOrResumeOrchestration, dispatchOrchestrationDelegation, OrchestrationStateError, pauseOrchestration, prepareOrchestrationDelegation, recoverPreparedOrchestrationDelegation, routeOrchestration, sealMatchingOrchestrationDelegation, sealOrchestrationDelegation, statusOrchestration } from './orchestration.js';
6
7
  import { applyTaskFinalization } from './finalization.js';
@@ -25,21 +26,14 @@ function absolute(name, value) {
25
26
  invalidContext(`${name} must be absolute`);
26
27
  return path.resolve(value);
27
28
  }
28
- function binding(value) {
29
- if (value === null || value === undefined)
30
- return value;
31
- if (!/^[a-f0-9]{64}$/u.test(value.instanceDigest) || !value.controlGeneration) {
32
- invalidContext('controller binding is invalid');
33
- }
34
- return value;
35
- }
36
29
  export function createDirectHostExecutionContext(params) {
37
30
  return {
38
31
  source: 'direct-host',
39
32
  mode: 'direct-host',
40
33
  repoRoot: absolute('repoRoot', params.repoRoot),
41
- ...(params.runtimeDir === undefined ? {} : { runtimeDir: absolute('runtimeDir', params.runtimeDir) }),
42
- ...(params.controllerBinding === undefined ? {} : { controllerBinding: binding(params.controllerBinding) }),
34
+ ...(params.controlBase === undefined ? {} : { controlBase: absolute('controlBase', params.controlBase) }),
35
+ ...(params.project === undefined ? {} : { project: params.project }),
36
+ ...(params.runtimeDir === undefined ? {} : { runtimeDir: absolute('runtimeDir', params.runtimeDir) })
43
37
  };
44
38
  }
45
39
  export function createSandboxExecutorExecutionContext(params) {
@@ -59,8 +53,7 @@ export function createSandboxExecutorExecutionContext(params) {
59
53
  taskId: params.taskId,
60
54
  generation: params.generation,
61
55
  manifestPath: absolute('manifestPath', params.manifestPath),
62
- requestId: params.requestId,
63
- ...(params.controllerBinding === undefined ? {} : { controllerBinding: binding(params.controllerBinding) }),
56
+ requestId: params.requestId
64
57
  };
65
58
  }
66
59
  export function assertTaskControlExecutionContext(context) {
@@ -70,7 +63,10 @@ export function assertTaskControlExecutionContext(context) {
70
63
  absolute('repoRoot', context.repoRoot);
71
64
  if (context.runtimeDir !== undefined)
72
65
  absolute('runtimeDir', context.runtimeDir);
73
- binding(context.controllerBinding);
66
+ if (Boolean(context.controlBase) !== Boolean(context.project))
67
+ invalidContext('control configuration is incomplete');
68
+ if (context.controlBase !== undefined)
69
+ absolute('controlBase', context.controlBase);
74
70
  return;
75
71
  }
76
72
  if (context.mode !== 'task-bound-sandbox' || !/^TASK-\d{8}-\d{6}$/u.test(context.taskId)
@@ -84,7 +80,6 @@ export function assertTaskControlExecutionContext(context) {
84
80
  if (path.resolve(context.runtimeDir) !== path.join(path.dirname(path.resolve(context.manifestPath)), 'runtime')) {
85
81
  invalidContext('runtimeDir is not bound to the manifest control root');
86
82
  }
87
- binding(context.controllerBinding);
88
83
  }
89
84
  function boundTaskRef(context, taskRef) {
90
85
  return context.source === 'sandbox-executor' ? context.taskId : taskRef;
@@ -115,6 +110,8 @@ function lifecycleTaskId(request, repoRoot) {
115
110
  }
116
111
  }
117
112
  async function applyLifecycleWithAuthority(context, request) {
113
+ const taskId = lifecycleTaskId(request, context.repoRoot);
114
+ const controlRoot = taskId ? controlRootForTask(context, taskId) : undefined;
118
115
  const execute = async (underTaskLock = false) => {
119
116
  if (request.intent === 'recover-started') {
120
117
  const adapter = isAgentClientId(request.agent)
@@ -130,10 +127,17 @@ async function applyLifecycleWithAuthority(context, request) {
130
127
  return adapter.recoverStarted(request, { repoRoot: context.repoRoot });
131
128
  }
132
129
  return underTaskLock
133
- ? applyTaskLifecycleWithinTaskLock(request, { repoRoot: context.repoRoot }, taskId)
134
- : applyTaskLifecycle(request, { repoRoot: context.repoRoot });
130
+ ? applyTaskLifecycleWithinTaskLock(request, {
131
+ repoRoot: context.repoRoot,
132
+ ...(controlRoot ? { controlRoot } : {}),
133
+ ...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
134
+ }, taskId)
135
+ : applyTaskLifecycle(request, {
136
+ repoRoot: context.repoRoot,
137
+ ...(controlRoot ? { controlRoot } : {}),
138
+ ...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {})
139
+ });
135
140
  };
136
- const taskId = lifecycleTaskId(request, context.repoRoot);
137
141
  if (!taskId)
138
142
  return await execute();
139
143
  try {
@@ -153,6 +157,18 @@ async function applyLifecycleWithAuthority(context, request) {
153
157
  return taskLifecycleFailure(request, { code: error.code, message: error.message }, taskId);
154
158
  }
155
159
  }
160
+ function controlRootForTask(context, taskId) {
161
+ if (context.source === 'sandbox-executor')
162
+ return path.dirname(context.manifestPath);
163
+ if (!context.controlBase || !context.project)
164
+ return undefined;
165
+ return sandboxControlPaths({
166
+ base: context.controlBase,
167
+ project: context.project,
168
+ container: '',
169
+ identity: { mode: 'task-bound', taskId }
170
+ }).root;
171
+ }
156
172
  function orchestration(context, operation) {
157
173
  const taskRef = boundTaskRef(context, operation.taskRef);
158
174
  const input = operation.input;
@@ -219,6 +235,10 @@ export function dispatchTaskControlOperation(context, operation) {
219
235
  });
220
236
  }
221
237
  if (operation.family === 'task-finalization') {
238
+ const resolved = resolveTaskRef(boundTaskRef(context, operation.request.taskRef), { repoRoot: context.repoRoot });
239
+ const controlRoot = context.source === 'sandbox-executor'
240
+ ? path.dirname(context.manifestPath)
241
+ : resolved.ok ? controlRootForTask(context, resolved.taskId) : undefined;
222
242
  return applyTaskFinalization({
223
243
  ...operation.request,
224
244
  taskRef: boundTaskRef(context, operation.request.taskRef)
@@ -228,6 +248,8 @@ export function dispatchTaskControlOperation(context, operation) {
228
248
  controlBinding: { generation: context.generation, requestId: context.requestId },
229
249
  manifestPath: context.manifestPath
230
250
  } : {}),
251
+ ...(controlRoot ? { controlRoot } : {}),
252
+ ...(context.source === 'direct-host' && context.project ? { controlProject: context.project } : {}),
231
253
  preflight: (request, options) => verifyTaskEvent({ ...request, event: 'complete-task.hard-preflight' }, options)
232
254
  });
233
255
  }
@@ -320,6 +342,8 @@ export function parseTaskControlOperation(family, args) {
320
342
  const taskRef = args[0];
321
343
  const intent = args[1];
322
344
  if (family === 'task-lifecycle') {
345
+ if (intent === 'complete')
346
+ operationInvalid('complete must use task-finalization');
323
347
  const values = parseValues(args, 2, LIFECYCLE_FLAGS);
324
348
  const agent = normalizeAgentToken(value(values, '--agent') ?? '');
325
349
  if (!agent)
@@ -16,12 +16,10 @@ export function parseControlOutput(output) {
16
16
  export const SANDBOX_CONTROL_REQUIRED_COMPLETION_PHASES = Object.freeze([
17
17
  'completed', 'evidence-written', 'publish-authorized'
18
18
  ]);
19
- const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'complete', 'close-codescan', 'close-dependabot', 'restore', 'recover-started'];
19
+ const LIFECYCLE_INTENTS = ['block', 'activate', 'cancel', 'close-codescan', 'close-dependabot', 'restore', 'recover-started'];
20
20
  export const SANDBOX_CONTROL_RECOVERY_OPERATIONS = Object.freeze([
21
21
  ...LIFECYCLE_INTENTS.map((intent) => ({ family: 'task-lifecycle', intent, class: 'lifecycle-mutation' })),
22
- { family: 'task-finalization', intent: 'complete', class: 'finalization' },
23
- { family: 'task-create', intent: 'create', class: 'task-create' },
24
- ...['controller.close', 'controller.verify'].map((intent) => ({ family: 'agent-client', intent, class: 'agent-client-operation' }))
22
+ { family: 'task-create', intent: 'create', class: 'task-create' }
25
23
  ]);
26
24
  export function digestControlRecoveryIntent(family, intent) {
27
25
  return createHash('sha256').update(`${family}\0${intent}`, 'utf8').digest('hex');
@@ -894,7 +894,13 @@ async function prepareUnderLock(request, taskId, options) {
894
894
  receipt = updateReceipt(repoRoot, receipt, { lifecycle: 'done', lastError: null });
895
895
  }
896
896
  else {
897
- const result = lifecycle({ taskRef: taskId, intent: 'complete', agent: request.agent }, { repoRoot, prepareOnly: true, ...(options.metadataProvider ? { metadataProvider: options.metadataProvider } : {}) });
897
+ const result = lifecycle({ taskRef: taskId, intent: 'complete', agent: request.agent }, {
898
+ repoRoot,
899
+ prepareOnly: true,
900
+ ...(options.controlRoot ? { controlRoot: options.controlRoot } : {}),
901
+ ...(options.controlProject ? { controlProject: options.controlProject } : {}),
902
+ ...(options.metadataProvider ? { metadataProvider: options.metadataProvider } : {})
903
+ });
898
904
  lifecycleResult = lifecycleStep(result);
899
905
  if (result.status !== 'applied' && result.status !== 'no-op') {
900
906
  receipt = updateReceipt(repoRoot, receipt, { lifecycle: 'pending', lastError: lifecycleResult.error });
@@ -1037,7 +1043,12 @@ async function commitPreparedTaskFinalization(request, options) {
1037
1043
  });
1038
1044
  receipt = updateReceipt(repoRoot, receipt, { verification: 'pending' });
1039
1045
  const lifecycleRequest = { taskRef: resolved.taskId, intent: 'complete', agent: request.agent };
1040
- const lifecycleOptions = { repoRoot, ...(options.metadataProvider ? { metadataProvider: options.metadataProvider } : {}) };
1046
+ const lifecycleOptions = {
1047
+ repoRoot,
1048
+ ...(options.controlRoot ? { controlRoot: options.controlRoot } : {}),
1049
+ ...(options.controlProject ? { controlProject: options.controlProject } : {}),
1050
+ ...(options.metadataProvider ? { metadataProvider: options.metadataProvider } : {})
1051
+ };
1041
1052
  const result = options.lifecycle
1042
1053
  ? options.lifecycle(lifecycleRequest, lifecycleOptions)
1043
1054
  : applyTaskLifecycleWithinTaskLock(lifecycleRequest, lifecycleOptions, resolved.taskId);
@@ -1133,6 +1144,20 @@ async function applyTaskFinalization(request, options) {
1133
1144
  const prepared = await prepareTaskFinalization(request, options);
1134
1145
  if (prepared.status !== 'prepared')
1135
1146
  return prepared;
1147
+ if (options.beforeLifecycle) {
1148
+ try {
1149
+ await options.beforeLifecycle(prepared.taskId);
1150
+ }
1151
+ catch (error) {
1152
+ const detail = errorOf(error, 'TASK_FINALIZATION_PRE_LIFECYCLE_FAILED', true);
1153
+ return failed(prepared.taskId, detail, {
1154
+ changed: prepared.changed,
1155
+ completedSteps: prepared.completedSteps,
1156
+ pendingSteps: prepared.pendingSteps,
1157
+ warnings: prepared.warnings
1158
+ });
1159
+ }
1160
+ }
1136
1161
  return commitPreparedTaskFinalization(request, options);
1137
1162
  }
1138
1163
  export { applyFinalizationReceiptMutation, commitPreparedTaskFinalization, applyTaskFinalization, prepareTaskFinalization, issueCapability as createFinalizationCapability, readTaskFinalizationReceipt, terminalResult };