@gajae-code/coding-agent 0.18.6 → 0.18.8

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 (302) hide show
  1. package/CHANGELOG.md +318 -1
  2. package/dist/types/async/job-manager.d.ts +1 -1
  3. package/dist/types/capability/mcp.d.ts +2 -0
  4. package/dist/types/capability/skill.d.ts +2 -0
  5. package/dist/types/capability/types.d.ts +6 -0
  6. package/dist/types/cli/public-command-errors.d.ts +3 -1
  7. package/dist/types/cli/setup-cli.d.ts +1 -1
  8. package/dist/types/commands/deep-interview.d.ts +3 -0
  9. package/dist/types/config/autorouting-tier-map.d.ts +348 -9
  10. package/dist/types/config/file-lock.d.ts +1 -0
  11. package/dist/types/config/model-bindings-applier.d.ts +2 -0
  12. package/dist/types/config/model-profile-activation.d.ts +11 -3
  13. package/dist/types/config/model-registry.d.ts +4 -9
  14. package/dist/types/config/settings.d.ts +4 -0
  15. package/dist/types/config/skill-settings-defaults.d.ts +2 -0
  16. package/dist/types/cursor-delete-path.d.ts +1 -0
  17. package/dist/types/cursor-mcp-name.d.ts +8 -0
  18. package/dist/types/customization/inventory.d.ts +2 -0
  19. package/dist/types/debug/report-bundle-parent.d.ts +2 -0
  20. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.d.ts +1 -0
  21. package/dist/types/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.d.ts +31 -0
  22. package/dist/types/defaults/gjc-skills.generated.d.ts +5 -6
  23. package/dist/types/discovery/helpers.d.ts +8 -3
  24. package/dist/types/export/html/css-color.d.ts +2 -0
  25. package/dist/types/export/html/template.generated.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/types.d.ts +7 -0
  27. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +14 -1
  28. package/dist/types/extensibility/plugins/marketplace/cache.d.ts +2 -0
  29. package/dist/types/extensibility/plugins/plugin-link-path.d.ts +2 -0
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +3 -1
  31. package/dist/types/extensibility/skill-management.d.ts +3 -1
  32. package/dist/types/extensibility/skills.d.ts +2 -0
  33. package/dist/types/gjc-runtime/deep-interview-crystallize.d.ts +74 -0
  34. package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +11 -0
  35. package/dist/types/gjc-runtime/gc-runtime.d.ts +5 -0
  36. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +0 -5
  37. package/dist/types/gjc-runtime/state-argv.d.ts +1 -1
  38. package/dist/types/gjc-runtime/state-migrations.d.ts +8 -0
  39. package/dist/types/gjc-runtime/state-runtime.d.ts +95 -0
  40. package/dist/types/gjc-runtime/state-writer.d.ts +11 -1
  41. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +8 -0
  42. package/dist/types/internal-urls/skill-path.d.ts +1 -0
  43. package/dist/types/lsp/workspace-path.d.ts +1 -0
  44. package/dist/types/modes/acp/acp-agent.d.ts +7 -0
  45. package/dist/types/modes/components/custom-editor.d.ts +6 -0
  46. package/dist/types/modes/components/customization/customization-dashboard.d.ts +1 -0
  47. package/dist/types/modes/components/extensions/state-manager.d.ts +4 -3
  48. package/dist/types/modes/controllers/input-controller.d.ts +9 -0
  49. package/dist/types/modes/interactive-mode.d.ts +1 -0
  50. package/dist/types/modes/utils/interrupt-ownership.d.ts +3 -0
  51. package/dist/types/modes/utils/keybinding-matchers.d.ts +1 -0
  52. package/dist/types/modes/utils/macos-option-forwarding.d.ts +17 -0
  53. package/dist/types/progress/collect-project-progress.d.ts +38 -0
  54. package/dist/types/progress/progress-contract.d.ts +154 -0
  55. package/dist/types/progress/progress-snapshot.d.ts +11 -0
  56. package/dist/types/progress/project-progress.d.ts +141 -0
  57. package/dist/types/progress/render-progress.d.ts +28 -0
  58. package/dist/types/runtime-mcp/elicitation.d.ts +12 -0
  59. package/dist/types/runtime-mcp/oauth-public-url.d.ts +1 -0
  60. package/dist/types/runtime-mcp/plugin-network-boundary.d.ts +1 -0
  61. package/dist/types/runtime-mcp/smithery-registry.d.ts +24 -0
  62. package/dist/types/runtime-mcp/types.d.ts +6 -0
  63. package/dist/types/sdk/acp/adapter.d.ts +1 -1
  64. package/dist/types/sdk/broker/broker-exit.d.ts +6 -2
  65. package/dist/types/sdk/broker/broker.d.ts +18 -1
  66. package/dist/types/sdk/broker/lifecycle.d.ts +9 -0
  67. package/dist/types/sdk/broker/session-index.d.ts +12 -6
  68. package/dist/types/sdk/broker/task-artifact-owner-validation.d.ts +55 -0
  69. package/dist/types/sdk/bus/index.d.ts +12 -1
  70. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +6 -1
  71. package/dist/types/sdk/bus/telegram-daemon.d.ts +3 -2
  72. package/dist/types/sdk/client/client.d.ts +2 -0
  73. package/dist/types/sdk/host/host.d.ts +6 -0
  74. package/dist/types/sdk/host/query/handlers.d.ts +3 -0
  75. package/dist/types/sdk/index.d.ts +1 -0
  76. package/dist/types/sdk/router/session-router.d.ts +9 -0
  77. package/dist/types/sdk/session-list.d.ts +1 -1
  78. package/dist/types/sdk/session.d.ts +8 -0
  79. package/dist/types/session/agent-session.d.ts +38 -9
  80. package/dist/types/session/artifacts.d.ts +2 -2
  81. package/dist/types/session/internal/managed-gc-retirement-codec.d.ts +32 -0
  82. package/dist/types/session/internal/managed-session-scope.d.ts +79 -2
  83. package/dist/types/session/internal/managed-session-storage.d.ts +36 -1
  84. package/dist/types/session/internal/managed-task-owner-cleanup.d.ts +62 -0
  85. package/dist/types/session/internal/task-artifact-owner-access.d.ts +19 -0
  86. package/dist/types/session/internal/task-artifact-owner-transcript.d.ts +11 -0
  87. package/dist/types/session/session-manager.d.ts +31 -5
  88. package/dist/types/session/session-retirement.d.ts +71 -0
  89. package/dist/types/session/session-storage.d.ts +62 -48
  90. package/dist/types/session/session-transcript-header.d.ts +2 -0
  91. package/dist/types/session/task-artifact-owner-codec.d.ts +109 -0
  92. package/dist/types/session/task-artifact-owner-retirement.d.ts +7 -0
  93. package/dist/types/session/task-artifact-owner.d.ts +10 -0
  94. package/dist/types/setup/credential-auto-import.d.ts +1 -1
  95. package/dist/types/setup/credential-import.d.ts +6 -4
  96. package/dist/types/skill-state/active-state.d.ts +38 -0
  97. package/dist/types/slash-commands/helpers/progress-report.d.ts +8 -0
  98. package/dist/types/task/executor.d.ts +3 -0
  99. package/dist/types/tools/bash-skill-urls.d.ts +1 -1
  100. package/dist/types/tools/index.d.ts +3 -0
  101. package/dist/types/tools/python.d.ts +9 -1
  102. package/dist/types/tools/recipe/recipe-guard.d.ts +7 -0
  103. package/dist/types/tools/restricted-cwd.d.ts +1 -0
  104. package/dist/types/tools/todo-write.d.ts +6 -0
  105. package/dist/types/utils/tools-checksum.d.ts +7 -0
  106. package/package.json +7 -7
  107. package/scripts/generate-sdk-operation-inventory.ts +21 -0
  108. package/scripts/resident-memory-bench.ts +174 -20
  109. package/scripts/verify-managed-empty-stop.ts +28 -0
  110. package/src/async/job-manager.ts +228 -122
  111. package/src/capability/index.ts +18 -0
  112. package/src/capability/mcp.ts +2 -0
  113. package/src/capability/skill.ts +2 -0
  114. package/src/capability/types.ts +6 -0
  115. package/src/cli/auth-broker-cli.ts +1 -1
  116. package/src/cli/config-cli.ts +8 -18
  117. package/src/cli/customize-doctor.ts +15 -2
  118. package/src/cli/public-command-errors.ts +21 -1
  119. package/src/cli/setup-cli.ts +4 -4
  120. package/src/cli/skills-cli.ts +5 -0
  121. package/src/cli-main.ts +7 -8
  122. package/src/commands/deep-interview.ts +47 -8
  123. package/src/commands/sdk.ts +140 -29
  124. package/src/config/autorouting-tier-map.ts +117 -7
  125. package/src/config/file-lock.ts +307 -68
  126. package/src/config/mcp-schema.json +4 -0
  127. package/src/config/model-bindings-applier.ts +20 -0
  128. package/src/config/model-profile-activation.ts +240 -46
  129. package/src/config/model-registry.ts +47 -153
  130. package/src/config/settings.ts +44 -4
  131. package/src/config/skill-settings-defaults.ts +7 -0
  132. package/src/coordinator-mcp/policy.ts +3 -2
  133. package/src/cursor-delete-path.ts +10 -0
  134. package/src/cursor-mcp-name.ts +15 -0
  135. package/src/cursor.ts +13 -2
  136. package/src/customization/inventory.ts +3 -0
  137. package/src/debug/report-bundle-parent.ts +22 -0
  138. package/src/debug/report-bundle.ts +3 -0
  139. package/src/debug/system-info.ts +13 -1
  140. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/stream.ts +67 -4
  141. package/src/defaults/gjc/extensions/grok-cli-vendor/src/provider/version-manager.ts +80 -0
  142. package/src/defaults/gjc/skills/deep-interview/SKILL.md +105 -10
  143. package/src/defaults/gjc/skills/ralplan/SKILL.md +6 -4
  144. package/src/defaults/gjc-defaults.test.ts +18 -1
  145. package/src/defaults/gjc-defaults.ts +3 -0
  146. package/src/defaults/gjc-skills.generated.ts +58 -36
  147. package/src/discovery/agents.ts +6 -1
  148. package/src/discovery/builtin.ts +10 -0
  149. package/src/discovery/helpers.ts +168 -23
  150. package/src/discovery/mcp-json.ts +6 -0
  151. package/src/discovery/ssh.ts +9 -4
  152. package/src/discovery/substitute-plugin-root.ts +3 -1
  153. package/src/edit/file-read-cache.ts +1 -1
  154. package/src/eval/py/executor.ts +380 -120
  155. package/src/export/html/css-color.ts +9 -0
  156. package/src/export/html/index.ts +5 -4
  157. package/src/export/html/template.generated.ts +1 -1
  158. package/src/extensibility/extensions/runner.ts +4 -0
  159. package/src/extensibility/extensions/types.ts +7 -0
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +73 -8
  161. package/src/extensibility/plugins/manager.ts +3 -2
  162. package/src/extensibility/plugins/marketplace/cache.ts +15 -0
  163. package/src/extensibility/plugins/marketplace/manager.ts +11 -3
  164. package/src/extensibility/plugins/plugin-link-path.ts +12 -0
  165. package/src/extensibility/runtime-skill-discovery.ts +20 -2
  166. package/src/extensibility/skill-management.ts +6 -2
  167. package/src/extensibility/skills.ts +6 -1
  168. package/src/gjc-runtime/deep-interview-crystallize.ts +1814 -0
  169. package/src/gjc-runtime/deep-interview-recorder.ts +20 -2
  170. package/src/gjc-runtime/deep-interview-runtime.ts +1415 -13
  171. package/src/gjc-runtime/deep-interview-stage.ts +98 -21
  172. package/src/gjc-runtime/gc-runtime.ts +206 -8
  173. package/src/gjc-runtime/launch-worktree.ts +14 -4
  174. package/src/gjc-runtime/ralplan-runtime.ts +447 -52
  175. package/src/gjc-runtime/state-argv.ts +2 -0
  176. package/src/gjc-runtime/state-migrations.ts +91 -29
  177. package/src/gjc-runtime/state-runtime.ts +3716 -135
  178. package/src/gjc-runtime/state-writer.ts +83 -8
  179. package/src/gjc-runtime/ultragoal-runtime.ts +16 -4
  180. package/src/gjc-runtime/workflow-manifest.generated.json +70 -42
  181. package/src/gjc-runtime/workflow-manifest.ts +54 -21
  182. package/src/harness-control-plane/operate.ts +12 -4
  183. package/src/harness-control-plane/owner.ts +5 -1
  184. package/src/hashline/parser.ts +48 -9
  185. package/src/hashline/recovery.ts +13 -4
  186. package/src/hindsight/config.ts +9 -3
  187. package/src/internal-urls/docs-index.generated.ts +19 -18
  188. package/src/internal-urls/skill-path.ts +19 -0
  189. package/src/internal-urls/skill-protocol.ts +2 -0
  190. package/src/lsp/edits.ts +6 -0
  191. package/src/lsp/workspace-path.ts +51 -0
  192. package/src/main.ts +195 -31
  193. package/src/modes/acp/acp-agent.ts +163 -7
  194. package/src/modes/components/custom-editor.ts +14 -0
  195. package/src/modes/components/customization/customization-dashboard.ts +12 -0
  196. package/src/modes/components/extensions/extension-dashboard.ts +2 -2
  197. package/src/modes/components/extensions/state-manager.ts +15 -5
  198. package/src/modes/components/model-selector.ts +1 -4
  199. package/src/modes/components/provider-onboarding-selector.ts +1 -1
  200. package/src/modes/components/status-line/segments.ts +4 -0
  201. package/src/modes/controllers/event-controller.ts +11 -4
  202. package/src/modes/controllers/input-controller.ts +74 -29
  203. package/src/modes/controllers/runtime-mcp-command-controller.ts +8 -3
  204. package/src/modes/controllers/selector-controller.ts +28 -15
  205. package/src/modes/interactive-mode.ts +4 -0
  206. package/src/modes/runtime-init.ts +4 -0
  207. package/src/modes/utils/abort-message.ts +3 -1
  208. package/src/modes/utils/interrupt-ownership.ts +12 -0
  209. package/src/modes/utils/keybinding-matchers.ts +4 -0
  210. package/src/modes/utils/macos-option-forwarding.ts +80 -0
  211. package/src/progress/collect-project-progress.ts +153 -0
  212. package/src/progress/progress-contract.ts +172 -0
  213. package/src/progress/progress-snapshot.ts +140 -0
  214. package/src/progress/project-progress.ts +446 -0
  215. package/src/progress/render-progress.ts +209 -0
  216. package/src/prompts/system/master-mode.md +1 -0
  217. package/src/prompts/tools/skill-discovery.md +1 -1
  218. package/src/runtime-mcp/client.ts +13 -4
  219. package/src/runtime-mcp/config-writer.ts +10 -6
  220. package/src/runtime-mcp/config.ts +1 -0
  221. package/src/runtime-mcp/elicitation.ts +142 -0
  222. package/src/runtime-mcp/oauth-flow.ts +5 -0
  223. package/src/runtime-mcp/oauth-public-url.ts +8 -0
  224. package/src/runtime-mcp/plugin-network-boundary.ts +4 -0
  225. package/src/runtime-mcp/smithery-registry.ts +22 -3
  226. package/src/runtime-mcp/transports/http.ts +2 -2
  227. package/src/runtime-mcp/types.ts +6 -0
  228. package/src/sdk/acp/adapter.ts +93 -8
  229. package/src/sdk/broker/broker-exit.ts +52 -23
  230. package/src/sdk/broker/broker.ts +83 -7
  231. package/src/sdk/broker/ensure.ts +2 -0
  232. package/src/sdk/broker/lifecycle.ts +820 -73
  233. package/src/sdk/broker/session-index.ts +191 -81
  234. package/src/sdk/broker/task-artifact-owner-validation.ts +259 -0
  235. package/src/sdk/bus/chat-daemon-cli.ts +38 -1
  236. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  237. package/src/sdk/bus/chat-daemon-runtime.ts +3 -0
  238. package/src/sdk/bus/index.ts +241 -46
  239. package/src/sdk/bus/telegram-daemon-contract.ts +6 -1
  240. package/src/sdk/bus/telegram-daemon.ts +4 -2
  241. package/src/sdk/cli/session-cli.ts +17 -3
  242. package/src/sdk/client/client.ts +28 -8
  243. package/src/sdk/host/host.ts +6 -0
  244. package/src/sdk/host/query/handlers.ts +9 -1
  245. package/src/sdk/host/session-runtime.test.ts +2805 -411
  246. package/src/sdk/host/session-runtime.ts +428 -111
  247. package/src/sdk/host/surface-policy.ts +1 -0
  248. package/src/sdk/index.ts +8 -0
  249. package/src/sdk/lifecycle-session.ts +3 -1
  250. package/src/sdk/mcp/server.ts +15 -3
  251. package/src/sdk/prompt-deadline-manager.ts +15 -0
  252. package/src/sdk/protocol/operation-inventory.generated.json +146 -0
  253. package/src/sdk/protocol/operation-registry.ts +9 -2
  254. package/src/sdk/router/session-router.ts +94 -14
  255. package/src/sdk/session-list.ts +1 -0
  256. package/src/sdk/session.ts +81 -38
  257. package/src/session/agent-session.ts +674 -224
  258. package/src/session/artifacts.ts +174 -70
  259. package/src/session/internal/managed-gc-retirement-codec.ts +319 -0
  260. package/src/session/internal/managed-session-scope.ts +3457 -462
  261. package/src/session/internal/managed-session-storage.ts +482 -61
  262. package/src/session/internal/managed-task-owner-cleanup.ts +473 -0
  263. package/src/session/internal/task-artifact-owner-access.ts +245 -0
  264. package/src/session/internal/task-artifact-owner-transcript.ts +614 -0
  265. package/src/session/session-manager.ts +939 -133
  266. package/src/session/session-retirement.ts +714 -0
  267. package/src/session/session-storage.ts +418 -174
  268. package/src/session/session-transcript-header.ts +17 -0
  269. package/src/session/task-artifact-owner-codec.ts +641 -0
  270. package/src/session/task-artifact-owner-retirement.ts +477 -0
  271. package/src/session/task-artifact-owner.ts +289 -0
  272. package/src/setup/credential-auto-import.ts +12 -3
  273. package/src/setup/credential-import.ts +176 -5
  274. package/src/setup/paseo/announce.ts +6 -1
  275. package/src/skill-state/active-state.ts +132 -2
  276. package/src/slash-commands/builtin-registry.ts +39 -9
  277. package/src/slash-commands/helpers/progress-report.ts +23 -0
  278. package/src/stt/setup.ts +3 -5
  279. package/src/task/commands.ts +3 -1
  280. package/src/task/executor.ts +4 -0
  281. package/src/task/index.ts +6 -0
  282. package/src/tools/ask.ts +205 -6
  283. package/src/tools/ast-edit.ts +4 -0
  284. package/src/tools/bash-allowed-prefixes.ts +15 -0
  285. package/src/tools/bash-skill-urls.ts +56 -3
  286. package/src/tools/bash.ts +48 -79
  287. package/src/tools/descriptors.ts +5 -1
  288. package/src/tools/eval.ts +56 -36
  289. package/src/tools/image-gen.ts +1 -1
  290. package/src/tools/index.ts +3 -0
  291. package/src/tools/python.ts +187 -66
  292. package/src/tools/recipe/index.ts +9 -0
  293. package/src/tools/recipe/recipe-guard.ts +19 -0
  294. package/src/tools/restricted-cwd.ts +10 -0
  295. package/src/tools/skill-discovery.ts +5 -0
  296. package/src/tools/skill.ts +28 -1
  297. package/src/tools/todo-write.ts +10 -1
  298. package/src/tools/tool-catalog.generated.ts +1 -1
  299. package/src/tools/write.ts +1 -0
  300. package/src/utils/tools-checksum.ts +34 -0
  301. package/src/utils/tools-manager.ts +24 -6
  302. package/src/web/search/providers/codex.ts +3 -2
