aether-colony 5.0.0 → 5.1.0

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 (312) hide show
  1. package/.aether/aether-utils.sh +3150 -3349
  2. package/.aether/agents-claude/aether-ambassador.md +265 -0
  3. package/.aether/agents-claude/aether-archaeologist.md +327 -0
  4. package/.aether/agents-claude/aether-architect.md +236 -0
  5. package/.aether/agents-claude/aether-auditor.md +271 -0
  6. package/.aether/agents-claude/aether-builder.md +224 -0
  7. package/.aether/agents-claude/aether-chaos.md +269 -0
  8. package/.aether/agents-claude/aether-chronicler.md +305 -0
  9. package/.aether/agents-claude/aether-gatekeeper.md +330 -0
  10. package/.aether/agents-claude/aether-includer.md +374 -0
  11. package/.aether/agents-claude/aether-keeper.md +272 -0
  12. package/.aether/agents-claude/aether-measurer.md +322 -0
  13. package/.aether/agents-claude/aether-oracle.md +237 -0
  14. package/.aether/agents-claude/aether-probe.md +211 -0
  15. package/.aether/agents-claude/aether-queen.md +330 -0
  16. package/.aether/agents-claude/aether-route-setter.md +178 -0
  17. package/.aether/agents-claude/aether-sage.md +418 -0
  18. package/.aether/agents-claude/aether-scout.md +179 -0
  19. package/.aether/agents-claude/aether-surveyor-disciplines.md +417 -0
  20. package/.aether/agents-claude/aether-surveyor-nest.md +355 -0
  21. package/.aether/agents-claude/aether-surveyor-pathogens.md +289 -0
  22. package/.aether/agents-claude/aether-surveyor-provisions.md +360 -0
  23. package/.aether/agents-claude/aether-tracker.md +270 -0
  24. package/.aether/agents-claude/aether-watcher.md +280 -0
  25. package/.aether/agents-claude/aether-weaver.md +248 -0
  26. package/.aether/commands/archaeology.yaml +653 -0
  27. package/.aether/commands/build.yaml +1221 -0
  28. package/.aether/commands/chaos.yaml +653 -0
  29. package/.aether/commands/colonize.yaml +438 -0
  30. package/.aether/commands/continue.yaml +1484 -0
  31. package/.aether/commands/council.yaml +304 -0
  32. package/.aether/commands/data-clean.yaml +80 -0
  33. package/.aether/commands/dream.yaml +275 -0
  34. package/.aether/commands/entomb.yaml +863 -0
  35. package/.aether/commands/export-signals.yaml +64 -0
  36. package/.aether/commands/feedback.yaml +158 -0
  37. package/.aether/commands/flag.yaml +160 -0
  38. package/.aether/commands/flags.yaml +177 -0
  39. package/.aether/commands/focus.yaml +112 -0
  40. package/.aether/commands/help.yaml +167 -0
  41. package/.aether/commands/history.yaml +137 -0
  42. package/.aether/commands/import-signals.yaml +79 -0
  43. package/.aether/commands/init.yaml +469 -0
  44. package/.aether/commands/insert-phase.yaml +98 -0
  45. package/.aether/commands/interpret.yaml +285 -0
  46. package/.aether/commands/lay-eggs.yaml +224 -0
  47. package/.aether/commands/maturity.yaml +122 -0
  48. package/.aether/commands/memory-details.yaml +74 -0
  49. package/.aether/commands/migrate-state.yaml +174 -0
  50. package/.aether/commands/oracle.yaml +1224 -0
  51. package/.aether/commands/organize.yaml +446 -0
  52. package/.aether/commands/patrol.yaml +621 -0
  53. package/.aether/commands/pause-colony.yaml +424 -0
  54. package/.aether/commands/phase.yaml +124 -0
  55. package/.aether/commands/pheromones.yaml +153 -0
  56. package/.aether/commands/plan.yaml +1313 -0
  57. package/.aether/commands/preferences.yaml +63 -0
  58. package/.aether/commands/redirect.yaml +123 -0
  59. package/.aether/commands/resume-colony.yaml +373 -0
  60. package/.aether/commands/resume.yaml +398 -0
  61. package/.aether/commands/run.yaml +193 -0
  62. package/.aether/commands/seal.yaml +1205 -0
  63. package/.aether/commands/skill-create.yaml +337 -0
  64. package/.aether/commands/status.yaml +364 -0
  65. package/.aether/commands/swarm.yaml +352 -0
  66. package/.aether/commands/tunnels.yaml +814 -0
  67. package/.aether/commands/update.yaml +131 -0
  68. package/.aether/commands/verify-castes.yaml +159 -0
  69. package/.aether/commands/watch.yaml +454 -0
  70. package/.aether/docs/INCIDENT_TEMPLATE.md +32 -0
  71. package/.aether/docs/QUEEN-SYSTEM.md +11 -11
  72. package/.aether/docs/README.md +32 -2
  73. package/.aether/docs/command-playbooks/README.md +23 -0
  74. package/.aether/docs/command-playbooks/build-complete.md +349 -0
  75. package/.aether/docs/command-playbooks/build-context.md +282 -0
  76. package/.aether/docs/command-playbooks/build-full.md +1682 -0
  77. package/.aether/docs/command-playbooks/build-prep.md +283 -0
  78. package/.aether/docs/command-playbooks/build-verify.md +405 -0
  79. package/.aether/docs/command-playbooks/build-wave.md +749 -0
  80. package/.aether/docs/command-playbooks/continue-advance.md +524 -0
  81. package/.aether/docs/command-playbooks/continue-finalize.md +447 -0
  82. package/.aether/docs/command-playbooks/continue-full.md +1724 -0
  83. package/.aether/docs/command-playbooks/continue-gates.md +686 -0
  84. package/.aether/docs/command-playbooks/continue-verify.md +406 -0
  85. package/.aether/docs/context-continuity.md +84 -0
  86. package/.aether/docs/disciplines/DISCIPLINES.md +9 -7
  87. package/.aether/docs/error-codes.md +1 -1
  88. package/.aether/docs/known-issues.md +34 -173
  89. package/.aether/docs/pheromones.md +86 -6
  90. package/.aether/docs/plans/pheromone-display-plan.md +257 -0
  91. package/.aether/docs/queen-commands.md +10 -9
  92. package/.aether/docs/source-of-truth-map.md +132 -0
  93. package/.aether/docs/xml-utilities.md +47 -0
  94. package/.aether/rules/aether-colony.md +23 -13
  95. package/.aether/scripts/incident-test-add.sh +47 -0
  96. package/.aether/scripts/weekly-audit.sh +79 -0
  97. package/.aether/skills/.index.json +649 -0
  98. package/.aether/skills/colony/.manifest.json +16 -0
  99. package/.aether/skills/colony/build-discipline/SKILL.md +78 -0
  100. package/.aether/skills/colony/colony-interaction/SKILL.md +56 -0
  101. package/.aether/skills/colony/colony-lifecycle/SKILL.md +77 -0
  102. package/.aether/skills/colony/colony-visuals/SKILL.md +112 -0
  103. package/.aether/skills/colony/context-management/SKILL.md +80 -0
  104. package/.aether/skills/colony/error-presentation/SKILL.md +99 -0
  105. package/.aether/skills/colony/pheromone-protocol/SKILL.md +79 -0
  106. package/.aether/skills/colony/pheromone-visibility/SKILL.md +81 -0
  107. package/.aether/skills/colony/state-safety/SKILL.md +84 -0
  108. package/.aether/skills/colony/worker-priming/SKILL.md +82 -0
  109. package/.aether/skills/domain/.manifest.json +24 -0
  110. package/.aether/skills/domain/README.md +33 -0
  111. package/.aether/skills/domain/django/SKILL.md +49 -0
  112. package/.aether/skills/domain/docker/SKILL.md +52 -0
  113. package/.aether/skills/domain/golang/SKILL.md +52 -0
  114. package/.aether/skills/domain/graphql/SKILL.md +51 -0
  115. package/.aether/skills/domain/html-css/SKILL.md +48 -0
  116. package/.aether/skills/domain/nextjs/SKILL.md +45 -0
  117. package/.aether/skills/domain/nodejs/SKILL.md +53 -0
  118. package/.aether/skills/domain/postgresql/SKILL.md +53 -0
  119. package/.aether/skills/domain/prisma/SKILL.md +59 -0
  120. package/.aether/skills/domain/python/SKILL.md +50 -0
  121. package/.aether/skills/domain/rails/SKILL.md +52 -0
  122. package/.aether/skills/domain/react/SKILL.md +45 -0
  123. package/.aether/skills/domain/rest-api/SKILL.md +58 -0
  124. package/.aether/skills/domain/svelte/SKILL.md +47 -0
  125. package/.aether/skills/domain/tailwind/SKILL.md +45 -0
  126. package/.aether/skills/domain/testing/SKILL.md +53 -0
  127. package/.aether/skills/domain/typescript/SKILL.md +58 -0
  128. package/.aether/skills/domain/vue/SKILL.md +49 -0
  129. package/.aether/templates/QUEEN.md.template +23 -41
  130. package/.aether/templates/colony-state-reset.jq.template +1 -0
  131. package/.aether/templates/colony-state.template.json +4 -0
  132. package/.aether/templates/learning-observations.template.json +6 -0
  133. package/.aether/templates/midden.template.json +13 -0
  134. package/.aether/templates/pheromones.template.json +6 -0
  135. package/.aether/templates/session.template.json +9 -0
  136. package/.aether/utils/atomic-write.sh +63 -17
  137. package/.aether/utils/chamber-utils.sh +145 -2
  138. package/.aether/utils/emoji-audit.sh +166 -0
  139. package/.aether/utils/error-handler.sh +21 -7
  140. package/.aether/utils/file-lock.sh +182 -27
  141. package/.aether/utils/flag.sh +267 -0
  142. package/.aether/utils/hive.sh +572 -0
  143. package/.aether/utils/learning.sh +1928 -0
  144. package/.aether/utils/midden.sh +342 -0
  145. package/.aether/utils/oracle/oracle.md +168 -0
  146. package/.aether/utils/oracle/oracle.sh +1023 -0
  147. package/.aether/utils/pheromone.sh +2029 -0
  148. package/.aether/utils/queen.sh +1698 -0
  149. package/.aether/utils/scan.sh +860 -0
  150. package/.aether/utils/semantic-cli.sh +10 -8
  151. package/.aether/utils/session.sh +552 -0
  152. package/.aether/utils/skills.sh +509 -0
  153. package/.aether/utils/spawn-tree.sh +103 -271
  154. package/.aether/utils/spawn.sh +260 -0
  155. package/.aether/utils/state-api.sh +199 -0
  156. package/.aether/utils/state-loader.sh +8 -6
  157. package/.aether/utils/suggest.sh +611 -0
  158. package/.aether/utils/swarm-display.sh +10 -1
  159. package/.aether/utils/swarm.sh +1004 -0
  160. package/.aether/utils/watch-spawn-tree.sh +11 -2
  161. package/.aether/utils/xml-compose.sh +2 -2
  162. package/.aether/utils/xml-convert.sh +9 -5
  163. package/.aether/utils/xml-core.sh +5 -9
  164. package/.aether/utils/xml-query.sh +4 -4
  165. package/.aether/workers.md +86 -67
  166. package/.claude/agents/ant/aether-ambassador.md +2 -1
  167. package/.claude/agents/ant/aether-archaeologist.md +6 -1
  168. package/.claude/agents/ant/aether-architect.md +236 -0
  169. package/.claude/agents/ant/aether-auditor.md +6 -1
  170. package/.claude/agents/ant/aether-builder.md +38 -1
  171. package/.claude/agents/ant/aether-chaos.md +2 -1
  172. package/.claude/agents/ant/aether-chronicler.md +1 -0
  173. package/.claude/agents/ant/aether-gatekeeper.md +6 -1
  174. package/.claude/agents/ant/aether-includer.md +1 -0
  175. package/.claude/agents/ant/aether-keeper.md +1 -0
  176. package/.claude/agents/ant/aether-measurer.md +6 -1
  177. package/.claude/agents/ant/aether-oracle.md +237 -0
  178. package/.claude/agents/ant/aether-probe.md +2 -1
  179. package/.claude/agents/ant/aether-queen.md +6 -1
  180. package/.claude/agents/ant/aether-route-setter.md +6 -1
  181. package/.claude/agents/ant/aether-sage.md +68 -3
  182. package/.claude/agents/ant/aether-scout.md +38 -1
  183. package/.claude/agents/ant/aether-surveyor-disciplines.md +2 -1
  184. package/.claude/agents/ant/aether-surveyor-nest.md +2 -1
  185. package/.claude/agents/ant/aether-surveyor-pathogens.md +2 -1
  186. package/.claude/agents/ant/aether-surveyor-provisions.md +2 -1
  187. package/.claude/agents/ant/aether-tracker.md +6 -1
  188. package/.claude/agents/ant/aether-watcher.md +37 -1
  189. package/.claude/agents/ant/aether-weaver.md +2 -1
  190. package/.claude/commands/ant/archaeology.md +1 -8
  191. package/.claude/commands/ant/build.md +43 -1159
  192. package/.claude/commands/ant/chaos.md +1 -14
  193. package/.claude/commands/ant/colonize.md +1 -14
  194. package/.claude/commands/ant/continue.md +40 -1026
  195. package/.claude/commands/ant/council.md +9 -16
  196. package/.claude/commands/ant/data-clean.md +81 -0
  197. package/.claude/commands/ant/dream.md +12 -9
  198. package/.claude/commands/ant/entomb.md +62 -87
  199. package/.claude/commands/ant/export-signals.md +57 -0
  200. package/.claude/commands/ant/feedback.md +18 -0
  201. package/.claude/commands/ant/flag.md +12 -0
  202. package/.claude/commands/ant/flags.md +22 -8
  203. package/.claude/commands/ant/focus.md +18 -0
  204. package/.claude/commands/ant/help.md +40 -8
  205. package/.claude/commands/ant/history.md +3 -0
  206. package/.claude/commands/ant/import-signals.md +71 -0
  207. package/.claude/commands/ant/init.md +316 -191
  208. package/.claude/commands/ant/insert-phase.md +101 -0
  209. package/.claude/commands/ant/interpret.md +11 -0
  210. package/.claude/commands/ant/lay-eggs.md +167 -158
  211. package/.claude/commands/ant/maturity.md +22 -11
  212. package/.claude/commands/ant/memory-details.md +77 -0
  213. package/.claude/commands/ant/migrate-state.md +6 -0
  214. package/.claude/commands/ant/oracle.md +317 -62
  215. package/.claude/commands/ant/organize.md +10 -5
  216. package/.claude/commands/ant/patrol.md +620 -0
  217. package/.claude/commands/ant/pause-colony.md +8 -22
  218. package/.claude/commands/ant/phase.md +26 -37
  219. package/.claude/commands/ant/pheromones.md +156 -0
  220. package/.claude/commands/ant/plan.md +175 -52
  221. package/.claude/commands/ant/preferences.md +65 -0
  222. package/.claude/commands/ant/redirect.md +18 -0
  223. package/.claude/commands/ant/resume-colony.md +34 -20
  224. package/.claude/commands/ant/resume.md +51 -7
  225. package/.claude/commands/ant/run.md +195 -0
  226. package/.claude/commands/ant/seal.md +497 -78
  227. package/.claude/commands/ant/skill-create.md +286 -0
  228. package/.claude/commands/ant/status.md +127 -1
  229. package/.claude/commands/ant/swarm.md +11 -23
  230. package/.claude/commands/ant/tunnels.md +1 -0
  231. package/.claude/commands/ant/update.md +58 -135
  232. package/.claude/commands/ant/verify-castes.md +90 -42
  233. package/.claude/commands/ant/watch.md +1 -0
  234. package/.opencode/agents/aether-ambassador.md +1 -1
  235. package/.opencode/agents/aether-architect.md +133 -0
  236. package/.opencode/agents/aether-builder.md +3 -3
  237. package/.opencode/agents/aether-oracle.md +137 -0
  238. package/.opencode/agents/aether-queen.md +1 -1
  239. package/.opencode/agents/aether-route-setter.md +1 -1
  240. package/.opencode/agents/aether-scout.md +1 -1
  241. package/.opencode/agents/aether-surveyor-disciplines.md +6 -1
  242. package/.opencode/agents/aether-surveyor-nest.md +6 -1
  243. package/.opencode/agents/aether-surveyor-pathogens.md +6 -1
  244. package/.opencode/agents/aether-surveyor-provisions.md +6 -1
  245. package/.opencode/agents/aether-tracker.md +1 -1
  246. package/.opencode/agents/aether-watcher.md +1 -1
  247. package/.opencode/agents/aether-weaver.md +1 -1
  248. package/.opencode/commands/ant/archaeology.md +7 -14
  249. package/.opencode/commands/ant/build.md +54 -88
  250. package/.opencode/commands/ant/chaos.md +7 -24
  251. package/.opencode/commands/ant/colonize.md +8 -17
  252. package/.opencode/commands/ant/continue.md +595 -66
  253. package/.opencode/commands/ant/council.md +11 -22
  254. package/.opencode/commands/ant/data-clean.md +77 -0
  255. package/.opencode/commands/ant/dream.md +15 -17
  256. package/.opencode/commands/ant/entomb.md +28 -18
  257. package/.opencode/commands/ant/export-signals.md +54 -0
  258. package/.opencode/commands/ant/feedback.md +24 -5
  259. package/.opencode/commands/ant/flag.md +16 -4
  260. package/.opencode/commands/ant/flags.md +24 -10
  261. package/.opencode/commands/ant/focus.md +22 -5
  262. package/.opencode/commands/ant/help.md +41 -8
  263. package/.opencode/commands/ant/history.md +9 -0
  264. package/.opencode/commands/ant/import-signals.md +68 -0
  265. package/.opencode/commands/ant/init.md +365 -156
  266. package/.opencode/commands/ant/insert-phase.md +107 -0
  267. package/.opencode/commands/ant/interpret.md +16 -0
  268. package/.opencode/commands/ant/lay-eggs.md +184 -112
  269. package/.opencode/commands/ant/maturity.md +18 -2
  270. package/.opencode/commands/ant/memory-details.md +83 -0
  271. package/.opencode/commands/ant/migrate-state.md +12 -0
  272. package/.opencode/commands/ant/oracle.md +322 -67
  273. package/.opencode/commands/ant/organize.md +14 -12
  274. package/.opencode/commands/ant/patrol.md +626 -0
  275. package/.opencode/commands/ant/pause-colony.md +12 -29
  276. package/.opencode/commands/ant/phase.md +30 -40
  277. package/.opencode/commands/ant/pheromones.md +162 -0
  278. package/.opencode/commands/ant/plan.md +184 -56
  279. package/.opencode/commands/ant/preferences.md +71 -0
  280. package/.opencode/commands/ant/redirect.md +22 -5
  281. package/.opencode/commands/ant/resume-colony.md +38 -27
  282. package/.opencode/commands/ant/resume.md +71 -20
  283. package/.opencode/commands/ant/run.md +201 -0
  284. package/.opencode/commands/ant/seal.md +230 -25
  285. package/.opencode/commands/ant/skill-create.md +63 -0
  286. package/.opencode/commands/ant/status.md +124 -31
  287. package/.opencode/commands/ant/swarm.md +3 -345
  288. package/.opencode/commands/ant/tunnels.md +3 -9
  289. package/.opencode/commands/ant/update.md +63 -127
  290. package/.opencode/commands/ant/verify-castes.md +96 -42
  291. package/.opencode/commands/ant/watch.md +7 -0
  292. package/CHANGELOG.md +278 -1
  293. package/README.md +188 -340
  294. package/bin/cli.js +236 -429
  295. package/bin/generate-commands.js +186 -0
  296. package/bin/generate-commands.sh +128 -89
  297. package/bin/lib/spawn-logger.js +0 -15
  298. package/bin/lib/update-transaction.js +285 -35
  299. package/bin/npx-install.js +178 -0
  300. package/bin/validate-package.sh +85 -3
  301. package/package.json +7 -3
  302. package/.aether/CONTEXT.md +0 -160
  303. package/.aether/docs/QUEEN.md +0 -84
  304. package/.aether/exchange/colony-registry.xml +0 -11
  305. package/.aether/exchange/pheromones.xml +0 -87
  306. package/.aether/exchange/queen-wisdom.xml +0 -14
  307. package/.aether/model-profiles.yaml +0 -100
  308. package/.aether/utils/spawn-with-model.sh +0 -56
  309. package/bin/lib/model-profiles.js +0 -445
  310. package/bin/lib/model-verify.js +0 -288
  311. package/bin/lib/proxy-health.js +0 -253
  312. package/bin/lib/telemetry.js +0 -441
