@inneranimalmedia/agentsam-sdk 2.6.7 → 2.6.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 (318) hide show
  1. package/README.md +37 -0
  2. package/docs/REPO_FILE_MAP.txt +132 -0
  3. package/migrations/d1/0018_goap_control_plane_remaster.sql +40 -0
  4. package/migrations/d1/0019_agentsam_agent_run_plan_todo.sql +14 -0
  5. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +20 -9
  6. package/migrations/runtime/0002_goap_blackboard_v1.sql +15 -0
  7. package/migrations/runtime/0004_agent_run_plan_linkage.sql +8 -0
  8. package/native/agentsam-machine/cli/Cargo.toml +8 -1
  9. package/native/agentsam-machine/cli/README.md +21 -0
  10. package/native/agentsam-machine/core/Cargo.toml +7 -0
  11. package/native/agentsam-machine/core/README.md +14 -0
  12. package/native/agentsam-machine/core/build.rs +33 -0
  13. package/native/agentsam-machine/core/contracts/source-types.v1.json +353 -0
  14. package/native/agentsam-machine/core/src/lib.rs +6 -0
  15. package/native/agentsam-machine/core/src/source_types.rs +2 -2
  16. package/package.json +16 -6
  17. package/packages/agentsam-errors/package.json +1 -1
  18. package/packages/agentsam-errors/src/index.js +1 -0
  19. package/packages/agentsam-errors/src/tool.js +56 -0
  20. package/packages/agentsam-errors/test/tool.test.mjs +58 -0
  21. package/packages/agentsam-goap/README.md +52 -0
  22. package/packages/agentsam-goap/package.json +37 -0
  23. package/packages/agentsam-goap/src/adapters/d1-sqlite.js +570 -0
  24. package/packages/agentsam-goap/src/adapters/memory.js +199 -0
  25. package/packages/agentsam-goap/src/contracts.js +226 -0
  26. package/packages/agentsam-goap/src/control-plane.js +112 -0
  27. package/packages/agentsam-goap/src/errors.js +157 -0
  28. package/packages/agentsam-goap/src/index.js +5 -0
  29. package/packages/agentsam-goap/src/world.js +202 -0
  30. package/packages/agentsam-goap/test/goap-control-plane.test.mjs +245 -0
  31. package/packages/agentsam-goap/test/world.test.mjs +79 -0
  32. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  33. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  34. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  35. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  36. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  37. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  38. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  39. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  40. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  41. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  42. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  43. package/packages/agentsam-nav/dist/browser.global.js +135 -0
  44. package/packages/agentsam-nav/dist/browser.js +7290 -0
  45. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  46. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  47. package/packages/agentsam-nav/dist/index.js +7291 -0
  48. package/packages/agentsam-nav/dist/legacy.css +83 -0
  49. package/packages/agentsam-nav/dist/shell.css +113 -0
  50. package/packages/agentsam-nav/dist/theme.css +113 -0
  51. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  52. package/packages/agentsam-repository/src/goap.js +13 -14
  53. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  54. package/packages/agentsam-repository/src/tickets.js +15 -22
  55. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +19 -8
  56. package/packages/connectors/cloudflare/package.json +3 -1
  57. package/packages/identity/tests/lane1-packed-consumer.test.mjs +1 -1
  58. package/python/agentsam_sdk/repository/intelligence/discovery.py +27 -2
  59. package/python/agentsam_sdk/repository/intelligence/git.py +4 -0
  60. package/python/tests/test_repository_intelligence.py +30 -0
  61. package/src/cli/command-catalog.js +2 -1
  62. package/src/cli.js +10 -1
  63. package/src/commands/goap-world.js +134 -0
  64. package/src/commands/goap.js +11 -4
  65. package/src/commands/machine-binary.js +33 -27
  66. package/src/commands/machine-runtime.js +266 -0
  67. package/src/commands/machine.js +122 -51
  68. package/src/commands/package.js +530 -0
  69. package/src/commands/plan-ledger.js +370 -0
  70. package/src/commands/plan.js +183 -0
  71. package/src/commands/skill.js +78 -17
  72. package/src/knowledge/source.js +1 -1
  73. package/src/lib/slash-commands.js +1 -1
  74. package/src/local/runtime-store.js +24 -2
  75. package/src/local/sqlite.js +17 -0
  76. package/src/sam/operations/package-audit.js +41 -0
  77. package/src/sam/seed.js +2 -0
  78. package/skills/grok-auth/SKILL.md +0 -110
  79. package/skills/grok-auth/agentsam.skill.json +0 -25
  80. package/skills/grok-auth/references/grok-identity.md +0 -64
  81. package/skills/grok-auth/references/per-user-data.md +0 -49
  82. package/skills/grok-auth/references/prewired-and-env.md +0 -54
  83. package/skills/grok-auth/references/session-ui.md +0 -133
  84. package/skills/grok-auth/references/sign-in-methods.md +0 -55
  85. package/skills/grok-auth/references/wiring.md +0 -71
  86. package/skills/grok-building-games/SKILL.md +0 -213
  87. package/skills/grok-building-games/agentsam.skill.json +0 -25
  88. package/skills/grok-building-games/references/3d-libs.md +0 -64
  89. package/skills/grok-building-games/references/ai-pathfinding.md +0 -122
  90. package/skills/grok-building-games/references/audio.md +0 -129
  91. package/skills/grok-building-games/references/babylon.md +0 -202
  92. package/skills/grok-building-games/references/collision-physics.md +0 -122
  93. package/skills/grok-building-games/references/ecs-architecture.md +0 -111
  94. package/skills/grok-building-games/references/game-feel-juice.md +0 -110
  95. package/skills/grok-building-games/references/genres/board-card-chess.md +0 -89
  96. package/skills/grok-building-games/references/genres/endless-runner.md +0 -83
  97. package/skills/grok-building-games/references/genres/fps.md +0 -105
  98. package/skills/grok-building-games/references/genres/platformer-2d.md +0 -97
  99. package/skills/grok-building-games/references/genres/puzzle-match3-tetris.md +0 -131
  100. package/skills/grok-building-games/references/genres/racing-kart.md +0 -106
  101. package/skills/grok-building-games/references/genres/topdown-twin-stick.md +0 -97
  102. package/skills/grok-building-games/references/genres/tower-defense.md +0 -84
  103. package/skills/grok-building-games/references/genres/voxel-minecraft.md +0 -89
  104. package/skills/grok-building-games/references/input.md +0 -139
  105. package/skills/grok-building-games/references/phaser.md +0 -277
  106. package/skills/grok-building-games/references/procedural-generation.md +0 -141
  107. package/skills/grok-building-games/references/save-persistence.md +0 -108
  108. package/skills/grok-building-games/references/threejs-foundational.md +0 -148
  109. package/skills/grok-controls/SKILL.md +0 -274
  110. package/skills/grok-controls/agentsam.skill.json +0 -25
  111. package/skills/grok-design-ui/SKILL.md +0 -122
  112. package/skills/grok-design-ui/agentsam.skill.json +0 -25
  113. package/skills/grok-design-ui/references/animations.md +0 -379
  114. package/skills/grok-design-ui/references/performance.md +0 -88
  115. package/skills/grok-design-ui/references/refined-ui.md +0 -384
  116. package/skills/grok-design-ui/references/surfaces.md +0 -247
  117. package/skills/grok-design-ui/references/typography.md +0 -123
  118. package/skills/grok-game-animation-frames/SKILL.md +0 -84
  119. package/skills/grok-game-animation-frames/agentsam.skill.json +0 -25
  120. package/skills/grok-game-asset-core/SKILL.md +0 -69
  121. package/skills/grok-game-asset-core/agentsam.skill.json +0 -25
  122. package/skills/grok-game-character-consistency/SKILL.md +0 -69
  123. package/skills/grok-game-character-consistency/agentsam.skill.json +0 -25
  124. package/skills/grok-game-tilesets/SKILL.md +0 -65
  125. package/skills/grok-game-tilesets/agentsam.skill.json +0 -25
  126. package/skills/grok-game-ui-icons/SKILL.md +0 -56
  127. package/skills/grok-game-ui-icons/agentsam.skill.json +0 -25
  128. package/skills/grok-generate2dmap/LICENSE +0 -21
  129. package/skills/grok-generate2dmap/SKILL.md +0 -120
  130. package/skills/grok-generate2dmap/SOURCE.md +0 -6
  131. package/skills/grok-generate2dmap/agentsam.skill.json +0 -25
  132. package/skills/grok-generate2dmap/references/deliverables.md +0 -101
  133. package/skills/grok-generate2dmap/references/layered-map-contract.md +0 -209
  134. package/skills/grok-generate2dmap/references/map-strategies.md +0 -341
  135. package/skills/grok-generate2dmap/references/object-production-gate.md +0 -24
  136. package/skills/grok-generate2dmap/references/pipeline.md +0 -149
  137. package/skills/grok-generate2dmap/references/prop-pack-contract.md +0 -174
  138. package/skills/grok-generate2dmap/references/side-scroll-stages.md +0 -29
  139. package/skills/grok-generate2dmap/scripts/compose_layered_preview.py +0 -157
  140. package/skills/grok-generate2dmap/scripts/extract_prop_pack.py +0 -369
  141. package/skills/grok-generate2dsprite/LICENSE +0 -21
  142. package/skills/grok-generate2dsprite/SKILL.md +0 -313
  143. package/skills/grok-generate2dsprite/SOURCE.md +0 -6
  144. package/skills/grok-generate2dsprite/agentsam.skill.json +0 -25
  145. package/skills/grok-generate2dsprite/references/modes.md +0 -124
  146. package/skills/grok-generate2dsprite/references/prompt-rules.md +0 -315
  147. package/skills/grok-generate2dsprite/scripts/generate2dsprite.py +0 -1031
  148. package/skills/grok-generate2dsprite/scripts/make_layout_guide.py +0 -109
  149. package/skills/grok-imagine/SKILL.md +0 -201
  150. package/skills/grok-imagine/agentsam.skill.json +0 -25
  151. package/skills/grok-multiplayer-p2p/SKILL.md +0 -111
  152. package/skills/grok-multiplayer-p2p/agentsam.skill.json +0 -25
  153. package/skills/grok-multiplayer-p2p/references/react-binding.md +0 -144
  154. package/skills/grok-multiplayer-p2p/references/signaling-relay.md +0 -269
  155. package/skills/grok-neon/SKILL.md +0 -157
  156. package/skills/grok-neon/agentsam.skill.json +0 -25
  157. package/skills/grok-og/SKILL.md +0 -102
  158. package/skills/grok-og/agentsam.skill.json +0 -25
  159. package/skills/grok-og/references/brand-pass.md +0 -53
  160. package/skills/grok-og/references/custom-card.md +0 -107
  161. package/skills/grok-og/references/favicon-and-icons.md +0 -48
  162. package/skills/grok-og/references/og-type-contract.md +0 -18
  163. package/skills/grok-og/references/placeholder-card.md +0 -21
  164. package/skills/grok-og/references/x-banner.md +0 -41
  165. package/skills/grok-threejs/SKILL.md +0 -67
  166. package/skills/grok-threejs/agentsam.skill.json +0 -25
  167. package/skills/grok-threejs/references/llms-full.txt +0 -2780
  168. package/skills/grok-video2dsprite/LICENSE +0 -21
  169. package/skills/grok-video2dsprite/SKILL.md +0 -236
  170. package/skills/grok-video2dsprite/SOURCE.md +0 -6
  171. package/skills/grok-video2dsprite/agentsam.skill.json +0 -25
  172. package/skills/grok-video2dsprite/references/pipeline.md +0 -90
  173. package/skills/grok-video2dsprite/references/prompt-rules.md +0 -63
  174. package/skills/grok-video2dsprite/scripts/video2dsprite.py +0 -490
  175. package/skills/grok-xai-api/SKILL.md +0 -152
  176. package/skills/grok-xai-api/agentsam.skill.json +0 -25
  177. package/test/account-session.test.mjs +0 -101
  178. package/test/agent-capabilities.test.mjs +0 -67
  179. package/test/app-authority-context.test.mjs +0 -32
  180. package/test/app-building-skills.test.mjs +0 -61
  181. package/test/apps-scaffold-contract.test.mjs +0 -115
  182. package/test/blender-cad.test.mjs +0 -146
  183. package/test/cad-docker.test.mjs +0 -96
  184. package/test/capabilities.test.mjs +0 -133
  185. package/test/cli/api-key-env-whoami.test.mjs +0 -129
  186. package/test/cli/catalog-authority.test.mjs +0 -64
  187. package/test/cli/codebaseindex-plan-ux.test.mjs +0 -37
  188. package/test/cli/eval-live.test.mjs +0 -219
  189. package/test/cli/go.test.mjs +0 -128
  190. package/test/cli/local-vault-and-provider-setup.test.mjs +0 -268
  191. package/test/cli/machine-command.test.mjs +0 -34
  192. package/test/cli/mcp-client.test.mjs +0 -256
  193. package/test/cli/preferences-runtime.test.mjs +0 -11
  194. package/test/cli/runtime-persist.test.mjs +0 -56
  195. package/test/cli/runtime-ui.test.mjs +0 -141
  196. package/test/cli/rust-command.test.mjs +0 -21
  197. package/test/cli/skill-npm-and-env.test.mjs +0 -52
  198. package/test/cli/status-actions.test.mjs +0 -88
  199. package/test/cli/wireframes-go-registry.test.mjs +0 -139
  200. package/test/cli-preferences.test.mjs +0 -46
  201. package/test/cloudflare-connector.test.mjs +0 -93
  202. package/test/cloudflare-runtime.test.mjs +0 -82
  203. package/test/context.test.mjs +0 -159
  204. package/test/credentials-audit.test.mjs +0 -113
  205. package/test/deploy-health-scan.test.mjs +0 -95
  206. package/test/deploy-receipt.test.mjs +0 -91
  207. package/test/dockerize.test.mjs +0 -93
  208. package/test/error-diagnostics.test.mjs +0 -124
  209. package/test/eval-context.test.mjs +0 -37
  210. package/test/execution-approvals.test.mjs +0 -27
  211. package/test/fixtures/cad/courtyard-house.json +0 -208
  212. package/test/fixtures/knowledge-rpc-worker.mjs +0 -16
  213. package/test/fixtures/project-authority/customer-app/.agentsam/app.json +0 -5
  214. package/test/fixtures/project-authority/customer-app/apps/my-product/index.ts +0 -1
  215. package/test/fixtures/project-authority/customer-app/wrangler.toml +0 -17
  216. package/test/gcloud-auth.test.mjs +0 -111
  217. package/test/go/build-source-identity.test.mjs +0 -31
  218. package/test/go/cloudflare-probe.test.mjs +0 -317
  219. package/test/go/distribution.test.mjs +0 -28
  220. package/test/google-cloud-connection.test.mjs +0 -83
  221. package/test/google-cloud-inventory.test.mjs +0 -64
  222. package/test/indexing-provider.test.mjs +0 -29
  223. package/test/init-options.test.mjs +0 -35
  224. package/test/integration/ai-access-onboarding.test.mjs +0 -47
  225. package/test/integration/app-command.test.mjs +0 -85
  226. package/test/integration/autorag-project-authority.integration.test.mjs +0 -51
  227. package/test/integration/autorag-runtime-discovery.test.mjs +0 -107
  228. package/test/integration/cad-discovery.test.mjs +0 -158
  229. package/test/integration/cad-docker-executor.test.mjs +0 -249
  230. package/test/integration/cad-execution.test.mjs +0 -184
  231. package/test/integration/cad-project-app.test.mjs +0 -31
  232. package/test/integration/cad-project-d1.test.mjs +0 -25
  233. package/test/integration/cad-project-native.test.mjs +0 -24
  234. package/test/integration/cad-project-workflow.test.mjs +0 -9
  235. package/test/integration/cad-project.test.mjs +0 -85
  236. package/test/integration/cli-help.test.mjs +0 -41
  237. package/test/integration/cms-app-scaffold.test.mjs +0 -77
  238. package/test/integration/cms-site-tenancy-contract.test.mjs +0 -268
  239. package/test/integration/codebaseindex-ingest.test.mjs +0 -255
  240. package/test/integration/core-client.integration.test.mjs +0 -55
  241. package/test/integration/database-hosted-honesty.test.mjs +0 -49
  242. package/test/integration/desktop-keychain-boundary.test.mjs +0 -45
  243. package/test/integration/error-runtime-rpc.test.mjs +0 -71
  244. package/test/integration/features-resolve.test.mjs +0 -147
  245. package/test/integration/hosted-work-host-authority.test.mjs +0 -47
  246. package/test/integration/icon-registry.test.mjs +0 -67
  247. package/test/integration/ingest-discover-models.test.mjs +0 -30
  248. package/test/integration/inspect-path-cli.test.mjs +0 -46
  249. package/test/integration/install-script.test.mjs +0 -110
  250. package/test/integration/inventory-core.test.mjs +0 -53
  251. package/test/integration/inventory-eligibility.test.mjs +0 -59
  252. package/test/integration/inventory-evidence.test.mjs +0 -125
  253. package/test/integration/knowledge-rpc.test.mjs +0 -112
  254. package/test/integration/local-fs.test.mjs +0 -113
  255. package/test/integration/local-provider-bridge.test.mjs +0 -65
  256. package/test/integration/local-studio-settings-production.test.mjs +0 -40
  257. package/test/integration/lockfile-sync.test.mjs +0 -26
  258. package/test/integration/merkle-cli.test.mjs +0 -61
  259. package/test/integration/merkle-persistence-identity.test.mjs +0 -48
  260. package/test/integration/plugins-cloudflare.integration.test.mjs +0 -28
  261. package/test/integration/provider-env-cli.test.mjs +0 -60
  262. package/test/integration/provider-factory.test.mjs +0 -197
  263. package/test/integration/repository-company-graph.test.mjs +0 -90
  264. package/test/integration/runtime-migrations.test.mjs +0 -87
  265. package/test/integration/runtime-status.integration.test.mjs +0 -227
  266. package/test/integration/sam-activity-recovery.test.mjs +0 -147
  267. package/test/integration/sam-decision.test.mjs +0 -584
  268. package/test/integration/sam-kernel.test.mjs +0 -99
  269. package/test/integration/sam-planning-astar.test.mjs +0 -279
  270. package/test/integration/scaffold-cloudflare.test.mjs +0 -46
  271. package/test/integration/skill-runtime.test.mjs +0 -240
  272. package/test/integration/storage-architecture.test.mjs +0 -154
  273. package/test/integration/store-discovery.test.mjs +0 -44
  274. package/test/integration/studio-fs-pty-e2e.test.mjs +0 -294
  275. package/test/integration/terminal-exec.integration.test.mjs +0 -86
  276. package/test/integration/theme-package-registry.test.mjs +0 -31
  277. package/test/integration/tool-runtime.test.mjs +0 -124
  278. package/test/integration/tool-schema.test.mjs +0 -59
  279. package/test/jr-dev-skill.test.mjs +0 -26
  280. package/test/knowledge-context-pack.test.mjs +0 -19
  281. package/test/knowledge-postgres.test.mjs +0 -40
  282. package/test/knowledge-service.test.mjs +0 -110
  283. package/test/knowledge.test.mjs +0 -206
  284. package/test/live/terminal-transport.live.test.mjs +0 -24
  285. package/test/local-sessions.test.mjs +0 -57
  286. package/test/local-studio-deploy.test.mjs +0 -83
  287. package/test/loopback-oauth.test.mjs +0 -53
  288. package/test/merkle-render.test.mjs +0 -31
  289. package/test/mini.test.mjs +0 -140
  290. package/test/model-catalog.test.mjs +0 -70
  291. package/test/models.test.mjs +0 -309
  292. package/test/npm10-lock.test.mjs +0 -29
  293. package/test/ollama.test.mjs +0 -137
  294. package/test/open-url.test.mjs +0 -64
  295. package/test/openai-responses.test.mjs +0 -155
  296. package/test/portable-context.test.mjs +0 -94
  297. package/test/project-config.test.mjs +0 -81
  298. package/test/project-rules.test.mjs +0 -44
  299. package/test/provider-credentials.test.mjs +0 -106
  300. package/test/rehydrate.test.mjs +0 -25
  301. package/test/release-hygiene.test.mjs +0 -42
  302. package/test/repository-snapshot-view.test.mjs +0 -112
  303. package/test/responses-runner.test.mjs +0 -465
  304. package/test/runtime-activity.test.mjs +0 -98
  305. package/test/sdk-worker-contract.test.mjs +0 -72
  306. package/test/security.test.mjs +0 -266
  307. package/test/setup-planner.test.mjs +0 -74
  308. package/test/setup-runtime.test.mjs +0 -51
  309. package/test/shell.test.mjs +0 -281
  310. package/test/skills.test.mjs +0 -22
  311. package/test/smoke.mjs +0 -122
  312. package/test/telemetry.test.mjs +0 -79
  313. package/test/terminal/local-pty.mock.test.mjs +0 -153
  314. package/test/terminal-machine-identity.test.mjs +0 -88
  315. package/test/theme-portability.test.mjs +0 -14
  316. package/test/tools-search.test.mjs +0 -73
  317. package/test/unit/website-assets-bindings.test.mjs +0 -60
  318. package/test/whoami-resume.test.mjs +0 -157
