aether-colony 3.1.17 → 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.
- package/.aether/aether-utils.sh +5354 -0
- package/.aether/agents-claude/aether-ambassador.md +265 -0
- package/.aether/agents-claude/aether-archaeologist.md +327 -0
- package/.aether/agents-claude/aether-architect.md +236 -0
- package/.aether/agents-claude/aether-auditor.md +271 -0
- package/.aether/agents-claude/aether-builder.md +224 -0
- package/.aether/agents-claude/aether-chaos.md +269 -0
- package/.aether/agents-claude/aether-chronicler.md +305 -0
- package/.aether/agents-claude/aether-gatekeeper.md +330 -0
- package/.aether/agents-claude/aether-includer.md +374 -0
- package/.aether/agents-claude/aether-keeper.md +272 -0
- package/.aether/agents-claude/aether-measurer.md +322 -0
- package/.aether/agents-claude/aether-oracle.md +237 -0
- package/.aether/agents-claude/aether-probe.md +211 -0
- package/.aether/agents-claude/aether-queen.md +330 -0
- package/.aether/agents-claude/aether-route-setter.md +178 -0
- package/.aether/agents-claude/aether-sage.md +418 -0
- package/.aether/agents-claude/aether-scout.md +179 -0
- package/.aether/agents-claude/aether-surveyor-disciplines.md +417 -0
- package/.aether/agents-claude/aether-surveyor-nest.md +355 -0
- package/.aether/agents-claude/aether-surveyor-pathogens.md +289 -0
- package/.aether/agents-claude/aether-surveyor-provisions.md +360 -0
- package/.aether/agents-claude/aether-tracker.md +270 -0
- package/.aether/agents-claude/aether-watcher.md +280 -0
- package/.aether/agents-claude/aether-weaver.md +248 -0
- package/.aether/commands/archaeology.yaml +653 -0
- package/.aether/commands/build.yaml +1221 -0
- package/.aether/commands/chaos.yaml +653 -0
- package/.aether/commands/colonize.yaml +438 -0
- package/.aether/commands/continue.yaml +1484 -0
- package/.aether/commands/council.yaml +304 -0
- package/.aether/commands/data-clean.yaml +80 -0
- package/.aether/commands/dream.yaml +275 -0
- package/.aether/commands/entomb.yaml +863 -0
- package/.aether/commands/export-signals.yaml +64 -0
- package/.aether/commands/feedback.yaml +158 -0
- package/.aether/commands/flag.yaml +160 -0
- package/.aether/commands/flags.yaml +177 -0
- package/.aether/commands/focus.yaml +112 -0
- package/.aether/commands/help.yaml +167 -0
- package/.aether/commands/history.yaml +137 -0
- package/.aether/commands/import-signals.yaml +79 -0
- package/.aether/commands/init.yaml +469 -0
- package/.aether/commands/insert-phase.yaml +98 -0
- package/.aether/commands/interpret.yaml +285 -0
- package/.aether/commands/lay-eggs.yaml +224 -0
- package/.aether/commands/maturity.yaml +122 -0
- package/.aether/commands/memory-details.yaml +74 -0
- package/.aether/commands/migrate-state.yaml +174 -0
- package/.aether/commands/oracle.yaml +1224 -0
- package/.aether/commands/organize.yaml +446 -0
- package/.aether/commands/patrol.yaml +621 -0
- package/.aether/commands/pause-colony.yaml +424 -0
- package/.aether/commands/phase.yaml +124 -0
- package/.aether/commands/pheromones.yaml +153 -0
- package/.aether/commands/plan.yaml +1313 -0
- package/.aether/commands/preferences.yaml +63 -0
- package/.aether/commands/redirect.yaml +123 -0
- package/.aether/commands/resume-colony.yaml +373 -0
- package/.aether/commands/resume.yaml +398 -0
- package/.aether/commands/run.yaml +193 -0
- package/.aether/commands/seal.yaml +1205 -0
- package/.aether/commands/skill-create.yaml +337 -0
- package/.aether/commands/status.yaml +364 -0
- package/.aether/commands/swarm.yaml +352 -0
- package/.aether/commands/tunnels.yaml +814 -0
- package/.aether/commands/update.yaml +131 -0
- package/.aether/commands/verify-castes.yaml +159 -0
- package/.aether/commands/watch.yaml +454 -0
- package/.aether/docs/INCIDENT_TEMPLATE.md +32 -0
- package/.aether/docs/QUEEN-SYSTEM.md +211 -0
- package/.aether/docs/README.md +98 -0
- package/.aether/docs/caste-system.md +48 -0
- package/.aether/docs/command-playbooks/README.md +23 -0
- package/.aether/docs/command-playbooks/build-complete.md +349 -0
- package/.aether/docs/command-playbooks/build-context.md +282 -0
- package/.aether/docs/command-playbooks/build-full.md +1682 -0
- package/.aether/docs/command-playbooks/build-prep.md +283 -0
- package/.aether/docs/command-playbooks/build-verify.md +405 -0
- package/.aether/docs/command-playbooks/build-wave.md +749 -0
- package/.aether/docs/command-playbooks/continue-advance.md +524 -0
- package/.aether/docs/command-playbooks/continue-finalize.md +447 -0
- package/.aether/docs/command-playbooks/continue-full.md +1724 -0
- package/.aether/docs/command-playbooks/continue-gates.md +686 -0
- package/.aether/docs/command-playbooks/continue-verify.md +406 -0
- package/.aether/docs/context-continuity.md +84 -0
- package/{runtime → .aether/docs/disciplines}/DISCIPLINES.md +13 -11
- package/.aether/docs/error-codes.md +268 -0
- package/.aether/docs/known-issues.md +94 -0
- package/{runtime → .aether}/docs/pheromones.md +86 -6
- package/.aether/docs/plans/pheromone-display-plan.md +257 -0
- package/.aether/docs/queen-commands.md +98 -0
- package/.aether/docs/source-of-truth-map.md +132 -0
- package/.aether/docs/xml-utilities.md +47 -0
- package/{runtime → .aether}/exchange/pheromone-xml.sh +2 -1
- package/{runtime → .aether}/exchange/registry-xml.sh +7 -3
- package/{runtime → .aether}/exchange/wisdom-xml.sh +11 -4
- package/.aether/rules/aether-colony.md +144 -0
- package/.aether/schemas/example-prompt-builder.xml +234 -0
- package/.aether/scripts/incident-test-add.sh +47 -0
- package/.aether/scripts/weekly-audit.sh +79 -0
- package/.aether/skills/.index.json +649 -0
- package/.aether/skills/colony/.manifest.json +16 -0
- package/.aether/skills/colony/build-discipline/SKILL.md +78 -0
- package/.aether/skills/colony/colony-interaction/SKILL.md +56 -0
- package/.aether/skills/colony/colony-lifecycle/SKILL.md +77 -0
- package/.aether/skills/colony/colony-visuals/SKILL.md +112 -0
- package/.aether/skills/colony/context-management/SKILL.md +80 -0
- package/.aether/skills/colony/error-presentation/SKILL.md +99 -0
- package/.aether/skills/colony/pheromone-protocol/SKILL.md +79 -0
- package/.aether/skills/colony/pheromone-visibility/SKILL.md +81 -0
- package/.aether/skills/colony/state-safety/SKILL.md +84 -0
- package/.aether/skills/colony/worker-priming/SKILL.md +82 -0
- package/.aether/skills/domain/.manifest.json +24 -0
- package/.aether/skills/domain/README.md +33 -0
- package/.aether/skills/domain/django/SKILL.md +49 -0
- package/.aether/skills/domain/docker/SKILL.md +52 -0
- package/.aether/skills/domain/golang/SKILL.md +52 -0
- package/.aether/skills/domain/graphql/SKILL.md +51 -0
- package/.aether/skills/domain/html-css/SKILL.md +48 -0
- package/.aether/skills/domain/nextjs/SKILL.md +45 -0
- package/.aether/skills/domain/nodejs/SKILL.md +53 -0
- package/.aether/skills/domain/postgresql/SKILL.md +53 -0
- package/.aether/skills/domain/prisma/SKILL.md +59 -0
- package/.aether/skills/domain/python/SKILL.md +50 -0
- package/.aether/skills/domain/rails/SKILL.md +52 -0
- package/.aether/skills/domain/react/SKILL.md +45 -0
- package/.aether/skills/domain/rest-api/SKILL.md +58 -0
- package/.aether/skills/domain/svelte/SKILL.md +47 -0
- package/.aether/skills/domain/tailwind/SKILL.md +45 -0
- package/.aether/skills/domain/testing/SKILL.md +53 -0
- package/.aether/skills/domain/typescript/SKILL.md +58 -0
- package/.aether/skills/domain/vue/SKILL.md +49 -0
- package/.aether/templates/QUEEN.md.template +61 -0
- package/.aether/templates/colony-state-reset.jq.template +23 -0
- package/.aether/templates/colony-state.template.json +39 -0
- package/.aether/templates/constraints.template.json +9 -0
- package/.aether/templates/crowned-anthill.template.md +36 -0
- package/.aether/templates/handoff-build-error.template.md +30 -0
- package/.aether/templates/handoff-build-success.template.md +39 -0
- package/.aether/templates/handoff.template.md +40 -0
- package/.aether/templates/learning-observations.template.json +6 -0
- package/.aether/templates/midden.template.json +13 -0
- package/.aether/templates/pheromones.template.json +6 -0
- package/.aether/templates/session.template.json +9 -0
- package/{runtime → .aether}/utils/atomic-write.sh +68 -22
- package/{runtime → .aether}/utils/chamber-compare.sh +23 -10
- package/.aether/utils/chamber-utils.sh +440 -0
- package/.aether/utils/emoji-audit.sh +166 -0
- package/{runtime → .aether}/utils/error-handler.sh +34 -8
- package/.aether/utils/file-lock.sh +313 -0
- package/.aether/utils/flag.sh +267 -0
- package/.aether/utils/hive.sh +572 -0
- package/.aether/utils/learning.sh +1928 -0
- package/.aether/utils/midden.sh +342 -0
- package/.aether/utils/oracle/oracle.md +168 -0
- package/.aether/utils/oracle/oracle.sh +1023 -0
- package/.aether/utils/pheromone.sh +2029 -0
- package/.aether/utils/queen.sh +1698 -0
- package/.aether/utils/scan.sh +860 -0
- package/.aether/utils/semantic-cli.sh +415 -0
- package/.aether/utils/session.sh +552 -0
- package/.aether/utils/skills.sh +509 -0
- package/.aether/utils/spawn-tree.sh +260 -0
- package/.aether/utils/spawn.sh +260 -0
- package/.aether/utils/state-api.sh +199 -0
- package/{runtime → .aether}/utils/state-loader.sh +8 -6
- package/.aether/utils/suggest.sh +611 -0
- package/{runtime → .aether}/utils/swarm-display.sh +10 -1
- package/.aether/utils/swarm.sh +1004 -0
- package/{runtime → .aether}/utils/watch-spawn-tree.sh +11 -2
- package/{runtime → .aether}/utils/xml-compose.sh +9 -3
- package/.aether/utils/xml-convert.sh +277 -0
- package/{runtime → .aether}/utils/xml-core.sh +5 -9
- package/.aether/utils/xml-query.sh +201 -0
- package/.aether/utils/xml-utils.sh +110 -0
- package/{runtime → .aether}/workers.md +97 -81
- package/.claude/agents/ant/aether-ambassador.md +265 -0
- package/.claude/agents/ant/aether-archaeologist.md +327 -0
- package/.claude/agents/ant/aether-architect.md +236 -0
- package/.claude/agents/ant/aether-auditor.md +271 -0
- package/.claude/agents/ant/aether-builder.md +224 -0
- package/.claude/agents/ant/aether-chaos.md +269 -0
- package/.claude/agents/ant/aether-chronicler.md +305 -0
- package/.claude/agents/ant/aether-gatekeeper.md +330 -0
- package/.claude/agents/ant/aether-includer.md +374 -0
- package/.claude/agents/ant/aether-keeper.md +272 -0
- package/.claude/agents/ant/aether-measurer.md +322 -0
- package/.claude/agents/ant/aether-oracle.md +237 -0
- package/.claude/agents/ant/aether-probe.md +211 -0
- package/.claude/agents/ant/aether-queen.md +330 -0
- package/.claude/agents/ant/aether-route-setter.md +178 -0
- package/.claude/agents/ant/aether-sage.md +418 -0
- package/.claude/agents/ant/aether-scout.md +179 -0
- package/.claude/agents/ant/aether-surveyor-disciplines.md +417 -0
- package/.claude/agents/ant/aether-surveyor-nest.md +355 -0
- package/.claude/agents/ant/aether-surveyor-pathogens.md +289 -0
- package/.claude/agents/ant/aether-surveyor-provisions.md +360 -0
- package/.claude/agents/ant/aether-tracker.md +270 -0
- package/.claude/agents/ant/aether-watcher.md +280 -0
- package/.claude/agents/ant/aether-weaver.md +248 -0
- package/.claude/commands/ant/archaeology.md +16 -14
- package/.claude/commands/ant/build.md +43 -1028
- package/.claude/commands/ant/chaos.md +19 -23
- package/.claude/commands/ant/colonize.md +52 -31
- package/.claude/commands/ant/continue.md +40 -1016
- package/.claude/commands/ant/council.md +21 -18
- package/.claude/commands/ant/data-clean.md +81 -0
- package/.claude/commands/ant/dream.md +27 -15
- package/.claude/commands/ant/entomb.md +317 -225
- package/.claude/commands/ant/export-signals.md +57 -0
- package/.claude/commands/ant/feedback.md +48 -26
- package/.claude/commands/ant/flag.md +30 -10
- package/.claude/commands/ant/flags.md +34 -12
- package/.claude/commands/ant/focus.md +45 -19
- package/.claude/commands/ant/help.md +50 -8
- package/.claude/commands/ant/history.md +13 -0
- package/.claude/commands/ant/import-signals.md +71 -0
- package/.claude/commands/ant/init.md +345 -194
- package/.claude/commands/ant/insert-phase.md +101 -0
- package/.claude/commands/ant/interpret.md +26 -4
- package/.claude/commands/ant/lay-eggs.md +184 -127
- package/.claude/commands/ant/maturity.md +32 -11
- package/.claude/commands/ant/memory-details.md +77 -0
- package/.claude/commands/ant/migrate-state.md +20 -2
- package/.claude/commands/ant/oracle.md +337 -74
- package/.claude/commands/ant/organize.md +39 -25
- package/.claude/commands/ant/patrol.md +620 -0
- package/.claude/commands/ant/pause-colony.md +23 -27
- package/.claude/commands/ant/phase.md +40 -42
- package/.claude/commands/ant/pheromones.md +156 -0
- package/.claude/commands/ant/plan.md +185 -51
- package/.claude/commands/ant/preferences.md +65 -0
- package/.claude/commands/ant/redirect.md +45 -30
- package/.claude/commands/ant/resume-colony.md +51 -27
- package/.claude/commands/ant/resume.md +314 -94
- package/.claude/commands/ant/run.md +195 -0
- package/.claude/commands/ant/seal.md +650 -221
- package/.claude/commands/ant/skill-create.md +286 -0
- package/.claude/commands/ant/status.md +196 -31
- package/.claude/commands/ant/swarm.md +16 -46
- package/.claude/commands/ant/tunnels.md +280 -105
- package/.claude/commands/ant/update.md +73 -89
- package/.claude/commands/ant/verify-castes.md +100 -42
- package/.claude/commands/ant/watch.md +14 -12
- package/.opencode/agents/aether-ambassador.md +63 -20
- package/.opencode/agents/aether-archaeologist.md +29 -12
- package/.opencode/agents/aether-architect.md +103 -36
- package/.opencode/agents/aether-auditor.md +51 -18
- package/.opencode/agents/aether-builder.md +70 -20
- package/.opencode/agents/aether-chaos.md +29 -12
- package/.opencode/agents/aether-chronicler.md +60 -18
- package/.opencode/agents/aether-gatekeeper.md +27 -18
- package/.opencode/agents/aether-includer.md +27 -18
- package/.opencode/agents/aether-keeper.md +89 -18
- package/.opencode/agents/aether-measurer.md +27 -18
- package/.opencode/agents/aether-oracle.md +137 -0
- package/.opencode/agents/aether-probe.md +60 -18
- package/.opencode/agents/aether-queen.md +172 -24
- package/.opencode/agents/aether-route-setter.md +57 -12
- package/.opencode/agents/aether-sage.md +26 -18
- package/.opencode/agents/aether-scout.md +28 -20
- package/.opencode/agents/aether-surveyor-disciplines.md +59 -2
- package/.opencode/agents/aether-surveyor-nest.md +59 -2
- package/.opencode/agents/aether-surveyor-pathogens.md +57 -2
- package/.opencode/agents/aether-surveyor-provisions.md +59 -2
- package/.opencode/agents/aether-tracker.md +64 -18
- package/.opencode/agents/aether-watcher.md +66 -19
- package/.opencode/agents/aether-weaver.md +61 -18
- package/.opencode/commands/ant/archaeology.md +7 -14
- package/.opencode/commands/ant/build.md +437 -257
- package/.opencode/commands/ant/chaos.md +7 -24
- package/.opencode/commands/ant/colonize.md +8 -17
- package/.opencode/commands/ant/continue.md +661 -142
- package/.opencode/commands/ant/council.md +11 -22
- package/.opencode/commands/ant/data-clean.md +77 -0
- package/.opencode/commands/ant/dream.md +15 -17
- package/.opencode/commands/ant/entomb.md +133 -62
- package/.opencode/commands/ant/export-signals.md +54 -0
- package/.opencode/commands/ant/feedback.md +24 -5
- package/.opencode/commands/ant/flag.md +16 -4
- package/.opencode/commands/ant/flags.md +24 -10
- package/.opencode/commands/ant/focus.md +22 -5
- package/.opencode/commands/ant/help.md +41 -8
- package/.opencode/commands/ant/history.md +9 -0
- package/.opencode/commands/ant/import-signals.md +68 -0
- package/.opencode/commands/ant/init.md +374 -167
- package/.opencode/commands/ant/insert-phase.md +107 -0
- package/.opencode/commands/ant/interpret.md +16 -0
- package/.opencode/commands/ant/lay-eggs.md +184 -112
- package/.opencode/commands/ant/maturity.md +18 -2
- package/.opencode/commands/ant/memory-details.md +83 -0
- package/.opencode/commands/ant/migrate-state.md +12 -0
- package/.opencode/commands/ant/oracle.md +322 -67
- package/.opencode/commands/ant/organize.md +18 -16
- package/.opencode/commands/ant/patrol.md +626 -0
- package/.opencode/commands/ant/pause-colony.md +12 -29
- package/.opencode/commands/ant/phase.md +30 -40
- package/.opencode/commands/ant/pheromones.md +162 -0
- package/.opencode/commands/ant/plan.md +184 -56
- package/.opencode/commands/ant/preferences.md +71 -0
- package/.opencode/commands/ant/redirect.md +22 -5
- package/.opencode/commands/ant/resume-colony.md +38 -27
- package/.opencode/commands/ant/resume.md +385 -0
- package/.opencode/commands/ant/run.md +201 -0
- package/.opencode/commands/ant/seal.md +259 -45
- package/.opencode/commands/ant/skill-create.md +63 -0
- package/.opencode/commands/ant/status.md +135 -31
- package/.opencode/commands/ant/swarm.md +3 -345
- package/.opencode/commands/ant/tunnels.md +152 -9
- package/.opencode/commands/ant/update.md +70 -91
- package/.opencode/commands/ant/verify-castes.md +96 -42
- package/.opencode/commands/ant/watch.md +7 -0
- package/CHANGELOG.md +356 -0
- package/README.md +203 -573
- package/bin/cli.js +455 -527
- package/bin/generate-commands.js +186 -0
- package/bin/generate-commands.sh +127 -88
- package/bin/lib/init.js +13 -3
- package/bin/lib/spawn-logger.js +0 -15
- package/bin/lib/update-transaction.js +392 -140
- package/bin/npx-install.js +178 -0
- package/bin/sync-to-runtime.sh +5 -137
- package/bin/validate-package.sh +166 -0
- package/package.json +14 -7
- package/.opencode/agents/aether-guardian.md +0 -107
- package/.opencode/agents/workers.md +0 -1034
- package/bin/lib/model-profiles.js +0 -445
- package/bin/lib/model-verify.js +0 -288
- package/bin/lib/proxy-health.js +0 -253
- package/bin/lib/telemetry.js +0 -441
- package/runtime/CONTEXT.md +0 -160
- package/runtime/QUEEN_ANT_ARCHITECTURE.md +0 -402
- package/runtime/aether-utils.sh +0 -3879
- package/runtime/data/signatures.json +0 -41
- package/runtime/docs/AETHER-2.0-IMPLEMENTATION-PLAN.md +0 -1343
- package/runtime/docs/AETHER-PHEROMONE-SYSTEM-MASTER-SPEC.md +0 -2642
- package/runtime/docs/PHEROMONE-INJECTION.md +0 -240
- package/runtime/docs/PHEROMONE-INTEGRATION.md +0 -192
- package/runtime/docs/PHEROMONE-SYSTEM-DESIGN.md +0 -426
- package/runtime/docs/README.md +0 -94
- package/runtime/docs/VISUAL-OUTPUT-SPEC.md +0 -219
- package/runtime/docs/biological-reference.md +0 -272
- package/runtime/docs/codebase-review.md +0 -399
- package/runtime/docs/command-sync.md +0 -164
- package/runtime/docs/constraints.md +0 -116
- package/runtime/docs/implementation-learnings.md +0 -89
- package/runtime/docs/known-issues.md +0 -217
- package/runtime/docs/namespace.md +0 -148
- package/runtime/docs/pathogen-schema-example.json +0 -36
- package/runtime/docs/pathogen-schema.md +0 -111
- package/runtime/docs/planning-discipline.md +0 -159
- package/runtime/docs/progressive-disclosure.md +0 -184
- package/runtime/lib/queen-utils.sh +0 -729
- package/runtime/model-profiles.yaml +0 -100
- package/runtime/planning.md +0 -159
- package/runtime/recover.sh +0 -136
- package/runtime/templates/QUEEN.md.template +0 -79
- package/runtime/utils/chamber-utils.sh +0 -285
- package/runtime/utils/file-lock.sh +0 -122
- package/runtime/utils/spawn-tree.sh +0 -428
- package/runtime/utils/spawn-with-model.sh +0 -56
- package/runtime/utils/xml-utils.sh +0 -2196
- package/runtime/workers-new-castes.md +0 -516
- /package/{runtime → .aether/docs/disciplines}/coding-standards.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/debugging.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/learning.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/tdd.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/verification-loop.md +0 -0
- /package/{runtime → .aether/docs/disciplines}/verification.md +0 -0
- /package/{runtime → .aether}/schemas/aether-types.xsd +0 -0
- /package/{runtime → .aether}/schemas/colony-registry.xsd +0 -0
- /package/{runtime → .aether}/schemas/pheromone.xsd +0 -0
- /package/{runtime → .aether}/schemas/prompt.xsd +0 -0
- /package/{runtime → .aether}/schemas/queen-wisdom.xsd +0 -0
- /package/{runtime → .aether}/schemas/worker-priming.xsd +0 -0
- /package/{runtime → .aether}/utils/colorize-log.sh +0 -0
- /package/{runtime → .aether}/utils/queen-to-md.xsl +0 -0
|
@@ -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
|
+
}
|