@@ -0,0 +1,477 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import type { NativeDirectoryTreeSnapshot, NativeExactUnlinkResult } from "@gajae-code/natives";
4
+ import type { ManagedSessionDescendantStore } from "./internal/managed-session-storage";
5
+ import {
6
+ captureOwnerTreeIfPresent,
7
+ captureValidatedOwnerTree,
8
+ newSessionRootReaderStore,
9
+ newSessionRootStore,
10
+ ownerTreeHasPendingManagedPublication,
11
+ } from "./internal/task-artifact-owner-access";
12
+ import {
13
+ EMPTY_PAYLOAD_SHA256,
14
+ isKnownNativeSidePath,
15
+ isOwnerRetainedRoot,
16
+ normalizeRetainedTreeSnapshot,
17
+ OWNER_DIRECTORY,
18
+ OWNER_RETIREMENT_SCHEMA_VERSION,
19
+ ownerAbsolutePath,
20
+ parseTaskArtifactOwnerDeletionEvidence,
21
+ parseTaskArtifactOwnerRetirementContinuation,
22
+ parseTaskArtifactOwnerRetirementOutcome,
23
+ retainedTreeDoesNotExpandAuthority,
24
+ sameOwnerParentIdentity,
25
+ type TaskArtifactOwnerDeletionEvidence,
26
+ type TaskArtifactOwnerRetirementContinuation,
27
+ type TaskArtifactOwnerRetirementOutcome,
28
+ type TaskArtifactOwnerStorageContext,
29
+ } from "./task-artifact-owner-codec";
30
+
31
+ function mergeUniqueStrings(
32
+ previous: readonly string[] | undefined,
33
+ next: string | undefined,
34
+ maximum: number,
35
+ ): string[] | undefined {
36
+ const values = new Set(previous ?? []);
37
+ if (next !== undefined) values.add(next);
38
+ if (values.size > maximum) throw new Error("task_artifact_owner_native_diagnostic_limit_exceeded");
39
+ return values.size > 0 ? [...values] : undefined;
40
+ }
41
+
42
+ function retainedSidePaths(
43
+ context: TaskArtifactOwnerStorageContext,
44
+ evidence: TaskArtifactOwnerDeletionEvidence,
45
+ previous: readonly string[] | undefined,
46
+ next: string | undefined,
47
+ ): string[] | undefined {
48
+ const values = mergeUniqueStrings(previous, next, 256) ?? [];
49
+ const ownerParent = path.dirname(ownerAbsolutePath(context, evidence.locator.ownerId));
50
+ const retained: string[] = [];
51
+ for (const pathname of values) {
52
+ if (!isKnownNativeSidePath(context, evidence.locator.ownerId, pathname))
53
+ throw new Error("task_artifact_owner_native_side_path_unrecognized");
54
+ if (path.dirname(pathname) !== ownerParent) {
55
+ retained.push(pathname);
56
+ continue;
57
+ }
58
+ try {
59
+ fs.lstatSync(pathname, { bigint: true });
60
+ retained.push(pathname);
61
+ } catch (error) {
62
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") retained.push(pathname);
63
+ }
64
+ }
65
+ return retained.length > 0 ? retained : undefined;
66
+ }
67
+
68
+ function continuationRecord(
69
+ context: TaskArtifactOwnerStorageContext,
70
+ evidence: TaskArtifactOwnerDeletionEvidence,
71
+ retainedRootPath: string,
72
+ retainedTreeSnapshot: NativeDirectoryTreeSnapshot,
73
+ previous?: TaskArtifactOwnerRetirementContinuation,
74
+ result?: NativeExactUnlinkResult,
75
+ ): TaskArtifactOwnerRetirementContinuation {
76
+ const detachedPaths = mergeUniqueStrings(previous?.detachedPaths, result?.detachedPath, 2);
77
+ if (detachedPaths?.some(pathname => !isOwnerRetainedRoot(context, evidence.locator.ownerId, pathname)))
78
+ throw new Error("task_artifact_owner_native_retained_root_unrecognized");
79
+ const nativeCodes = mergeUniqueStrings(previous?.nativeCodes, result?.code, 64);
80
+ if (nativeCodes?.some(code => !/^[A-Za-z0-9_.:-]{1,128}$/u.test(code)))
81
+ throw new Error("task_artifact_owner_native_code_unrecognized");
82
+ const retainedSuccessorPaths = retainedSidePaths(
83
+ context,
84
+ evidence,
85
+ previous?.retainedSuccessorPaths,
86
+ result?.retainedSuccessorPath,
87
+ );
88
+ const retainedPlaceholderPaths = retainedSidePaths(
89
+ context,
90
+ evidence,
91
+ previous?.retainedPlaceholderPaths,
92
+ result?.retainedPlaceholderPath,
93
+ );
94
+ const retainedUnknownPaths = retainedSidePaths(
95
+ context,
96
+ evidence,
97
+ previous?.retainedUnknownPaths,
98
+ result?.retainedUnknownPath,
99
+ );
100
+ const windowsErrorCodes = mergeUniqueStrings(previous?.windowsErrorCodes, result?.windowsErrorCode, 64);
101
+ if (windowsErrorCodes?.some(code => !/^0x[0-9A-Fa-f]{8}$/u.test(code)))
102
+ throw new Error("task_artifact_owner_native_windows_code_unrecognized");
103
+ const payloadDurable =
104
+ previous?.payloadDurable === true || result?.payloadDurable === true
105
+ ? true
106
+ : (result?.payloadDurable ?? previous?.payloadDurable);
107
+ return parseTaskArtifactOwnerRetirementContinuation(context, evidence, {
108
+ schemaVersion: OWNER_RETIREMENT_SCHEMA_VERSION,
109
+ parentIdentity: evidence.parentIdentity,
110
+ retainedRootPath,
111
+ retainedTreeSnapshot,
112
+ ...(detachedPaths !== undefined ? { detachedPaths } : {}),
113
+ ...(nativeCodes !== undefined ? { nativeCodes } : {}),
114
+ ...(payloadDurable !== undefined ? { payloadDurable } : {}),
115
+ ...(retainedSuccessorPaths !== undefined ? { retainedSuccessorPaths } : {}),
116
+ ...(retainedPlaceholderPaths !== undefined ? { retainedPlaceholderPaths } : {}),
117
+ ...(retainedUnknownPaths !== undefined ? { retainedUnknownPaths } : {}),
118
+ ...(windowsErrorCodes !== undefined ? { windowsErrorCodes } : {}),
119
+ });
120
+ }
121
+
122
+ function defaultContinuation(
123
+ context: TaskArtifactOwnerStorageContext,
124
+ evidence: TaskArtifactOwnerDeletionEvidence,
125
+ previous?: TaskArtifactOwnerRetirementContinuation,
126
+ ): TaskArtifactOwnerRetirementContinuation {
127
+ return (
128
+ previous ??
129
+ continuationRecord(
130
+ context,
131
+ evidence,
132
+ `${ownerAbsolutePath(context, evidence.locator.ownerId)}.removing`,
133
+ evidence.treeSnapshot,
134
+ )
135
+ );
136
+ }
137
+
138
+ function nativeResultSidePathsRemain(
139
+ context: TaskArtifactOwnerStorageContext,
140
+ rootStore: ManagedSessionDescendantStore,
141
+ evidence: TaskArtifactOwnerDeletionEvidence,
142
+ continuation: TaskArtifactOwnerRetirementContinuation,
143
+ ): boolean {
144
+ const ownerParent = path.dirname(ownerAbsolutePath(context, evidence.locator.ownerId));
145
+ try {
146
+ if (!sameOwnerParentIdentity(rootStore.captureDirectoryIdentity(OWNER_DIRECTORY), evidence.parentIdentity))
147
+ return true;
148
+ } catch {
149
+ return true;
150
+ }
151
+ let remains = false;
152
+ for (const pathname of [
153
+ ...(continuation.retainedSuccessorPaths ?? []),
154
+ ...(continuation.retainedPlaceholderPaths ?? []),
155
+ ...(continuation.retainedUnknownPaths ?? []),
156
+ ]) {
157
+ if (path.dirname(pathname) !== ownerParent) {
158
+ remains = true;
159
+ continue;
160
+ }
161
+ try {
162
+ fs.lstatSync(pathname, { bigint: true });
163
+ remains = true;
164
+ } catch (error) {
165
+ if ((error as NodeJS.ErrnoException).code !== "ENOENT") remains = true;
166
+ }
167
+ }
168
+ try {
169
+ return (
170
+ remains ||
171
+ !sameOwnerParentIdentity(rootStore.captureDirectoryIdentity(OWNER_DIRECTORY), evidence.parentIdentity)
172
+ );
173
+ } catch {
174
+ return true;
175
+ }
176
+ }
177
+
178
+ /** Confirm physical completion from a managed native proof, never from canonical absence alone. */
179
+ export function verifyTaskArtifactOwnerPhysicalRetirement(
180
+ context: TaskArtifactOwnerStorageContext,
181
+ evidence: TaskArtifactOwnerDeletionEvidence,
182
+ value: unknown,
183
+ ): void {
184
+ const outcome = parseTaskArtifactOwnerRetirementOutcome(context, evidence, value);
185
+ if (outcome.kind !== "completed") throw new Error("task_artifact_owner_physical_retirement_unverified");
186
+ const store = newSessionRootReaderStore(context);
187
+ try {
188
+ if (!sameOwnerParentIdentity(store.captureDirectoryIdentity(OWNER_DIRECTORY), evidence.parentIdentity))
189
+ throw new Error("task_artifact_owner_parent_identity_mismatch");
190
+ const canonical = ownerAbsolutePath(context, evidence.locator.ownerId);
191
+ if (
192
+ captureOwnerTreeIfPresent(context, store, evidence.locator.ownerId, canonical) ||
193
+ captureOwnerTreeIfPresent(context, store, evidence.locator.ownerId, `${canonical}.removing`)
194
+ )
195
+ throw new Error("task_artifact_owner_physical_retirement_unverified");
196
+ } finally {
197
+ store.close();
198
+ }
199
+ }
200
+
201
+ /** Revalidate a persisted remnant through managed authority without mutation or new payload proof. */
202
+ export function verifyTaskArtifactOwnerRetirementContinuation(
203
+ context: TaskArtifactOwnerStorageContext,
204
+ evidenceValue: TaskArtifactOwnerDeletionEvidence,
205
+ value: unknown,
206
+ ): TaskArtifactOwnerRetirementContinuation {
207
+ const evidence = parseTaskArtifactOwnerDeletionEvidence(evidenceValue);
208
+ const continuation = parseTaskArtifactOwnerRetirementContinuation(context, evidence, value);
209
+ const store = newSessionRootReaderStore(context);
210
+ try {
211
+ if (!sameOwnerParentIdentity(store.captureDirectoryIdentity(OWNER_DIRECTORY), evidence.parentIdentity))
212
+ throw new Error("task_artifact_owner_parent_identity_mismatch");
213
+ const snapshot = captureOwnerTreeIfPresent(
214
+ context,
215
+ store,
216
+ evidence.locator.ownerId,
217
+ continuation.retainedRootPath,
218
+ );
219
+ const prior = normalizeRetainedTreeSnapshot(evidence.treeSnapshot, continuation.retainedTreeSnapshot);
220
+ const current = snapshot && normalizeRetainedTreeSnapshot(evidence.treeSnapshot, snapshot);
221
+ if (!prior || !current || !retainedTreeDoesNotExpandAuthority(prior, current))
222
+ throw new Error("task_artifact_owner_retained_tree_mismatch");
223
+ if (
224
+ continuation.payloadDurable === true &&
225
+ snapshot.entries.some(
226
+ entry => entry.kind === "file" && (entry.size !== "0" || entry.sha256 !== EMPTY_PAYLOAD_SHA256),
227
+ )
228
+ )
229
+ throw new Error("task_artifact_owner_retired_payload_changed");
230
+ return continuation;
231
+ } finally {
232
+ store.close();
233
+ }
234
+ }
235
+
236
+ /** Continue exact native removal without widening the original owner-tree authority. */
237
+ export function retireTaskArtifactOwner(
238
+ context: TaskArtifactOwnerStorageContext,
239
+ evidenceValue: TaskArtifactOwnerDeletionEvidence,
240
+ continuationValue?: unknown,
241
+ ): TaskArtifactOwnerRetirementOutcome {
242
+ const evidence = parseTaskArtifactOwnerDeletionEvidence(evidenceValue);
243
+ const previous =
244
+ continuationValue === undefined
245
+ ? undefined
246
+ : parseTaskArtifactOwnerRetirementContinuation(context, evidence, continuationValue);
247
+ const fallback = defaultContinuation(context, evidence, previous);
248
+ const rootStore = newSessionRootStore(context);
249
+ try {
250
+ try {
251
+ rootStore.verifyRootSecurity();
252
+ } catch {
253
+ return {
254
+ kind: "uncertain",
255
+ evidence,
256
+ continuation: fallback,
257
+ reason: "task_artifact_owner_namespace_unverified",
258
+ };
259
+ }
260
+ let currentParent: { readonly dev: string; readonly ino: string };
261
+ try {
262
+ currentParent = rootStore.captureDirectoryIdentity(OWNER_DIRECTORY);
263
+ } catch {
264
+ return {
265
+ kind: "uncertain",
266
+ evidence,
267
+ continuation: fallback,
268
+ reason: "task_artifact_owner_parent_unavailable",
269
+ };
270
+ }
271
+ if (!sameOwnerParentIdentity(currentParent, evidence.parentIdentity))
272
+ return {
273
+ kind: "uncertain",
274
+ evidence,
275
+ continuation: fallback,
276
+ reason: "task_artifact_owner_parent_identity_changed",
277
+ };
278
+
279
+ // Publication markers can hold writable descriptors; scrubbing cannot revoke them.
280
+ if (ownerTreeHasPendingManagedPublication(evidence.treeSnapshot))
281
+ return {
282
+ kind: "uncertain",
283
+ evidence,
284
+ continuation: fallback,
285
+ reason: "task_artifact_owner_writer_not_quiescent",
286
+ };
287
+
288
+ const ownerPath = ownerAbsolutePath(context, evidence.locator.ownerId);
289
+ const removingPath = `${ownerPath}.removing`;
290
+ const baseline = previous
291
+ ? normalizeRetainedTreeSnapshot(evidence.treeSnapshot, previous.retainedTreeSnapshot)
292
+ : evidence.treeSnapshot;
293
+ const candidates = [
294
+ ...new Set(
295
+ [previous?.retainedRootPath, removingPath, ownerPath].filter(
296
+ (pathname): pathname is string => pathname !== undefined,
297
+ ),
298
+ ),
299
+ ];
300
+ let retainedRootPath: string | undefined;
301
+ let retainedTreeSnapshot: NativeDirectoryTreeSnapshot | undefined;
302
+ let nativeTreeSnapshot: NativeDirectoryTreeSnapshot | undefined;
303
+ for (const candidate of candidates) {
304
+ let snapshot: NativeDirectoryTreeSnapshot | undefined;
305
+ try {
306
+ snapshot = captureOwnerTreeIfPresent(context, rootStore, evidence.locator.ownerId, candidate);
307
+ } catch {
308
+ return {
309
+ kind: "uncertain",
310
+ evidence,
311
+ continuation: fallback,
312
+ reason: "task_artifact_owner_retained_tree_unavailable",
313
+ };
314
+ }
315
+ if (snapshot && ownerTreeHasPendingManagedPublication(snapshot))
316
+ return {
317
+ kind: "uncertain",
318
+ evidence,
319
+ continuation: fallback,
320
+ reason: "task_artifact_owner_writer_not_quiescent",
321
+ };
322
+ const normalized = snapshot && normalizeRetainedTreeSnapshot(evidence.treeSnapshot, snapshot);
323
+ if (!snapshot || !normalized || !baseline || !retainedTreeDoesNotExpandAuthority(baseline, normalized))
324
+ continue;
325
+ if (candidate === ownerPath && JSON.stringify(snapshot) === JSON.stringify(evidence.treeSnapshot)) {
326
+ try {
327
+ const validated = captureValidatedOwnerTree(context, rootStore, evidence.sessionId, evidence.locator);
328
+ if (JSON.stringify(validated) !== JSON.stringify(evidence.treeSnapshot))
329
+ return {
330
+ kind: "uncertain",
331
+ evidence,
332
+ continuation: fallback,
333
+ reason: "task_artifact_owner_changed_since_capture",
334
+ };
335
+ } catch {
336
+ return {
337
+ kind: "uncertain",
338
+ evidence,
339
+ continuation: fallback,
340
+ reason: "task_artifact_owner_identity_unverified",
341
+ };
342
+ }
343
+ }
344
+ retainedRootPath = candidate;
345
+ retainedTreeSnapshot = snapshot;
346
+ nativeTreeSnapshot = normalized;
347
+ break;
348
+ }
349
+ if (!retainedRootPath || !retainedTreeSnapshot || !nativeTreeSnapshot)
350
+ return {
351
+ kind: "uncertain",
352
+ evidence,
353
+ continuation: fallback,
354
+ reason: "task_artifact_owner_retained_root_not_found_or_unverified",
355
+ };
356
+
357
+ let nativeOutcome: NativeExactUnlinkResult;
358
+ try {
359
+ nativeOutcome = rootStore.removeTreeExpectedWithParentIdentity(
360
+ path.relative(context.sessionsRoot, retainedRootPath).split(path.sep).join("/"),
361
+ nativeTreeSnapshot,
362
+ { dev: BigInt(evidence.parentIdentity.dev), ino: BigInt(evidence.parentIdentity.ino) },
363
+ );
364
+ } catch {
365
+ return {
366
+ kind: "uncertain",
367
+ evidence,
368
+ continuation: fallback,
369
+ reason: "task_artifact_owner_native_removal_uncertain",
370
+ };
371
+ }
372
+ let parentStillBound = false;
373
+ try {
374
+ parentStillBound = sameOwnerParentIdentity(
375
+ rootStore.captureDirectoryIdentity(OWNER_DIRECTORY),
376
+ evidence.parentIdentity,
377
+ );
378
+ } catch {
379
+ parentStillBound = false;
380
+ }
381
+ if (!parentStillBound)
382
+ return {
383
+ kind: "uncertain",
384
+ evidence,
385
+ continuation: fallback,
386
+ reason: "task_artifact_owner_parent_identity_changed_after_removal",
387
+ nativeOutcome,
388
+ };
389
+
390
+ const reportedRoot = nativeOutcome.detachedPath;
391
+ const reportedRootKnown =
392
+ reportedRoot === undefined || isOwnerRetainedRoot(context, evidence.locator.ownerId, reportedRoot);
393
+ const nextRoot = reportedRootKnown && reportedRoot !== undefined ? reportedRoot : retainedRootPath;
394
+ let residualTree: NativeDirectoryTreeSnapshot | undefined;
395
+ let residualValid = reportedRootKnown;
396
+ try {
397
+ residualTree = captureOwnerTreeIfPresent(context, rootStore, evidence.locator.ownerId, nextRoot);
398
+ if (residualTree) {
399
+ const normalizedResidual = normalizeRetainedTreeSnapshot(evidence.treeSnapshot, residualTree);
400
+ if (!normalizedResidual || !retainedTreeDoesNotExpandAuthority(nativeTreeSnapshot, normalizedResidual))
401
+ residualValid = false;
402
+ }
403
+ } catch {
404
+ residualValid = false;
405
+ }
406
+ const nextTree = residualValid && residualTree ? residualTree : retainedTreeSnapshot;
407
+ let nextContinuation: TaskArtifactOwnerRetirementContinuation;
408
+ try {
409
+ nextContinuation = continuationRecord(context, evidence, nextRoot, nextTree, previous, nativeOutcome);
410
+ } catch {
411
+ return {
412
+ kind: "uncertain",
413
+ evidence,
414
+ continuation: continuationRecord(context, evidence, retainedRootPath, retainedTreeSnapshot, previous),
415
+ reason: "task_artifact_owner_native_retained_state_unrecognized",
416
+ nativeOutcome,
417
+ };
418
+ }
419
+ if (!residualValid)
420
+ return {
421
+ kind: "uncertain",
422
+ evidence,
423
+ continuation: nextContinuation,
424
+ reason: "task_artifact_owner_native_retained_state_unverified",
425
+ nativeOutcome,
426
+ };
427
+
428
+ let ownerRootRemains = false;
429
+ for (const candidate of [ownerPath, removingPath]) {
430
+ let snapshot: NativeDirectoryTreeSnapshot | undefined;
431
+ try {
432
+ snapshot = captureOwnerTreeIfPresent(context, rootStore, evidence.locator.ownerId, candidate);
433
+ } catch {
434
+ ownerRootRemains = true;
435
+ break;
436
+ }
437
+ if (snapshot) {
438
+ ownerRootRemains = true;
439
+ break;
440
+ }
441
+ }
442
+ const sidePathsRemain = nativeResultSidePathsRemain(context, rootStore, evidence, nextContinuation);
443
+ if (nativeOutcome.ok && !ownerRootRemains && !sidePathsRemain)
444
+ return { kind: "completed", evidence, nativeOutcome };
445
+ if (
446
+ !nativeOutcome.ok &&
447
+ nativeOutcome.code === "cleanup_pending" &&
448
+ nativeOutcome.payloadDurable === true &&
449
+ residualTree &&
450
+ nextRoot === removingPath &&
451
+ !sidePathsRemain &&
452
+ residualTree.entries.every(
453
+ entry => entry.kind === "directory" || (entry.size === "0" && entry.sha256 === EMPTY_PAYLOAD_SHA256),
454
+ )
455
+ )
456
+ return {
457
+ kind: "payload_retired",
458
+ namespace: "retained",
459
+ evidence,
460
+ continuation: nextContinuation,
461
+ nativeOutcome,
462
+ };
463
+ if (!nativeOutcome.ok && nativeOutcome.code === "cleanup_pending")
464
+ return { kind: "cleanup_pending", evidence, continuation: nextContinuation, nativeOutcome };
465
+ return {
466
+ kind: "uncertain",
467
+ evidence,
468
+ continuation: nextContinuation,
469
+ reason: nativeOutcome.ok
470
+ ? "task_artifact_owner_native_success_retained_authority"
471
+ : `task_artifact_owner_native_removal_${nativeOutcome.code ?? "uncertain"}`,
472
+ nativeOutcome,
473
+ };
474
+ } finally {
475
+ rootStore.close();
476
+ }
477
+ }