@@ -0,0 +1,670 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { execFileSync } from 'node:child_process';
5
+ import { tryResolveGitContext } from './git-context.js';
6
+ import {
7
+ createTicketId,
8
+ createAgentRunId,
9
+ generateTicketCreateSql,
10
+ generateTicketCloseSql,
11
+ } from './tickets.js';
12
+
13
+ function clean(value) {
14
+ return value == null ? '' : String(value).trim();
15
+ }
16
+
17
+ function sqlEsc(value) {
18
+ return String(value ?? '').replaceAll("'", "''");
19
+ }
20
+
21
+ function formatDate(epoch) {
22
+ if (!epoch) return 'none';
23
+ const num = Number(epoch);
24
+ return Number.isFinite(num) ? new Date(num * 1000).toISOString().replace('T', ' ').slice(0, 19) : String(epoch);
25
+ }
26
+
27
+ function executeD1JsonQuery({
28
+ cwd = process.cwd(),
29
+ sql,
30
+ query = null,
31
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
32
+ databaseName = 'inneranimalmedia-business',
33
+ }) {
34
+ if (typeof query === 'function') return query(sql);
35
+ const configPath = path.resolve(cwd, wranglerConfig);
36
+ const args = ['d1', 'execute', databaseName, '--remote', '--json'];
37
+ if (fs.existsSync(configPath)) args.push('--config', configPath);
38
+ args.push('--command', sql);
39
+
40
+ const out = execFileSync('npx', ['wrangler', ...args], {
41
+ cwd,
42
+ encoding: 'utf8',
43
+ stdio: ['ignore', 'pipe', 'pipe'],
44
+ });
45
+
46
+ const startIdx = out.indexOf('[');
47
+ const endIdx = out.lastIndexOf(']');
48
+ if (startIdx === -1 || endIdx === -1) {
49
+ throw new Error(`Invalid JSON output from D1: ${out.slice(0, 200)}`);
50
+ }
51
+ return JSON.parse(out.slice(startIdx, endIdx + 1));
52
+ }
53
+
54
+ function executeD1WriteSql({
55
+ cwd = process.cwd(),
56
+ sql,
57
+ write = null,
58
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
59
+ databaseName = 'inneranimalmedia-business',
60
+ }) {
61
+ if (typeof write === 'function') return write(sql);
62
+ const configPath = path.resolve(cwd, wranglerConfig);
63
+ const tmpFile = path.join(os.tmpdir(), `agentsam-d1-${Date.now()}-${Math.random().toString(36).slice(2, 7)}.sql`);
64
+ fs.writeFileSync(tmpFile, `${sql}\n`, 'utf8');
65
+
66
+ try {
67
+ const args = ['d1', 'execute', databaseName, '--remote', '--yes'];
68
+ if (fs.existsSync(configPath)) args.push('--config', configPath);
69
+ args.push(`--file=${tmpFile}`);
70
+
71
+ return execFileSync('npx', ['wrangler', ...args], {
72
+ cwd,
73
+ encoding: 'utf8',
74
+ stdio: ['ignore', 'pipe', 'pipe'],
75
+ });
76
+ } finally {
77
+ try { fs.unlinkSync(tmpFile); } catch {}
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Read the complete GOAP state straight off tables:
83
+ * - agentsam_workspace_state (beliefs, lock, checkpoint)
84
+ * - agentsam_tickets (active goal/task, linked commit, agent run pointer)
85
+ * - agentsam_agent_run (live run status, calls, tokens)
86
+ * - agentsam_work_git_commits (recent commit history)
87
+ * - agentsam_work_tracking_checkpoint (ingest cursor)
88
+ */
89
+ export async function readGoapState({
90
+ cwd = process.cwd(),
91
+ repositoryId = null,
92
+ accountId = null,
93
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
94
+ databaseName = 'inneranimalmedia-business',
95
+ query = null,
96
+ } = {}) {
97
+ const git = tryResolveGitContext({ cwd });
98
+ const repoId = repositoryId || (git?.repoFullName ? `github:${git.repoFullName.toLowerCase()}` : null);
99
+ if (!repoId) return { ok: false, error: 'repository_identity_unresolved', git };
100
+ const accId = clean(accountId);
101
+ if (!accId) return { ok: false, repositoryId: repoId, error: 'account_id_required', git };
102
+
103
+ try {
104
+ const sql = `
105
+ SELECT * FROM agentsam_workspace_state WHERE repository_id = '${sqlEsc(repoId)}' LIMIT 1;
106
+ SELECT * FROM agentsam_tickets WHERE id = (SELECT current_task_id FROM agentsam_workspace_state WHERE repository_id = '${sqlEsc(repoId)}') AND account_id = '${sqlEsc(accId)}' AND repository_id = '${sqlEsc(repoId)}' LIMIT 1;
107
+ SELECT * FROM agentsam_agent_run WHERE id = (SELECT agent_run_id FROM agentsam_tickets WHERE id = (SELECT current_task_id FROM agentsam_workspace_state WHERE repository_id = '${sqlEsc(repoId)}') AND account_id = '${sqlEsc(accId)}' AND repository_id = '${sqlEsc(repoId)}' LIMIT 1) LIMIT 1;
108
+ SELECT sha, message, committed_at FROM agentsam_work_git_commits WHERE repository_id = '${sqlEsc(repoId)}' ORDER BY committed_at DESC LIMIT 3;
109
+ SELECT * FROM agentsam_work_tracking_checkpoint WHERE repository_id = '${sqlEsc(repoId)}' AND tracker_key = 'git_commit_ingest' LIMIT 1;
110
+ SELECT id, title, status, sort_order FROM agentsam_todo
111
+ WHERE plan_id IN (SELECT id FROM agentsam_plans WHERE agent_run_id = (SELECT agent_run_id FROM agentsam_tickets WHERE id = (SELECT current_task_id FROM agentsam_workspace_state WHERE repository_id = '${sqlEsc(repoId)}') LIMIT 1))
112
+ ORDER BY sort_order, created_at_unix;
113
+ `;
114
+ const data = await executeD1JsonQuery({ cwd, sql, query, wranglerConfig, databaseName });
115
+ const workspaceState = data?.[0]?.results?.[0] || null;
116
+ const activeTicket = data?.[1]?.results?.[0] || null;
117
+ const agentRun = data?.[2]?.results?.[0] || null;
118
+ const recentCommits = data?.[3]?.results || [];
119
+ const checkpoint = data?.[4]?.results?.[0] || null;
120
+ const steps = (data?.[5]?.results || []).map((row) => ({
121
+ id: row.id,
122
+ title: row.title,
123
+ status: row.status,
124
+ sort_order: row.sort_order,
125
+ }));
126
+
127
+ let cursor = {};
128
+ if (checkpoint?.cursor_json) {
129
+ try { cursor = JSON.parse(checkpoint.cursor_json); } catch {}
130
+ }
131
+
132
+ return {
133
+ ok: true,
134
+ repositoryId: repoId,
135
+ git,
136
+ workspaceState,
137
+ activeTicket,
138
+ agentRun,
139
+ recentCommits,
140
+ checkpoint,
141
+ cursor,
142
+ steps,
143
+ };
144
+ } catch (err) {
145
+ return {
146
+ ok: false,
147
+ repositoryId: repoId,
148
+ git,
149
+ error: err?.stderr || err?.message || String(err),
150
+ };
151
+ }
152
+ }
153
+
154
+ /**
155
+ * List all GOAP tickets/goals for the current repository and workspace.
156
+ */
157
+ export async function listGoapTickets({
158
+ cwd = process.cwd(),
159
+ repositoryId = null,
160
+ accountId = null,
161
+ limit = 20,
162
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
163
+ databaseName = 'inneranimalmedia-business',
164
+ query = null,
165
+ } = {}) {
166
+ const git = tryResolveGitContext({ cwd });
167
+ const repoId = repositoryId || (git?.repoFullName ? `github:${git.repoFullName.toLowerCase()}` : null);
168
+ if (!repoId) return { ok: false, error: 'repository_identity_unresolved', git, tickets: [] };
169
+
170
+ try {
171
+ const accId = clean(accountId);
172
+ if (!accId) return { ok: false, repositoryId: repoId, error: 'account_id_required', tickets: [] };
173
+ const sql = `
174
+ SELECT current_task_id FROM agentsam_workspace_state WHERE repository_id = '${sqlEsc(repoId)}' LIMIT 1;
175
+ SELECT id, title, status, priority, subsystem, surface, agent_run_id, linked_commit,
176
+ account_id, repository_id, owner_ref, created_at, updated_at
177
+ FROM agentsam_tickets
178
+ WHERE account_id = '${sqlEsc(accId)}' AND repository_id = '${sqlEsc(repoId)}'
179
+ ORDER BY
180
+ (id = (SELECT current_task_id FROM agentsam_workspace_state WHERE repository_id = '${sqlEsc(repoId)}' LIMIT 1)) DESC,
181
+ CASE status
182
+ WHEN 'active' THEN 1
183
+ WHEN 'backlog' THEN 2
184
+ WHEN 'blocked' THEN 3
185
+ ELSE 4
186
+ END,
187
+ updated_at DESC
188
+ LIMIT ${Math.max(1, Math.min(Number(limit) || 20, 100))};
189
+ `;
190
+ const data = await executeD1JsonQuery({ cwd, sql, query, wranglerConfig, databaseName });
191
+ const currentTaskId = data?.[0]?.results?.[0]?.current_task_id || null;
192
+ const tickets = data?.[1]?.results || [];
193
+
194
+ return {
195
+ ok: true,
196
+ repositoryId: repoId,
197
+ currentTaskId,
198
+ tickets,
199
+ };
200
+ } catch (err) {
201
+ return {
202
+ ok: false,
203
+ repositoryId: repoId,
204
+ error: err?.stderr || err?.message || String(err),
205
+ tickets: [],
206
+ };
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Create and activate a new GOAP goal/ticket.
212
+ */
213
+ export async function createGoapGoal({
214
+ cwd = process.cwd(),
215
+ title,
216
+ accountId = null,
217
+ priority = 'P2',
218
+ subsystem = 'agent-runtime',
219
+ description = null,
220
+ surface = 'platform',
221
+ status = 'active',
222
+ setActive = true,
223
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
224
+ databaseName = 'inneranimalmedia-business',
225
+ write = null,
226
+ } = {}) {
227
+ const cleanTitle = clean(title);
228
+ if (!cleanTitle) throw new Error('title_required');
229
+
230
+ const git = tryResolveGitContext({ cwd });
231
+ const repoId = git?.repoFullName ? `github:${git.repoFullName.toLowerCase()}` : 'github:local/workspace';
232
+
233
+ let accId = clean(accountId);
234
+ if (!accId) throw new Error('account_id_required');
235
+
236
+ const ticketId = createTicketId();
237
+ const agentRunId = createAgentRunId();
238
+ const now = Math.floor(Date.now() / 1000);
239
+
240
+ const { sql: ticketSql } = generateTicketCreateSql({
241
+ accountId: accId,
242
+ ticketId,
243
+ title: cleanTitle,
244
+ description,
245
+ status,
246
+ priority,
247
+ subsystem,
248
+ surface,
249
+ accountIdForTicket: accId,
250
+ repositoryId: repoId,
251
+ ownerRef: repoId,
252
+ source: 'agentsam_sdk',
253
+ agentRunId,
254
+ now,
255
+ });
256
+
257
+ const statements = [ticketSql];
258
+
259
+ if (setActive) {
260
+ const wsId = `ws_${repoId.replace(/[^a-zA-Z0-9_]/g, '_')}`;
261
+ statements.push(`
262
+ INSERT INTO agentsam_workspace_state (
263
+ id, repository_id, workspace_id, current_task_id, locked_by, checkpoint_sha,
264
+ last_agent_action, state_json, created_at, updated_at
265
+ ) VALUES (
266
+ 'wss_' || lower(hex(randomblob(8))),
267
+ '${sqlEsc(repoId)}',
268
+ '${sqlEsc(wsId)}',
269
+ '${sqlEsc(ticketId)}',
270
+ 'agentsam_cli',
271
+ ${git?.headSha ? `'${sqlEsc(git.headSha.slice(0, 10))}'` : 'NULL'},
272
+ 'created_and_activated_goal',
273
+ '{}',
274
+ ${now},
275
+ ${now}
276
+ )
277
+ ON CONFLICT(repository_id) DO UPDATE SET
278
+ current_task_id = '${sqlEsc(ticketId)}',
279
+ last_agent_action = 'activated_goal',
280
+ updated_at = ${now};
281
+ `);
282
+ }
283
+
284
+ const fullSql = statements.join('\n\n');
285
+ await executeD1WriteSql({ cwd, sql: fullSql, write, wranglerConfig, databaseName });
286
+
287
+ return {
288
+ ok: true,
289
+ ticketId,
290
+ agentRunId,
291
+ title: cleanTitle,
292
+ status,
293
+ priority,
294
+ subsystem,
295
+ active: setActive,
296
+ };
297
+ }
298
+
299
+ /**
300
+ * Switch active GOAP focus to an existing ticket.
301
+ */
302
+ export async function switchGoapGoal({
303
+ cwd = process.cwd(),
304
+ ticketId,
305
+ accountId = null,
306
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
307
+ databaseName = 'inneranimalmedia-business',
308
+ query = null,
309
+ write = null,
310
+ } = {}) {
311
+ const tid = clean(ticketId);
312
+ if (!tid) throw new Error('ticket_id_required');
313
+
314
+ const git = tryResolveGitContext({ cwd });
315
+ const repoId = git?.repoFullName ? `github:${git.repoFullName.toLowerCase()}` : 'github:local/workspace';
316
+ const now = Math.floor(Date.now() / 1000);
317
+ const wsId = `ws_${repoId.replace(/[^a-zA-Z0-9_]/g, '_')}`;
318
+ const lookup = await executeD1JsonQuery({
319
+ cwd,
320
+ query,
321
+ wranglerConfig,
322
+ databaseName,
323
+ sql: `SELECT id, account_id, repository_id FROM agentsam_tickets WHERE id = '${sqlEsc(tid)}' LIMIT 1;`,
324
+ });
325
+ const ticket = lookup?.[0]?.results?.[0];
326
+ const accId = clean(accountId);
327
+ if (!ticket) throw new Error('ticket_not_found');
328
+ if (ticket.repository_id && ticket.repository_id !== repoId) throw new Error('ticket_repository_mismatch');
329
+ if (!accId || ticket.account_id !== accId) throw new Error('ticket_account_mismatch');
330
+ const runId = createAgentRunId();
331
+
332
+ const sql = `
333
+ INSERT INTO agentsam_agent_run (
334
+ id, account_id, mode, status, started_at_unix, created_at_unix, updated_at_unix
335
+ ) VALUES ('${sqlEsc(runId)}', '${sqlEsc(accId)}', 'agent', 'running', ${now}, ${now}, ${now});
336
+
337
+ UPDATE agentsam_tickets SET
338
+ status = 'active',
339
+ agent_run_id = '${sqlEsc(runId)}',
340
+ updated_at = ${now}
341
+ WHERE id = '${sqlEsc(tid)}';
342
+
343
+ INSERT INTO agentsam_workspace_state (
344
+ id, repository_id, workspace_id, current_task_id, locked_by, checkpoint_sha,
345
+ last_agent_action, state_json, created_at, updated_at
346
+ ) VALUES (
347
+ 'wss_' || lower(hex(randomblob(8))),
348
+ '${sqlEsc(repoId)}',
349
+ '${sqlEsc(wsId)}',
350
+ '${sqlEsc(tid)}',
351
+ 'agentsam_cli',
352
+ ${git?.headSha ? `'${sqlEsc(git.headSha.slice(0, 10))}'` : 'NULL'},
353
+ 'switched_active_goal',
354
+ '{}',
355
+ ${now},
356
+ ${now}
357
+ )
358
+ ON CONFLICT(repository_id) DO UPDATE SET
359
+ current_task_id = '${sqlEsc(tid)}',
360
+ last_agent_action = 'switched_active_goal',
361
+ updated_at = ${now};
362
+ `;
363
+
364
+ await executeD1WriteSql({ cwd, sql, write, wranglerConfig, databaseName });
365
+
366
+ return {
367
+ ok: true,
368
+ ticketId: tid,
369
+ repositoryId: repoId,
370
+ agentRunId: runId,
371
+ };
372
+ }
373
+
374
+ /**
375
+ * Close/ship the active GOAP goal or a specified ticket.
376
+ */
377
+ export async function closeGoapGoal({
378
+ cwd = process.cwd(),
379
+ ticketId = null,
380
+ status = 'shipped',
381
+ statusReason = null,
382
+ linkedCommit = null,
383
+ clearActive = true,
384
+ accountId = null,
385
+ wranglerConfig = 'apps/local-studio/backend/wrangler.jsonc',
386
+ databaseName = 'inneranimalmedia-business',
387
+ query = null,
388
+ write = null,
389
+ } = {}) {
390
+ const git = tryResolveGitContext({ cwd });
391
+ const repoId = git?.repoFullName ? `github:${git.repoFullName.toLowerCase()}` : 'github:local/workspace';
392
+ const now = Math.floor(Date.now() / 1000);
393
+
394
+ let tid = clean(ticketId);
395
+ if (!tid) {
396
+ const existing = await readGoapState({ cwd, accountId, wranglerConfig, databaseName, query });
397
+ tid = existing?.workspaceState?.current_task_id || existing?.activeTicket?.id;
398
+ }
399
+ if (!tid) throw new Error('no_active_ticket_to_close');
400
+ const lookup = await executeD1JsonQuery({
401
+ cwd,
402
+ query,
403
+ wranglerConfig,
404
+ databaseName,
405
+ sql: `SELECT id, account_id, repository_id FROM agentsam_tickets WHERE id = '${sqlEsc(tid)}' LIMIT 1;`,
406
+ });
407
+ const ticket = lookup?.[0]?.results?.[0];
408
+ const accId = clean(accountId);
409
+ if (!ticket) throw new Error('ticket_not_found');
410
+ if (ticket.repository_id && ticket.repository_id !== repoId) throw new Error('ticket_repository_mismatch');
411
+ if (!accId || ticket.account_id !== accId) throw new Error('ticket_account_mismatch');
412
+
413
+ const commitSha = clean(linkedCommit) || clean(git?.headSha) || null;
414
+ const { sql: closeSql } = generateTicketCloseSql({
415
+ ticketId: tid,
416
+ status,
417
+ statusReason: statusReason || `closed_via_goap_${status}`,
418
+ linkedCommit: commitSha,
419
+ now,
420
+ });
421
+
422
+ const statements = [closeSql];
423
+
424
+ if (clearActive) {
425
+ statements.push(`
426
+ UPDATE agentsam_workspace_state SET
427
+ current_task_id = NULL,
428
+ last_agent_action = 'closed_task_${sqlEsc(tid)}_${sqlEsc(status)}',
429
+ updated_at = ${now}
430
+ WHERE repository_id = '${sqlEsc(repoId)}';
431
+ `);
432
+ }
433
+
434
+ const fullSql = statements.join('\n\n');
435
+ await executeD1WriteSql({ cwd, sql: fullSql, write, wranglerConfig, databaseName });
436
+
437
+ return {
438
+ ok: true,
439
+ ticketId: tid,
440
+ status,
441
+ linkedCommit: commitSha,
442
+ clearedActive: clearActive,
443
+ };
444
+ }
445
+
446
+ /**
447
+ * Render GOAP status view.
448
+ */
449
+ export function renderGoapStatus(state = {}) {
450
+ const ws = state.workspaceState || {};
451
+ const ticket = state.activeTicket || {};
452
+ const run = state.agentRun || {};
453
+ const cp = state.cursor || {};
454
+ const git = state.git || {};
455
+ const headSha = git?.revisionSha || git?.headSha || 'unknown';
456
+
457
+ return [
458
+ '================================================================================',
459
+ ' GOAP BLACKBOARD STATUS ',
460
+ '================================================================================',
461
+ `Repository: ${state.repositoryId || git?.repoFullName || 'unknown'}`,
462
+ `Branch / HEAD: ${git?.branch || 'main'} @ ${headSha !== 'unknown' ? headSha.slice(0, 10) : 'unknown'} (${git?.dirty ? 'DIRTY' : 'CLEAN'})`,
463
+ `Locked By: ${ws.locked_by || 'unlocked'}`,
464
+ `Active Task: ${ws.current_task_id || ticket.id || 'none'}`,
465
+ `Task Title: ${ticket.title || 'no active ticket'}`,
466
+ `Task Status: ${ticket.status || 'none'} [Priority: ${ticket.priority || 'P2'}] [Subsystem: ${ticket.subsystem || 'general'}]`,
467
+ `Agent Run: ${ticket.agent_run_id || run.id || 'none'} [Status: ${run.status || 'none'}] [Mode: ${run.mode || 'agent'}]`,
468
+ `Linked Commit: ${ticket.linked_commit ? ticket.linked_commit.slice(0, 10) : 'none'}`,
469
+ `Checkpoint: ${ws.checkpoint_sha ? ws.checkpoint_sha.slice(0, 10) : 'none'} (Tracker cursor: ${cp.last_sha ? cp.last_sha.slice(0, 10) : 'none'})`,
470
+ `Last Action: ${ws.last_agent_action || 'none'}`,
471
+ `Updated: ${formatDate(ws.updated_at || ticket.updated_at)}`,
472
+ '--------------------------------------------------------------------------------',
473
+ `Recent Ingested Commits (${state.recentCommits?.length || 0}):`,
474
+ ...(state.recentCommits && state.recentCommits.length
475
+ ? state.recentCommits.map((c) => ` * ${c.sha.slice(0, 8)} ${c.message?.slice(0, 65)} (${formatDate(c.committed_at)})`)
476
+ : [' (no commits ingested yet)']),
477
+ '================================================================================',
478
+ ].join('\n');
479
+ }
480
+
481
+ /**
482
+ * Render GOAP list view.
483
+ */
484
+ export function renderGoapList(state = {}) {
485
+ const tickets = Array.isArray(state) ? state : (state.tickets || []);
486
+ const currentTaskId = state.currentTaskId || state.activeTaskId || null;
487
+
488
+ const header = [
489
+ '================================================================================',
490
+ ' GOAP TICKETS & GOALS ',
491
+ '================================================================================',
492
+ ];
493
+
494
+ if (!tickets.length) {
495
+ return [
496
+ ...header,
497
+ ' (no tickets found in agentsam_tickets)',
498
+ '',
499
+ ' To create a new goal, run:',
500
+ ' agentsam goap new "Your goal title" [--priority P1] [--subsystem sys]',
501
+ '================================================================================',
502
+ ].join('\n');
503
+ }
504
+
505
+ const rows = [
506
+ ' ACT STATUS PRI TICKET ID TITLE',
507
+ ' --- -------- ---- -------------------------- -----------------------------',
508
+ ];
509
+
510
+ for (const t of tickets) {
511
+ const isActive = Boolean(currentTaskId && t.id === currentTaskId);
512
+ const actMark = isActive ? ' * ' : ' ';
513
+ const status = (t.status || 'open').padEnd(8).slice(0, 8);
514
+ const pri = (t.priority || 'P2').padEnd(4).slice(0, 4);
515
+ const id = (t.id || '').padEnd(26).slice(0, 26);
516
+ const title = (t.title || 'untitled').slice(0, 42);
517
+ rows.push(` ${actMark} ${status} ${pri} ${id} ${title}`);
518
+ }
519
+
520
+ return [
521
+ ...header,
522
+ ...rows,
523
+ '--------------------------------------------------------------------------------',
524
+ ' * = active blackboard goal',
525
+ ' Commands:',
526
+ ' agentsam goap new "<title>" Create and activate a new goal',
527
+ ' agentsam goap switch <ticket_id> Switch active goal focus',
528
+ ' agentsam goap close [ticket_id] Close/ship active goal',
529
+ '================================================================================',
530
+ ].join('\n');
531
+ }
532
+
533
+ /**
534
+ * Render GOAP goal view.
535
+ */
536
+ export function renderGoapGoal(state = {}) {
537
+ const ws = state.workspaceState || {};
538
+ const ticket = state.activeTicket || {};
539
+ const run = state.agentRun || {};
540
+
541
+ return [
542
+ '================================================================================',
543
+ ' GOAP ACTIVE GOAL ',
544
+ '================================================================================',
545
+ `Goal ID: ${ticket.id || ws.current_task_id || 'none'}`,
546
+ `Title: ${ticket.title || 'no goal active'}`,
547
+ `Priority: ${ticket.priority || 'P2'}`,
548
+ `Subsystem: ${ticket.subsystem || 'general'}`,
549
+ `Surface: ${ticket.surface || 'platform'}`,
550
+ `Status: ${ticket.status || 'none'}`,
551
+ `Reason: ${ticket.status_reason || 'primary sprint goal'}`,
552
+ '--------------------------------------------------------------------------------',
553
+ 'EXECUTION RUN ENVELOPE:',
554
+ `Agent Run ID: ${ticket.agent_run_id || run.id || 'unassigned'}`,
555
+ `Run Status: ${run.status || 'unknown'}`,
556
+ `Run Mode: ${run.mode || 'agent'}`,
557
+ `Started At: ${formatDate(run.started_at_unix)}`,
558
+ `Calls / Tools: ${run.model_call_count || 0} model / ${run.tool_call_count || 0} tool calls`,
559
+ '--------------------------------------------------------------------------------',
560
+ 'GOAL SUCCESS CRITERIA:',
561
+ ' 1. Verify code changes pass local tests and typecheck.',
562
+ ' 2. Commit changes with a why-focused message.',
563
+ ' 3. Sync commit to agentsam_work_git_commits & advance checkpoint.',
564
+ ` 4. Populate agentsam_tickets.linked_commit for ${ticket.id || 'active task'}.`,
565
+ ' 5. Transition ticket to shipped and complete agent_run.',
566
+ '================================================================================',
567
+ ].join('\n');
568
+ }
569
+
570
+ /**
571
+ * Render GOAP why view.
572
+ */
573
+ export function renderGoapWhy(state = {}) {
574
+ const ws = state.workspaceState || {};
575
+ const ticket = state.activeTicket || {};
576
+ const git = state.git || {};
577
+ const headSha = git?.revisionSha || git?.headSha || 'unknown';
578
+
579
+ return [
580
+ '================================================================================',
581
+ ' GOAP BELIEF GROUNDING (WHY) ',
582
+ '================================================================================',
583
+ `Question: Why is task [${ticket.id || ws.current_task_id || 'none'}] active right now?`,
584
+ '',
585
+ 'BELIEF FOUNDATIONS:',
586
+ ` 1. Repository Identity: ${state.repositoryId || git?.repoFullName || 'unknown'}`,
587
+ ` - Workspace lock is held by '${ws.locked_by || 'agentsam_cli'}'.`,
588
+ ` - Current HEAD is ${headSha !== 'unknown' ? headSha.slice(0, 10) : 'unknown'} (${git?.dirty ? 'working tree dirty' : 'clean'}).`,
589
+ '',
590
+ ` 2. Ticket Priority & Assignment:`,
591
+ ` - Ticket [${ticket.id || ws.current_task_id || 'none'}] is marked '${ticket.status || 'active'}' with priority '${ticket.priority || 'P2'}'.`,
592
+ ` - Subsystem: '${ticket.subsystem || 'agent-runtime'}'.`,
593
+ ` - Title: ${ticket.title || 'no active ticket'}`,
594
+ '',
595
+ ` 3. Operational Provenance:`,
596
+ ` - Linked Agent Run: ${ticket.agent_run_id || 'none'}`,
597
+ ` - Checkpoint Commit: ${ws.checkpoint_sha ? ws.checkpoint_sha.slice(0, 10) : 'none'}`,
598
+ ` - Linked Commit: ${ticket.linked_commit ? ticket.linked_commit.slice(0, 10) : 'pending commit'}`,
599
+ ` - Last Agent Action: ${ws.last_agent_action || 'none'}`,
600
+ '',
601
+ 'CONCLUSION:',
602
+ ticket.id
603
+ ? ` The agent selected this action because ticket [${ticket.id}] has active operator\n focus, satisfies all prerequisite blockers, and is linked to the live workspace belief state.`
604
+ : ' No ticket is currently active. Run `agentsam goap list` or `agentsam goap new` to establish focus.',
605
+ '================================================================================',
606
+ ].join('\n');
607
+ }
608
+
609
+ /**
610
+ * Render GOAP plan view.
611
+ */
612
+ export function renderGoapPlan(state = {}) {
613
+ const ws = state.workspaceState || {};
614
+ const ticket = state.activeTicket || {};
615
+ const run = state.agentRun || {};
616
+ const git = state.git || {};
617
+
618
+ let steps = [];
619
+ if (Array.isArray(state.steps) && state.steps.length > 0) {
620
+ steps = state.steps.map((step) => ({
621
+ text: step.title || step.text || String(step),
622
+ status: step.status || 'open',
623
+ }));
624
+ } else if (ticket.plan_steps && Array.isArray(ticket.plan_steps)) {
625
+ steps = ticket.plan_steps;
626
+ } else if (ticket.description) {
627
+ const lines = ticket.description.split('\n')
628
+ .map((l) => l.trim())
629
+ .filter((l) => /^(\d+\.|\*|\-|\-\s*\[[ x]\])/i.test(l));
630
+ if (lines.length > 0) {
631
+ steps = lines.map((l) => l.replace(/^(\d+\.|\*|\-\s*\[[ x]\]|\-)\s*/, '').trim());
632
+ }
633
+ }
634
+
635
+ if (!steps.length) {
636
+ if (ticket.title) {
637
+ steps = [
638
+ `Step 1: Understand context and isolate scope for "${ticket.title}"`,
639
+ `Step 2: Implement focused changes with test-driven verification`,
640
+ `Step 3: Run repository test suite and verify build integrity`,
641
+ `Step 4: Commit changes with why-focused message linked to ${ticket.id || 'ticket'}`,
642
+ `Step 5: Transition ticket ${ticket.id || ''} to shipped and finalize agent run`,
643
+ ];
644
+ } else {
645
+ steps = [
646
+ 'No active goal selected. Use `agentsam goap new "<title>"` or `agentsam goap switch <ticket_id>` to select a goal.',
647
+ ];
648
+ }
649
+ }
650
+
651
+ return [
652
+ '================================================================================',
653
+ ' GOAP OPERATIONAL ACTION PLAN ',
654
+ '================================================================================',
655
+ `Objective: ${ticket.title || 'No active goal selected'}`,
656
+ `Active Ticket: ${ticket.id || ws.current_task_id || 'none'} [Priority: ${ticket.priority || 'P2'}]`,
657
+ `Active Run: ${ticket.agent_run_id || run.id || 'none'}`,
658
+ `Repository: ${state.repositoryId || git?.repoFullName || 'unknown'}`,
659
+ '',
660
+ 'PLANNED ACTION SEQUENCE:',
661
+ ...steps.map((step, idx) => {
662
+ const text = typeof step === 'string' ? step : step.text;
663
+ const status = typeof step === 'string' ? 'open' : step.status;
664
+ const prefix = text.startsWith('Step ') || /^\d+\./.test(text) ? '' : `Step ${idx + 1}: `;
665
+ const marker = status === 'complete' ? 'x' : status === 'blocked' ? '!' : ' ';
666
+ return ` [${marker}] ${prefix}${text}`;
667
+ }),
668
+ '================================================================================',
669
+ ].join('\n');
670
+ }