@@ -74,7 +74,7 @@ semantic-index() {
74
74
  local entry_id="${3:-}"
75
75
 
76
76
  if [[ -z "$text" ]]; then
77
- json_err 1 "semantic-index requires text argument"
77
+ semantic_json_err 1 "semantic-index requires text argument"
78
78
  return 1
79
79
  fi
80
80
 
@@ -161,12 +161,12 @@ semantic-search() {
161
161
  local source_filter="${4:-}"
162
162
 
163
163
  if [[ -z "$query" ]]; then
164
- json_err 1 "semantic-search requires query argument"
164
+ semantic_json_err 1 "semantic-search requires query argument"
165
165
  return 1
166
166
  fi
167
167
 
168
168
  if [[ ! -f "$SEMANTIC_EMBEDDINGS_FILE" ]]; then
169
- json_ok '{"results":[]}' "No semantic index found. Run semantic-init first."
169
+ semantic_json_ok '{"results":[]}' "No semantic index found. Run semantic-init first."
170
170
  return 0
171
171
  fi
172
172
 
@@ -236,7 +236,7 @@ semantic-find-duplicate() {
236
236
  local threshold="${2:-0.85}"
237
237
 
238
238
  if [[ -z "$text" ]]; then
239
- json_err 1 "semantic-find-duplicate requires text argument"
239
+ semantic_json_err 1 "semantic-find-duplicate requires text argument"
240
240
  return 1
241
241
  fi
242
242
 
@@ -249,7 +249,7 @@ semantic-find-duplicate() {
249
249
  if [[ "$count" -gt 0 ]]; then
250
250
  echo "$result" | jq '. + {"is_duplicate": true}'
251
251
  else
252
- json_ok "[]" "No duplicates found"
252
+ semantic_json_ok "[]" "No duplicates found"
253
253
  fi
254
254
  }
255
255
 
@@ -368,7 +368,7 @@ semantic-get-context() {
368
368
  # Check semantic layer status
369
369
  semantic-status() {
370
370
  if [[ ! -f "$SEMANTIC_DATA_DIR/index.json" ]]; then
371
- json_ok '{"initialized": false, "message": "Run semantic-init to initialize"}'
371
+ semantic_json_ok '{"initialized": false, "message": "Run semantic-init to initialize"}'
372
372
  return 0
373
373
  fi
374
374
 
@@ -387,7 +387,7 @@ semantic-status() {
387
387
  }
388
388
 
389
389
  # Helper: Output JSON OK response
390
- json_ok() {
390
+ semantic_json_ok() {
391
391
  local result="${1:-}"
392
392
  local message="${2:-}"
393
393
  jq -n --argjson result "$result" --arg message "$message" \
@@ -395,7 +395,7 @@ json_ok() {
395
395
  }
396
396
 
397
397
  # Helper: Output JSON error response
398
- json_err() {
398
+ semantic_json_err() {
399
399
  local code="${1:-1}"
400
400
  local message="${2:-Unknown error}"
401
401
  jq -n --arg code "$code" --arg message "$message" \
@@ -411,3 +411,5 @@ export -f semantic-rebuild
411
411
  export -f semantic-get-context
412
412
  export -f semantic-status
413
413
  export -f semantic-check-deps
414
+ export -f semantic_json_ok
415
+ export -f semantic_json_err
@@ -0,0 +1,552 @@
1
+ #!/usr/bin/env bash
2
+ # Session utility functions -- extracted from aether-utils.sh
3
+ # Provides: _session_verify_fresh, _session_clear, _session_init, _session_update,
4
+ # _session_read, _session_is_stale, _session_clear_context,
5
+ # _session_mark_resumed, _session_summary
6
+ # Also includes: _rotate_spawn_tree (helper used only by _session_init)
7
+
8
+ # ============================================================================
9
+ # _session_verify_fresh
10
+ # Generic session freshness verification
11
+ # Usage: _session_verify_fresh [args...] (same args as before: --command <name> [--force] <session_start_unixtime>)
12
+ # Returns: JSON with pass/fail status and file details
13
+ # ============================================================================
14
+ _session_verify_fresh() {
15
+ # Parse arguments
16
+ local command_name=""
17
+ local force_mode=""
18
+ local session_start_time=""
19
+
20
+ while [[ $# -gt 0 ]]; do
21
+ case "$1" in
22
+ --command) command_name="$2"; shift 2 ;;
23
+ --force) force_mode="--force"; shift ;;
24
+ *) session_start_time="$1"; shift ;;
25
+ esac
26
+ done
27
+
28
+ # Validate command name
29
+ [[ -z "$command_name" ]] && json_err "$E_VALIDATION_FAILED" "Usage: session-verify-fresh --command <name> [--force] <session_start>"
30
+
31
+ # Map command to directory and files (using env var override pattern)
32
+ local session_dir required_docs
33
+ case "$command_name" in
34
+ survey)
35
+ session_dir="${SURVEY_DIR:-.aether/data/survey}"
36
+ required_docs="PROVISIONS.md TRAILS.md BLUEPRINT.md CHAMBERS.md DISCIPLINES.md SENTINEL-PROTOCOLS.md PATHOGENS.md"
37
+ ;;
38
+ oracle)
39
+ session_dir="${ORACLE_DIR:-.aether/oracle}"
40
+ required_docs="state.json plan.json gaps.md synthesis.md research-plan.md"
41
+ ;;
42
+ watch)
43
+ session_dir="${WATCH_DIR:-.aether/data}"
44
+ required_docs="watch-status.txt watch-progress.txt"
45
+ ;;
46
+ swarm)
47
+ session_dir="${SWARM_DIR:-.aether/data/swarm}"
48
+ required_docs="findings.json"
49
+ ;;
50
+ init)
51
+ session_dir="${INIT_DIR:-.aether/data}"
52
+ required_docs="COLONY_STATE.json constraints.json"
53
+ ;;
54
+ seal|entomb)
55
+ session_dir="${ARCHIVE_DIR:-.aether/data/archive}"
56
+ required_docs="manifest.json"
57
+ ;;
58
+ *)
59
+ json_err "$E_VALIDATION_FAILED" "Unknown command: $command_name" '{"commands":["survey","oracle","watch","swarm","init","seal","entomb"]}'
60
+ ;;
61
+ esac
62
+
63
+ # Initialize result arrays
64
+ local fresh_docs=""
65
+ local stale_docs=""
66
+ local missing_docs=""
67
+ local total_lines=0
68
+
69
+ for doc in $required_docs; do
70
+ local doc_path="$session_dir/$doc"
71
+
72
+ if [[ ! -f "$doc_path" ]]; then
73
+ missing_docs="${missing_docs:+$missing_docs }$doc"
74
+ continue
75
+ fi
76
+
77
+ # Get line count
78
+ local lines
79
+ lines=$(wc -l < "$doc_path" 2>/dev/null | tr -d ' ' || echo "0") # SUPPRESS:OK -- read-default: file may not exist
80
+ total_lines=$((total_lines + lines))
81
+
82
+ # In force mode, accept any existing file
83
+ if [[ "$force_mode" == "--force" ]]; then
84
+ fresh_docs="${fresh_docs:+$fresh_docs }$doc"
85
+ continue
86
+ fi
87
+
88
+ # Check timestamp if session_start_time provided
89
+ if [[ -n "$session_start_time" ]]; then
90
+ # Cross-platform stat: macOS uses -f %m, Linux uses -c %Y
91
+ local file_mtime
92
+ file_mtime=$(stat -f %m "$doc_path" 2>/dev/null || stat -c %Y "$doc_path" 2>/dev/null || echo "0") # SUPPRESS:OK -- cross-platform: macOS stat syntax
93
+
94
+ if [[ "$file_mtime" -ge "$session_start_time" ]]; then
95
+ fresh_docs="${fresh_docs:+$fresh_docs }$doc"
96
+ else
97
+ stale_docs="${stale_docs:+$stale_docs }$doc"
98
+ fi
99
+ else
100
+ # No start time provided - accept existing file (backward compatible)
101
+ fresh_docs="${fresh_docs:+$fresh_docs }$doc"
102
+ fi
103
+ done
104
+
105
+ # Determine pass/fail
106
+ # pass = true if: no stale files (fresh files can coexist with missing files)
107
+ # missing files are ok - they will be created during the session
108
+ local pass=false
109
+ if [[ "$force_mode" == "--force" ]] || [[ -z "$stale_docs" ]]; then
110
+ pass=true
111
+ fi
112
+
113
+ # Build JSON response
114
+ local fresh_json=""
115
+ for item in $fresh_docs; do fresh_json="$fresh_json\"$item\","; done
116
+ fresh_json="[${fresh_json%,}]"
117
+
118
+ local stale_json=""
119
+ for item in $stale_docs; do stale_json="$stale_json\"$item\","; done
120
+ stale_json="[${stale_json%,}]"
121
+
122
+ local missing_json=""
123
+ for item in $missing_docs; do missing_json="$missing_json\"$item\","; done
124
+ missing_json="[${missing_json%,}]"
125
+
126
+ echo "$(jq -n --argjson ok "$pass" --arg command "$command_name" \
127
+ --argjson fresh "$fresh_json" --argjson stale "$stale_json" \
128
+ --argjson missing "$missing_json" --argjson total_lines "$total_lines" \
129
+ '{ok: $ok, command: $command, fresh: $fresh, stale: $stale, missing: $missing, total_lines: $total_lines}')"
130
+ exit 0
131
+ }
132
+
133
+ # ============================================================================
134
+ # _session_clear
135
+ # Generic session file clearing
136
+ # Usage: _session_clear [args...] (same args as before: --command <name> [--dry-run])
137
+ # ============================================================================
138
+ _session_clear() {
139
+ # Parse arguments
140
+ local command_name=""
141
+ local dry_run=""
142
+
143
+ while [[ $# -gt 0 ]]; do
144
+ case "$1" in
145
+ --command) command_name="$2"; shift 2 ;;
146
+ --dry-run) dry_run="--dry-run"; shift ;;
147
+ *) shift ;;
148
+ esac
149
+ done
150
+
151
+ [[ -z "$command_name" ]] && json_err "$E_VALIDATION_FAILED" "Usage: session-clear --command <name> [--dry-run]"
152
+
153
+ # Map command to directory and files
154
+ local session_dir="" files="" subdir_files=""
155
+ case "$command_name" in
156
+ survey)
157
+ session_dir="${SURVEY_DIR:-.aether/data/survey}"
158
+ files="PROVISIONS.md TRAILS.md BLUEPRINT.md CHAMBERS.md DISCIPLINES.md SENTINEL-PROTOCOLS.md PATHOGENS.md"
159
+ ;;
160
+ oracle)
161
+ session_dir="${ORACLE_DIR:-.aether/oracle}"
162
+ files="state.json plan.json gaps.md synthesis.md research-plan.md .stop .last-topic"
163
+ # Also clear discoveries subdirectory
164
+ subdir_files="discoveries/*"
165
+ ;;
166
+ watch)
167
+ session_dir="${WATCH_DIR:-.aether/data}"
168
+ files="watch-status.txt watch-progress.txt"
169
+ ;;
170
+ swarm)
171
+ session_dir="${SWARM_DIR:-.aether/data/swarm}"
172
+ files="findings.json display.json timing.json"
173
+ ;;
174
+ init)
175
+ # Init clear is destructive - blocked for auto-clear
176
+ json_err "$E_VALIDATION_FAILED" "Command 'init' is protected and cannot be auto-cleared. Use manual removal of COLONY_STATE.json if absolutely necessary."
177
+ ;;
178
+ seal|entomb)
179
+ # Archive operations should never be auto-cleared
180
+ json_err "$E_VALIDATION_FAILED" "Command '$command_name' is protected and cannot be auto-cleared. Archives and chambers must be managed manually."
181
+ ;;
182
+ *)
183
+ json_err "$E_VALIDATION_FAILED" "Unknown command: $command_name"
184
+ ;;
185
+ esac
186
+
187
+ local cleared=""
188
+ local errors=""
189
+
190
+ if [[ -d "$session_dir" && -n "$files" ]]; then
191
+ for doc in $files; do
192
+ local doc_path="$session_dir/$doc"
193
+ if [[ -f "$doc_path" ]]; then
194
+ if [[ "$dry_run" == "--dry-run" ]]; then
195
+ cleared="$cleared $doc"
196
+ else
197
+ if rm -f "$doc_path" 2>/dev/null; then # SUPPRESS:OK -- cleanup: file may not exist
198
+ cleared="$cleared $doc"
199
+ else
200
+ errors="$errors $doc"
201
+ fi
202
+ fi
203
+ fi
204
+ done
205
+
206
+ # Handle oracle discoveries subdirectory
207
+ if [[ "$command_name" == "oracle" && -d "$session_dir/discoveries" ]]; then
208
+ if [[ "$dry_run" == "--dry-run" ]]; then
209
+ cleared="$cleared discoveries/"
210
+ else
211
+ # SUPPRESS:OK -- cleanup: file may not exist
212
+ rm -rf "$session_dir/discoveries" 2>/dev/null && cleared="$cleared discoveries/" || errors="$errors discoveries/"
213
+ fi
214
+ fi
215
+ fi
216
+
217
+ local dry_run_bool=$([[ "$dry_run" == "--dry-run" ]] && echo "true" || echo "false")
218
+ json_ok "$(jq -n --arg command "$command_name" --arg cleared "${cleared// /}" \
219
+ --arg errors "${errors// /}" --argjson dry_run "$dry_run_bool" \
220
+ '{command: $command, cleared: $cleared, errors: $errors, dry_run: $dry_run}')"
221
+ }
222
+
223
+ # ============================================================================
224
+ # _rotate_spawn_tree (helper -- used only by _session_init)
225
+ # ARCH-03: Rotate spawn-tree.txt at session start to prevent unbounded growth.
226
+ # Archives previous session's tree to a timestamped file; caps archive count at 5.
227
+ # ============================================================================
228
+ _rotate_spawn_tree() {
229
+ local tree_file="$COLONY_DATA_DIR/spawn-tree.txt"
230
+ [[ -f "$tree_file" ]] && [[ -s "$tree_file" ]] || return 0
231
+ mkdir -p "$COLONY_DATA_DIR/spawn-tree-archive"
232
+ local archive_ts
233
+ archive_ts=$(date +%Y%m%d_%H%M%S)
234
+ if ! cp "$tree_file" "$COLONY_DATA_DIR/spawn-tree-archive/spawn-tree.${archive_ts}.txt" 2>/dev/null; then # SUPPRESS:OK -- cleanup: backup copy is best-effort
235
+ _aether_log_error "Could not archive spawn-tree before rotation"
236
+ fi
237
+ > "$tree_file" # Truncate in-place — preserves file handle for tail -f watchers
238
+ # Keep only 5 archives
239
+ # SUPPRESS:OK -- read-default: directory may not exist
240
+ # SUPPRESS:OK -- cleanup: rotation cleanup is best-effort
241
+ ls -t "$COLONY_DATA_DIR/spawn-tree-archive"/spawn-tree.*.txt 2>/dev/null \
242
+ | tail -n +6 | while IFS= read -r file; do rm -f "$file"; done 2>/dev/null || true # SUPPRESS:OK -- cleanup: file may not exist
243
+ }
244
+
245
+ # ============================================================================
246
+ # _session_init
247
+ # Initialize a new session tracking file
248
+ # Usage: _session_init [session_id] [goal]
249
+ # ============================================================================
250
+ _session_init() {
251
+ local session_id="${1:-$(date +%s)_$(openssl rand -hex 4 2>/dev/null || echo $$)}" # SUPPRESS:OK -- read-default: openssl may not be available
252
+ local goal="${2:-}"
253
+
254
+ _rotate_spawn_tree
255
+
256
+ local session_file="$COLONY_DATA_DIR/session.json"
257
+ local baseline
258
+ baseline=$(git rev-parse HEAD 2>/dev/null || echo "") # SUPPRESS:OK -- read-default: may not have commits yet
259
+
260
+ jq -n --arg sid "$session_id" --arg started "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
261
+ --arg goal "$goal" --arg baseline "$baseline" \
262
+ '{
263
+ session_id: $sid,
264
+ started_at: $started,
265
+ last_command: null,
266
+ last_command_at: null,
267
+ colony_goal: $goal,
268
+ current_phase: 0,
269
+ current_milestone: "First Mound",
270
+ suggested_next: "/ant:plan",
271
+ context_cleared: false,
272
+ baseline_commit: $baseline,
273
+ resumed_at: null,
274
+ active_todos: [],
275
+ summary: "Session initialized"
276
+ }' > "$session_file.tmp"
277
+ mv "$session_file.tmp" "$session_file"
278
+ json_ok "$(jq -n --arg sid "$session_id" --arg goal "$goal" --arg file "$session_file" \
279
+ '{session_id: $sid, goal: $goal, file: $file}')"
280
+ }
281
+
282
+ # ============================================================================
283
+ # _session_update
284
+ # Update session with latest activity
285
+ # Usage: _session_update <command> [suggested_next] [summary]
286
+ # ============================================================================
287
+ _session_update() {
288
+ local cmd_run="${1:-}"
289
+ local suggested="${2:-}"
290
+ local summary="${3:-}"
291
+
292
+ local session_file="$COLONY_DATA_DIR/session.json"
293
+
294
+ if [[ ! -f "$session_file" ]]; then
295
+ # Auto-initialize if doesn't exist
296
+ bash "$SCRIPT_DIR/aether-utils.sh" session-init "auto_$(date +%s)" ""
297
+ fi
298
+
299
+ # Read current session
300
+ local current_session
301
+ current_session=$(cat "$session_file" 2>/dev/null || echo '{}') # SUPPRESS:OK -- read-default: file may not exist yet
302
+
303
+ # Extract current values for preservation
304
+ local current_goal current_phase current_milestone
305
+ current_goal=$(sanitize_read_value "$(echo "$current_session" | jq -r '.colony_goal // empty')")
306
+ current_phase=$(echo "$current_session" | jq -r '.current_phase // 0')
307
+ current_milestone=$(echo "$current_session" | jq -r '.current_milestone // "First Mound"')
308
+
309
+ # Get top 3 TODOs if TO-DOs.md exists
310
+ local todos="[]"
311
+ if [[ -f "TO-DOs.md" ]]; then
312
+ todos=$(grep "^### " TO-DOs.md 2>/dev/null | head -3 | sed 's/^### //' | jq -R . | jq -s .) # SUPPRESS:OK -- existence-test: file may not exist
313
+ fi
314
+
315
+ # MIGRATE: direct COLONY_STATE.json access -- use _state_read_field instead
316
+ # Get colony state if exists
317
+ if [[ -f "$DATA_DIR/COLONY_STATE.json" ]]; then
318
+ # SUPPRESS:OK -- read-default: query may return empty
319
+ current_goal=$(sanitize_read_value "$(jq -r '.goal // empty' "$DATA_DIR/COLONY_STATE.json" 2>/dev/null || echo "$current_goal")")
320
+ # SUPPRESS:OK -- read-default: query may return empty
321
+ current_phase=$(jq -r '.current_phase // 0' "$DATA_DIR/COLONY_STATE.json" 2>/dev/null || echo "$current_phase")
322
+ # SUPPRESS:OK -- read-default: query may return empty
323
+ current_milestone=$(jq -r '.milestone // "First Mound"' "$DATA_DIR/COLONY_STATE.json" 2>/dev/null || echo "$current_milestone")
324
+ fi
325
+
326
+ # Capture current git HEAD for drift detection
327
+ local baseline
328
+ baseline=$(git rev-parse HEAD 2>/dev/null || echo "") # SUPPRESS:OK -- read-default: may not have commits yet
329
+
330
+ # Build updated session
331
+ echo "$current_session" | jq --arg cmd "$cmd_run" \
332
+ --arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
333
+ --arg suggested "$suggested" \
334
+ --arg summary "$summary" \
335
+ --arg goal "$current_goal" \
336
+ --argjson phase "$current_phase" \
337
+ --arg milestone "$current_milestone" \
338
+ --argjson todos "$todos" \
339
+ --arg baseline "$baseline" \
340
+ '.last_command = $cmd |
341
+ .last_command_at = $ts |
342
+ .suggested_next = $suggested |
343
+ .summary = $summary |
344
+ .colony_goal = $goal |
345
+ .current_phase = $phase |
346
+ .current_milestone = $milestone |
347
+ .active_todos = $todos |
348
+ .baseline_commit = $baseline' > "$session_file.tmp" || {
349
+ _aether_log_error "Could not process session update"
350
+ rm -f "$session_file.tmp"
351
+ json_err "$E_UNKNOWN" "Failed to update session file"
352
+ }
353
+ [[ -s "$session_file.tmp" ]] || {
354
+ _aether_log_error "Session update produced empty result -- not overwriting"
355
+ rm -f "$session_file.tmp"
356
+ json_err "$E_JSON_INVALID" "Session update produced empty result"
357
+ }
358
+ mv "$session_file.tmp" "$session_file" || {
359
+ _aether_log_error "Could not finalize session file update"
360
+ rm -f "$session_file.tmp"
361
+ json_err "$E_UNKNOWN" "Failed to rename temporary session file"
362
+ }
363
+
364
+ json_ok "$(jq -n --arg cmd "$cmd_run" '{updated: true, command: $cmd}')"
365
+ }
366
+
367
+ # ============================================================================
368
+ # _session_read
369
+ # Read and return current session state
370
+ # ============================================================================
371
+ _session_read() {
372
+ local session_file="$COLONY_DATA_DIR/session.json"
373
+
374
+ if [[ ! -f "$session_file" ]]; then
375
+ json_ok "{\"exists\":false,\"session\":null}"
376
+ exit 0
377
+ fi
378
+
379
+ local session_data
380
+ session_data=$(cat "$session_file" 2>/dev/null || echo '{}') # SUPPRESS:OK -- read-default: file may not exist yet
381
+
382
+ # Check if stale (> 24 hours)
383
+ local last_cmd_ts="" is_stale="" age_hours=""
384
+ last_cmd_ts=$(echo "$session_data" | jq -r '.last_command_at // .started_at // empty')
385
+ if [[ -n "$last_cmd_ts" ]]; then
386
+ local last_epoch=0 now_epoch=0
387
+ # SUPPRESS:OK -- cross-platform: macOS date syntax
388
+ # SUPPRESS:OK -- cross-platform: macOS vs Linux date/stat flags
389
+ last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_cmd_ts" +%s 2>/dev/null \
390
+ || date -d "$last_cmd_ts" +%s 2>/dev/null \
391
+ || echo 0)
392
+ now_epoch=$(date +%s)
393
+ age_hours=$(( (now_epoch - last_epoch) / 3600 ))
394
+ [[ $age_hours -gt 24 ]] && is_stale=true || is_stale=false
395
+ else
396
+ is_stale="false"
397
+ age_hours="unknown"
398
+ fi
399
+
400
+ json_ok "$(jq -n --argjson is_stale "$is_stale" --argjson age "$age_hours" \
401
+ --argjson session "$session_data" \
402
+ '{exists: true, is_stale: $is_stale, age_hours: $age, session: $session}')"
403
+ }
404
+
405
+ # ============================================================================
406
+ # _session_is_stale
407
+ # Check if session is stale (returns JSON with is_stale boolean)
408
+ # ============================================================================
409
+ _session_is_stale() {
410
+ _deprecation_warning "session-is-stale"
411
+ local session_file="$COLONY_DATA_DIR/session.json"
412
+
413
+ if [[ ! -f "$session_file" ]]; then
414
+ json_ok '{"is_stale":true}'
415
+ exit 0
416
+ fi
417
+
418
+ local last_cmd_ts
419
+ last_cmd_ts=$(jq -r '.last_command_at // .started_at // empty' "$session_file" 2>/dev/null) # SUPPRESS:OK -- read-default: file may not exist yet
420
+
421
+ if [[ -z "$last_cmd_ts" ]]; then
422
+ json_ok '{"is_stale":true}'
423
+ exit 0
424
+ fi
425
+
426
+ # macOS uses -j -f, Linux uses -d
427
+ # SUPPRESS:OK -- cross-platform: macOS date syntax
428
+ # SUPPRESS:OK -- cross-platform: macOS vs Linux date/stat flags
429
+ local last_epoch now_epoch age_hours
430
+ last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_cmd_ts" +%s 2>/dev/null \
431
+ || date -d "$last_cmd_ts" +%s 2>/dev/null \
432
+ || echo 0)
433
+ now_epoch=$(date +%s)
434
+ age_hours=$(( (now_epoch - last_epoch) / 3600 ))
435
+
436
+ if [[ $age_hours -gt 24 ]]; then
437
+ json_ok '{"is_stale":true}'
438
+ else
439
+ json_ok '{"is_stale":false}'
440
+ fi
441
+ }
442
+
443
+ # ============================================================================
444
+ # _session_clear_context
445
+ # Mark session context as cleared (preserves file but marks context_cleared)
446
+ # ============================================================================
447
+ _session_clear_context() {
448
+ _deprecation_warning "session-clear-context"
449
+ local preserve="${1:-false}"
450
+ local session_file="$COLONY_DATA_DIR/session.json"
451
+
452
+ if [[ -f "$session_file" ]]; then
453
+ if [[ "$preserve" == "true" ]]; then
454
+ # Just mark as cleared
455
+ jq '.context_cleared = true' "$session_file" > "$session_file.tmp" || {
456
+ _aether_log_error "Could not mark session as cleared"
457
+ rm -f "$session_file.tmp"
458
+ }
459
+ if [[ -s "$session_file.tmp" ]]; then
460
+ mv "$session_file.tmp" "$session_file" || _aether_log_error "Could not finalize session clear"
461
+ fi
462
+ json_ok "{\"cleared\":true,\"preserved\":true}"
463
+ else
464
+ # Remove file entirely
465
+ rm -f "$session_file"
466
+ json_ok "{\"cleared\":true,\"preserved\":false}"
467
+ fi
468
+ else
469
+ json_ok "{\"cleared\":false,\"reason\":\"no_session_exists\"}"
470
+ fi
471
+ }
472
+
473
+ # ============================================================================
474
+ # _session_mark_resumed
475
+ # Mark session as resumed
476
+ # ============================================================================
477
+ _session_mark_resumed() {
478
+ local session_file="$COLONY_DATA_DIR/session.json"
479
+
480
+ if [[ -f "$session_file" ]]; then
481
+ jq --arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
482
+ '.resumed_at = $ts | .context_cleared = false' "$session_file" > "$session_file.tmp" || {
483
+ _aether_log_error "Could not process session resume update"
484
+ rm -f "$session_file.tmp"
485
+ }
486
+ if [[ -s "$session_file.tmp" ]]; then
487
+ mv "$session_file.tmp" "$session_file" || _aether_log_error "Could not finalize session resume"
488
+ fi
489
+ json_ok "$(jq -n --arg ts "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" '{resumed: true, timestamp: $ts}')"
490
+ else
491
+ json_err "$E_RESOURCE_NOT_FOUND" "No active session to mark as resumed. Try: run /ant:init to start a new session."
492
+ fi
493
+ }
494
+
495
+ # ============================================================================
496
+ # _session_summary
497
+ # Get session summary (human-readable or JSON)
498
+ # ============================================================================
499
+ _session_summary() {
500
+ _deprecation_warning "session-summary"
501
+ local session_file="$COLONY_DATA_DIR/session.json"
502
+ local json_mode="false"
503
+
504
+ # Parse --json flag (command name already shifted by main dispatch)
505
+ while [[ $# -gt 0 ]]; do
506
+ case "$1" in
507
+ --json)
508
+ json_mode="true"
509
+ shift
510
+ ;;
511
+ *)
512
+ shift
513
+ ;;
514
+ esac
515
+ done
516
+
517
+ if [[ ! -f "$session_file" ]]; then
518
+ if [[ "$json_mode" == "true" ]]; then
519
+ json_ok '{"exists":false,"goal":null,"phase":0}'
520
+ else
521
+ echo "No active session found."
522
+ fi
523
+ exit 0
524
+ fi
525
+
526
+ local goal phase milestone last_cmd last_at suggested cleared
527
+ goal=$(sanitize_read_value "$(jq -r '.colony_goal // "No goal set"' "$session_file")")
528
+ phase=$(jq -r '.current_phase // 0' "$session_file")
529
+ milestone=$(jq -r '.current_milestone // "First Mound"' "$session_file")
530
+ last_cmd=$(jq -r '.last_command // "None"' "$session_file")
531
+ last_at=$(jq -r '.last_command_at // "Unknown"' "$session_file")
532
+ suggested=$(jq -r '.suggested_next // "None"' "$session_file")
533
+ cleared=$(jq -r '.context_cleared // false' "$session_file")
534
+
535
+ if [[ "$json_mode" == "true" ]]; then
536
+ json_ok "$(jq -n --arg goal "$goal" --argjson phase "$phase" \
537
+ --arg milestone "$milestone" --arg last_cmd "$last_cmd" \
538
+ --arg last_at "$last_at" --arg suggested "$suggested" \
539
+ --argjson cleared "$cleared" \
540
+ '{exists: true, goal: $goal, phase: $phase, milestone: $milestone, last_command: $last_cmd, last_active: $last_at, suggested_next: $suggested, context_cleared: $cleared}')"
541
+ else
542
+ echo "Session Summary"
543
+ echo "=================="
544
+ echo "Goal: $goal"
545
+ [[ "$phase" != "0" ]] && echo "Phase: $phase"
546
+ echo "Milestone: $milestone"
547
+ echo "Last Command: $last_cmd"
548
+ echo "Last Active: $last_at"
549
+ [[ "$suggested" != "None" ]] && echo "Suggested Next: $suggested"
550
+ [[ "$cleared" == "true" ]] && echo "Status: Context was cleared"
551
+ fi
552
+ }