Skip to content

stabilize: snapshot-pinning scaffolding (Amara action #2 — completes Stabilize stage)#223

Merged
AceHack merged 1 commit intomainfrom
stabilize/snapshot-pinning-tick-history-amara-action-2
Apr 24, 2026
Merged

stabilize: snapshot-pinning scaffolding (Amara action #2 — completes Stabilize stage)#223
AceHack merged 1 commit intomainfrom
stabilize/snapshot-pinning-tick-history-amara-action-2

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented Apr 24, 2026

Summary

Completes Amara's Stabilize-stage from her 4th ferry roadmap (PR #221). The remaining action item: pin Claude model + loaded memory + prompt bundle so "Claude" isn't a moving target across model-version shifts.

What landed

Three-part v0 scaffolding:

  • tools/hygiene/capture-tick-snapshot.sh — capture helper (YAML / JSON output; CLI version + file SHAs + git state; agent fills model + prompt bundle hash)
  • docs/hygiene-history/session-snapshots.md — session-level + significant-event pin sidecar (append-only), seeded with first entry
  • docs/hygiene-history/loop-tick-history.md — new subsection documenting the snapshot-pinning discipline + relationship to the sidecar file

Amara Stabilize-stage complete

First-run observation

Snapshot tool first fire surfaced: memory/MEMORY.md at 58,842 bytes (~58KB) — over the FACTORY-HYGIENE row #11 24,976-byte cap. Known separately-tracked drift. Not fixed in this PR; flagged for separate cleanup.

What this PR is NOT

  • Not CI-gated (v0 discipline; enforcement is Determinize-stage)
  • Not retroactive for prior sessions (starts from here forward)
  • Not complete — model_snapshot + prompt_bundle_hash are agent-filled / future-tool-filled respectively
  • Not a per-tick gate (per-tick pins are optional; don't slow CronList close)

Composes with "deterministic reconciliation" (Otto-67)

Snapshot pinning is the mechanism that reconciles "what Claude knew" with "what Claude did" across time. Necessary for audit, future tuning pipelines (per Otto-57 PR-review archive memory), and Amara-style drift analysis.

Test plan

  • capture-tick-snapshot.sh runs clean on current branch (YAML output seeded the sidecar entry)
  • Sidecar file + schema extension cross-reference each other and the capture tool
  • actionlint N/A (no new workflow); shellcheck-via-eyeball on the shell script

🤖 Generated with Claude Code

…(Amara action #2)

Amara's 4th ferry (PR #221) action item #2: pin Claude model
snapshot + loaded memory state + prompt bundle hash so "Claude"
is not a moving target across model version shifts (3.5 → 3.7 →
4 → 4.x all have materially different system-prompt bundles +
knowledge cutoffs + memory-retention language per archived Drive
artifacts).

Three-part scaffolding (v0):

1. tools/hygiene/capture-tick-snapshot.sh
   - Captures mechanically-accessible state:
     * Claude Code CLI version (`claude --version`)
     * CLAUDE.md + AGENTS.md + memory/MEMORY.md SHAs
     * Memory index byte count
     * Git HEAD + branch + repo
     * Date UTC
     * Per-user ~/.claude/CLAUDE.md SHA if present
   - Outputs YAML (default) or JSON (`--json`)
   - Agent fills model_snapshot + prompt_bundle_hash from
     session context (not CLI-accessible today)

2. docs/hygiene-history/session-snapshots.md
   - Session-level + significant-event pins (not per-tick)
   - Append-only row format: session_id / captured_utc /
     event (session-open | mid-session-pin | session-close |
     compaction) / agent / model / CLI version / git state /
     files SHAs / notes / prompt_bundle_hash
   - Seeded with one mid-session-pin for this tick's Otto-70
     capture (the session has been running ~70 ticks; actual
     session-open is earlier and unreachable for pins)

3. docs/hygiene-history/loop-tick-history.md schema extension
   - New "On snapshot pinning" subsection documenting the
     relationship: per-tick pins optional + inline in `notes`;
     session-level pins go in the sidecar file.
   - Snapshot capture is discipline, not gate — don't slow
     the autonomous-loop tick-close for every fire.

What the snapshot does NOT capture yet:

- model_snapshot — known to the agent from session context,
  not exposed by `claude --version` (which gives CLI version
  only). Agent fills.
- prompt_bundle_hash — no current tool reconstructs the
  system prompt bundle. Placeholder null until such a tool
  lands. Amara's Determinize-stage work potentially.
- Active permissions / skill set — session-specific; not
  captured in v0.

First run of the tool on this branch surfaced a separate
drift: memory/MEMORY.md is at 58842 bytes (~58KB, over the
FACTORY-HYGIENE row #11 24976-byte cap). Not fixed in this
PR — known-separately tracked drift.

Amara Stabilize-stage: 3/3 landed (with this PR).
  ✓ Action #3 — decision-proxy-evidence schema (PR #222)
  ✓ Action #4 — branch-chat non-canonical framing (PR #222)
  ✓ Action #2 — snapshot pinning scaffolding (this PR)

"Deterministic reconciliation" framing (Otto-67 endorsement):
snapshot pinning is the mechanism that reconciles "what Claude
knew" with "what Claude did" across time — essential for any
future audit, tuning, or Amara-style drift analysis.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 24, 2026 00:30
@AceHack AceHack enabled auto-merge (squash) April 24, 2026 00:30
@AceHack AceHack merged commit a1a013f into main Apr 24, 2026
12 checks passed
@AceHack AceHack deleted the stabilize/snapshot-pinning-tick-history-amara-action-2 branch April 24, 2026 00:31
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds initial snapshot-pinning scaffolding so autonomous-loop ticks and significant session events can record the exact “Claude state” (CLI version, key file SHAs, git state) to reduce model/prompt/memory drift over time.

Changes:

  • Introduces tools/hygiene/capture-tick-snapshot.sh to emit a snapshot fingerprint (YAML/JSON).
  • Adds docs/hygiene-history/session-snapshots.md as an append-only sidecar log for session-level state pins.
  • Extends docs/hygiene-history/loop-tick-history.md with guidance on when/how to pin snapshots.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
tools/hygiene/capture-tick-snapshot.sh New capture helper that prints a snapshot fingerprint of git + key file SHAs + CLI version (YAML/JSON).
docs/hygiene-history/session-snapshots.md New append-only session snapshot sidecar with schema and seeded first entry.
docs/hygiene-history/loop-tick-history.md Documents optional per-tick snapshot pinning and links to the new sidecar + capture helper.

Comment on lines +56 to +63
git hash-object "$1" 2>/dev/null || printf ''
fi
}

safe_bytes() {
if [[ -f "$1" ]]; then
wc -c < "$1" 2>/dev/null | tr -d ' ' || printf ''
fi
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: safe_sha/safe_bytes can return a non-zero status when the file does not exist (the [[ -f ... ]] test fails), which can still abort the script under set -e during var=$(safe_sha ...) assignments. Make these helpers always succeed (exit 0) and print an empty string when the file is missing, matching the comment’s stated behavior.

Suggested change
git hash-object "$1" 2>/dev/null || printf ''
fi
}
safe_bytes() {
if [[ -f "$1" ]]; then
wc -c < "$1" 2>/dev/null | tr -d ' ' || printf ''
fi
git hash-object "$1" 2>/dev/null || printf ''
else
printf ''
fi
return 0
}
safe_bytes() {
if [[ -f "$1" ]]; then
wc -c < "$1" 2>/dev/null | tr -d ' ' || printf ''
else
printf ''
fi
return 0

Copilot uses AI. Check for mistakes.
memory_index_bytes=$(safe_bytes "memory/MEMORY.md")
head_sha=$(git rev-parse HEAD 2>/dev/null || printf 'unknown')
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || printf 'unknown')
repo_full=$(git config --get remote.origin.url 2>/dev/null | sed -E 's|.*[:/]([^/]+/[^/]+)(\.git)?$|\1|' || printf 'unknown')
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: repo_full parsing can incorrectly retain the .git suffix for common remotes like git@github.com:owner/repo.git or https://.../owner/repo.git because the capture group includes the .git portion. Consider stripping a trailing .git after extraction (or use git remote get-url origin + explicit suffix removal) so repo is consistently owner/repo.

Suggested change
repo_full=$(git config --get remote.origin.url 2>/dev/null | sed -E 's|.*[:/]([^/]+/[^/]+)(\.git)?$|\1|' || printf 'unknown')
repo_full=$(git config --get remote.origin.url 2>/dev/null | sed -E 's|.*[:/]([^/]+/[^/]+)(\.git)?$|\1|' | sed -E 's|\.git$||' || printf 'unknown')

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +10
# Captures a snapshot pin of factory state at tick-open /
# tick-close time. Prints a YAML fragment that can be pasted
# into:
# - docs/hygiene-history/session-snapshots.md (session-level)
# - docs/decision-proxy-evidence/DP-NNN.yaml `model` block
# (decision-level)
# - a tick-history row's `notes` column (tick-level)
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: The header claims this YAML can be pasted into session-snapshots.md and the DP model block, but the script’s YAML output is a snapshot: object (and JSON has top-level model_snapshot), which doesn’t match either documented schema (session snapshots are list rows; DP expects a nested model: block). Align the emitted shape with the target schemas (or add mode flags) to avoid copy/paste errors.

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +15
per-decision pin-time. Addresses Amara's 4th-ferry concern
(PR #221) that "Claude is not a single stable operator unless
the actual snapshot, system-prompt bundle, and loaded memory
surfaces are all pinned and recorded."

## Why this file

Across Claude model versions (3.5 → 3.7 → 4 → 4.x), the
system-prompt bundle + knowledge cutoff + memory-retention
language shift materially. When a future session, external
reviewer, or tuning pipeline asks *"what did Kenji actually
know when this decision was made?"* this file answers.
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: This doc introduces direct contributor/agent names (e.g., “Kenji”, “Amara”, “Otto”). docs/AGENT-BEST-PRACTICES.md operational standing rule forbids name attribution in non-exempt docs and requires role references instead. Please rewrite these references to role-refs (e.g., “architect”, “external AI maintainer”, “loop agent”, “human maintainer”) and keep personal names confined to the exempt surfaces.

Suggested change
per-decision pin-time. Addresses Amara's 4th-ferry concern
(PR #221) that "Claude is not a single stable operator unless
the actual snapshot, system-prompt bundle, and loaded memory
surfaces are all pinned and recorded."
## Why this file
Across Claude model versions (3.5 → 3.7 → 4 → 4.x), the
system-prompt bundle + knowledge cutoff + memory-retention
language shift materially. When a future session, external
reviewer, or tuning pipeline asks *"what did Kenji actually
know when this decision was made?"* this file answers.
per-decision pin-time. Addresses the external AI maintainer's
4th-ferry concern (PR #221) that "Claude is not a single
stable operator unless the actual snapshot, system-prompt
bundle, and loaded memory surfaces are all pinned and
recorded."
## Why this file
Across Claude model versions (3.5 → 3.7 → 4 → 4.x), the
system-prompt bundle + knowledge cutoff + memory-retention
language shift materially. When a future session, external
reviewer, or tuning pipeline asks *"what did the architect
actually know when this decision was made?"* this file
answers.

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +55
scaffolding (PR <this-pr>): when a tick's action is
proxy-significant or settings-changing, the `notes`
column can include a brief snapshot fingerprint
(CLAUDE.md SHA, model snapshot). For session-level
state — model swap, compaction boundary, significant
memory migration — use the dedicated sidecar file
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: PR <this-pr> is a placeholder that will become stale/unresolvable after merge. Replace it with the actual PR number (and ideally a link) so the provenance trail remains auditable.

Suggested change
scaffolding (PR <this-pr>): when a tick's action is
proxy-significant or settings-changing, the `notes`
column can include a brief snapshot fingerprint
(CLAUDE.md SHA, model snapshot). For session-level
state — model swap, compaction boundary, significant
memory migration — use the dedicated sidecar file
scaffolding: when a tick's action is proxy-significant
or settings-changing, the `notes` column can include a
brief snapshot fingerprint (CLAUDE.md SHA, model
snapshot). For session-level state — model swap,
compaction boundary, significant memory migration — use
the dedicated sidecar file

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 040b849a8e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +67 to +70
claude_md_sha=$(safe_sha "./CLAUDE.md")
agents_md_sha=$(safe_sha "./AGENTS.md")
memory_index_sha=$(safe_sha "memory/MEMORY.md")
memory_index_bytes=$(safe_bytes "memory/MEMORY.md")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Anchor snapshot file paths to repository root

The snapshot fields are read from ./CLAUDE.md, ./AGENTS.md, and memory/MEMORY.md relative to the caller’s current directory, so running this helper from any non-root cwd (for example docs/) silently produces empty hashes/byte counts while still returning success. That creates incomplete pin records that appear valid and weakens the audit/reproducibility goal of this feature; resolve paths from git rev-parse --show-toplevel (or the script directory) before hashing.

Useful? React with 👍 / 👎.

AceHack added a commit that referenced this pull request Apr 24, 2026
…rows (Amara Govern-stage 1/2)

Amara's 4th ferry (PR #221 absorb) named populating
docs/CONTRIBUTOR-CONFLICTS.md as the Govern-stage action: the
schema has existed since PR #166 but the Resolved table was
empty despite multiple session-observed contributor-level
disagreements that closed with evidence.

Backfills three genuine contributor-level conflicts observed
this session (narrow scope — not maintainer-directives,
which are out-of-scope per the schema's contributor-level
disagreement definition):

- CC-001: Copilot (PR reviewer) vs Aaron on no-name-attribution
  rule scope (history-file exemption). Resolved in Aaron's
  favor via Otto-52 clarification; policy BACKLOG row filed
  in PR #210.
- CC-002: Amara (4th ferry) vs Otto (pre-Otto-67 pattern) on
  Stabilize-vs-keep-opening-new-frames. Resolved in Amara's
  favor; Otto pivoted at Otto-68 to execute her roadmap;
  3/3 Stabilize + 3/5 Determinize landed via PRs
  #222/#223/#224/#225/#226.
- CC-003: Codex (PR reviewer) vs Otto (initial framing) on
  citing-absent-artifacts. Resolved in Codex's favor via fix
  commits 29872af/1c7f97d on PRs #207/#208; pattern now
  discipline (distinguish merged-on-main from
  proposed-in-PR-open).

All three rows follow the schema's 8-column layout and include
the full Resolution-so-far / Scope / Source cells the schema
requires. No retroactive Aaron→human-maintainer sweep of prior
rows; schema's rule 1 (resolutions are additive) honored.

This is 1/2 of Amara's Govern-stage work. 2/2 is the
authority-envelope + escalation-path ADR (deferred, M-effort).

Part of Amara's 4-stage remediation roadmap
(Stabilize → Determinize → Govern → Assure).

Otto-75 tick.
AceHack added a commit that referenced this pull request Apr 24, 2026
…rows (Amara Govern 1/2) (#227)

* govern: CONTRIBUTOR-CONFLICTS backfill — 3 resolved session-observed rows (Amara Govern-stage 1/2)

Amara's 4th ferry (PR #221 absorb) named populating
docs/CONTRIBUTOR-CONFLICTS.md as the Govern-stage action: the
schema has existed since PR #166 but the Resolved table was
empty despite multiple session-observed contributor-level
disagreements that closed with evidence.

Backfills three genuine contributor-level conflicts observed
this session (narrow scope — not maintainer-directives,
which are out-of-scope per the schema's contributor-level
disagreement definition):

- CC-001: Copilot (PR reviewer) vs Aaron on no-name-attribution
  rule scope (history-file exemption). Resolved in Aaron's
  favor via Otto-52 clarification; policy BACKLOG row filed
  in PR #210.
- CC-002: Amara (4th ferry) vs Otto (pre-Otto-67 pattern) on
  Stabilize-vs-keep-opening-new-frames. Resolved in Amara's
  favor; Otto pivoted at Otto-68 to execute her roadmap;
  3/3 Stabilize + 3/5 Determinize landed via PRs
  #222/#223/#224/#225/#226.
- CC-003: Codex (PR reviewer) vs Otto (initial framing) on
  citing-absent-artifacts. Resolved in Codex's favor via fix
  commits 29872af/1c7f97d on PRs #207/#208; pattern now
  discipline (distinguish merged-on-main from
  proposed-in-PR-open).

All three rows follow the schema's 8-column layout and include
the full Resolution-so-far / Scope / Source cells the schema
requires. No retroactive Aaron→human-maintainer sweep of prior
rows; schema's rule 1 (resolutions are additive) honored.

This is 1/2 of Amara's Govern-stage work. 2/2 is the
authority-envelope + escalation-path ADR (deferred, M-effort).

Part of Amara's 4-stage remediation roadmap
(Stabilize → Determinize → Govern → Assure).

Otto-75 tick.

* govern: annotate CC-002/CC-003 Source cells — PR #221/#219 open, not yet on main

Applies CC-003's own discipline (cite-as-open-not-landed) to CC-002 and CC-003
themselves. Both rows cited `docs/aurora/2026-04-23-amara-memory-drift-*` and
`docs/aurora/2026-04-23-amara-decision-proxy-*` without the "not yet on main"
marker — the files are added by PRs #221 / #219 which are still open.

Drain for PR #227 review threads PRRT_kwDOSF9kNM59RFIx and
PRRT_kwDOSF9kNM59RFJE (dangling file refs at lines 132, 133).

* fix: markdownlint auto-fixes on governance doc

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants