aboutsummaryrefslogtreecommitdiff
path: root/.ai/protocols.org
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-14 22:07:00 -0500
committerCraig Jennings <c@cjennings.net>2026-06-14 22:07:00 -0500
commite0f914d510c081db45cafaf4fe5c8f7b65e46fec (patch)
tree8ad851aea65e0e5fc1b6adbc70355b435a4dde0d /.ai/protocols.org
parent16e64fb5f81bd8c3eaa2dc4c00a796ddbec01441 (diff)
downloadrulesets-e0f914d510c081db45cafaf4fe5c8f7b65e46fec.tar.gz
rulesets-e0f914d510c081db45cafaf4fe5c8f7b65e46fec.zip
docs(ai): require an epoch on the tail of helper-agent ids
A helper agent's session-context file is .ai/session-context.d/<id>.org. A bare, reused id like "codex" makes the next run resolve to the previous run's leftover anchor, which it then mistakes for a crash to recover or clobbers. That bit on 2026-06-13: a codex run left codex.org for the next session to clean up. The fix is a convention, not a resolver change. The spawner appends an epoch on the tail (host.project.runtime.<epoch>) so each run gets a fresh anchor. The epoch can't be minted inside session-context-path, since that resolver runs many times per session and must return the same path each call. I documented it in protocols.org, the wrap-up recommended-shape note, and the resolver header.
Diffstat (limited to '.ai/protocols.org')
-rw-r--r--.ai/protocols.org4
1 files changed, 4 insertions, 0 deletions
diff --git a/.ai/protocols.org b/.ai/protocols.org
index 6b1d873..caa5303 100644
--- a/.ai/protocols.org
+++ b/.ai/protocols.org
@@ -100,6 +100,10 @@ When two agents share one project at the same time, a single =session-context.or
- =AI_AGENT_ID= unset or empty (the normal one-agent-per-project case): =.ai/session-context.org=, exactly as before.
- =AI_AGENT_ID= set: =.ai/session-context.d/<id>.org= (id sanitized to filename-safe chars). Archived at wrap-up to =.ai/sessions/YYYY-MM-DD-HH-MM-<id>-<description>.org= so concurrent agents don't collide on the archive name either.
+The id must be unique per run, and the spawner makes it so by appending an epoch on the tail. The recommended shape is =host.project.runtime.<epoch>= (e.g. =velox.rulesets.claude.1718400000=); a fresh run of the same logical agent then resolves to a fresh anchor. A bare, reused id (just =codex=) makes the next run resolve to the previous run's leftover =codex.org= and either mistake it for a crashed session to recover or clobber it if both run at once. This happened on 2026-06-13: a =codex= run left =session-context.d/codex.org= behind, and the next session had to clean it up by hand.
+
+The epoch is baked into the id by the spawner, never minted inside =session-context-path=. That resolver is called many times per session (startup existence check, every log write, the wrap-up rename) and must return the same path on every call, so a self-generated =date +%s= would fragment the anchor across calls. The shell that runs each call doesn't carry env between calls either, so the agent can't export the epoch once at startup. The only stable source is the =AI_AGENT_ID= the spawner injects on every call.
+
Resolve the path with =.ai/scripts/session-context-path= rather than hardcoding =.ai/session-context.org=; it prints the right path for the current =AI_AGENT_ID=. Fall back to =.ai/session-context.org= if the script isn't present (older checkouts mid-sync). Everything below — the record/recovery purpose, the update triggers, the startup existence check, the wrap-up rename — operates on that resolved path. The prose says "session-context.org" as the default name; read it as "the resolved active path" when =AI_AGENT_ID= is set.
This file serves two purposes with one mechanism: