# DECISION LOG
# What the agent CHOSE and WHY - proactive memory ("I chose this").
# Complement to an error log ("I broke this"). Append-only: history is
# never rewritten - corrections are new entries that point back.

# THREE STATES:
#   LOCKED   - the decision stands
#   OPEN     - deferred; needs a decision next session
#   REVISED  - supersedes an earlier decision (carries SUPERSEDES: <ts>)

# THE FORK RULE (when to log):
#   Log a decision when reversing it would cost time, or when you
#   actively considered an alternative and picked one.

# Entry format:
#   [2026-08-09 14:32] DECISION: used regex instead of AST parser
#     REASON: faster for simple case, file was small
#     FILES: src/parser.py
#     STATUS: LOCKED

# A REVISED entry points back at what it replaced:
#   [2026-08-10 09:15] DECISION: moved parser to AST
#     REASON: file grew past 200 lines; regex became unmaintainable
#     FILES: src/parser.py
#     SUPERSEDES: 2026-08-09 14:32
#     STATUS: REVISED

================================================================================
1) EXAMPLE ENTRIES
================================================================================
[2026-08-09 14:32] DECISION: used regex instead of AST parser
  REASON: faster for simple case, file was small
  FILES: src/parser.py
  STATUS: LOCKED

[2026-08-09 15:00] DECISION: auth flow - JWT over OAuth
  REASON: single API consumer, no third-party login needed yet
  FILES: auth.py
  STATUS: OPEN

[2026-08-10 09:15] DECISION: moved parser to AST
  REASON: file grew past 200 lines; regex became unmaintainable
  FILES: src/parser.py
  SUPERSEDES: 2026-08-09 14:32
  STATUS: REVISED

================================================================================
2) VALIDATION
================================================================================
Run `python check_decisions.py` (no arguments) to validate the log:
  - every entry needs a timestamp, DECISION, REASON, and a valid STATUS
  - STATUS must be LOCKED, OPEN, or REVISED
  - a REVISED entry must carry SUPERSEDES: <timestamp of what it replaces>
  - SUPERSEDES must point at an entry that actually exists
  - timestamps must be unique
Exit code 0 = valid, 1 = invalid.

================================================================================
3) WORKFLOW
================================================================================
  - Before fixing/choosing: run `python start.py` to see recent decisions
    and anything still OPEN.
  - When you make a fork-in-the-road choice:
        python check_decisions.py --decide
  - When you change your mind later:
        python check_decisions.py --revise
  - Distill recurring reversals into rules:
        python check_decisions.py --review
        python check_decisions.py --review --apply   # writes rules.txt drafts

================================================================================
4) COMPANION TOOL
================================================================================
This is the decision half of the pair. The failure half lives in
agent-error-log (errors.txt). The two feed the same permanent memory:
  - failures teach rules (agent-error-log --lessons)
  - decisions teach rules (this tool --review)
Cross-link them in your setup notes.

[2026-08-09 05:41] DECISION: Build agent-decision-log as companion to agent-error-log
  REASON: Handoff pain: new sessions re-explore settled decisions; boot recall fixes recall at session start
  FILES: src/, docs
  STATUS: LOCKED.

[2026-08-09 05:45] DECISION: JWT for single-consumer API
  REASON: one API consumer, no third-party login needed - OAuth adds infra we do not need yet
  FILES: auth.py
  SUPERSEDES: 2026-08-09 15:00
  STATUS: LOCKED.

[2026-08-11 10:00] DECISION: back to regex for the small parser
  REASON: parser file shrank to 40 lines after cleanup; AST setup felt like overhead
  FILES: src/parser.py
  SUPERSEDES: 2026-08-10 09:15
  STATUS: REVISED.

[2026-08-12 11:30] DECISION: AST after all - parser split across modules
  REASON: refactor split the parser; regex state scattered across five functions
  FILES: src/parser.py
  SUPERSEDES: 2026-08-11 10:00
  STATUS: REVISED.

[2026-08-11 14:00] DECISION: YAML for project config
  REASON: readable, human-editable, matches the ecosystem defaults
  FILES: config.yaml
  STATUS: LOCKED.

[2026-08-12 09:00] DECISION: TOML for config
  REASON: typed values and no tag soup; CI templates already use it
  FILES: config.yaml
  SUPERSEDES: 2026-08-11 14:00
  STATUS: REVISED.

[2026-08-13 10:15] DECISION: back to YAML for config
  REASON: team convention and the internal tooling reads YAML natively
  FILES: config.yaml
  SUPERSEDES: 2026-08-12 09:00
  STATUS: REVISED.

[2026-08-09 05:56] DECISION: Release workflow skips cleanly when CHANGELOG has no released version
  REASON: A fresh repo has only [Unreleased]; the old exit-1 reddened every non-release push and the first live push proved it. Skip (exit 0) + guard.
  FILES: .github/workflows/release.yml
  STATUS: LOCKED.

[2026-08-09 06:01] DECISION: Release v0.1.0 - first published release of the decision log
  REASON: The repo is live and green; a released version makes the release badge render and gives the pitch kit a citable version
  FILES: CHANGELOG.md
  STATUS: LOCKED.

[2026-08-09 06:55] DECISION: add a companion badge to the README badge row linking agent-error-log
  REASON: the ecosystem cross-link should be visible at the top of the README, not only in the bottom Companion section; mirrors the sibling's badge row
  STATUS: LOCKED.

[2026-08-09 07:26] DECISION: add a commit-message gate to the CI workflow
  REASON: the AREA marker was convention only - this repo has no local commit hook, so mechanical enforcement needs a server-side gate in CI
  FILES: check_decisions.py, .github/workflows/ci.yml, _test_decisions.py
  STATUS: LOCKED.

[2026-08-09 07:36] DECISION: document the CI commit-message gate in AGENTS.md
  REASON: agents must know the AREA marker is enforced server-side - this repo has no local hook, and docs should match the enforced reality
  FILES: AGENTS.md
  STATUS: LOCKED.

[2026-08-09 07:50] DECISION: release v0.2.0 of agent-decision-log with the CI-gate work
  REASON: the CI-gate feature and follow-up polish are verified (104 tests, lint clean, gate green on master) - time to ship them as a release
  FILES: CHANGELOG.md
  STATUS: LOCKED.

[2026-08-09 07:59] DECISION: state the unit-test count explicitly in the README Development section
  REASON: an explicit count prevents silent drift - the same stale-count bug that hit the error-log (quoted '90' vs real count); a reviewer flagged the vague '100% pass expected' wording
  FILES: README.md
  STATUS: LOCKED.

[2026-08-09 08:26] DECISION: add a README test-count drift guard to CI
  REASON: the README's stated test count has drifted twice across the pair (90 vs 117; '100% pass expected' with no count) - a guard that fails CI on mismatch prevents the class of bug
  FILES: _check_readme_count.py, .github/workflows/ci.yml
  STATUS: LOCKED.

[2026-08-09 08:40] DECISION: release v0.3.0 of agent-decision-log with the drift guard
  REASON: the drift guard and the explicit test-count fix are verified (104 tests, lint clean, 9/9 checks green) - time to ship them
  FILES: CHANGELOG.md
  STATUS: LOCKED.

[2026-08-09 17:00] DECISION: apply batch 1+2 review fixes across both repos
  REASON: external review scored error-log 87 / decision-log 90 and flagged real
  issues: extract-area/hook marker mismatch, en-dash statuses, decision-log file
  re-read in revise/resolve, generic review proposals, and missing fuzz/BOM/edge
  tests. Batch 1+2 = correctness fixes + edge-case tests + doc notes.
  FILES: check_decisions.py, check_errors.py, start.py, _test_decisions.py,
         _test_errors.py, README.md, CHANGELOG.md
  STATUS: OPEN.

[2026-08-09 18:00] DECISION: add a --stats analytics command to the decision-log
  REASON: external reviewer suggested analytics (reversal rate, average time from
  LOCKED to REVISED, most volatile topics) - turns the log into a decision-metrics
  dashboard. Batch 1+2 review round 3.
  FILES: check_decisions.py, _test_decisions.py, README.md, CHANGELOG.md, AGENTS.md
  STATUS: OPEN.

[2026-08-09 18:30] DECISION: document the _topic_of grouping heuristic in README and docstring
  REASON: reviewer asked whether the heuristic is documented or implicit - chose
  documentation (small) over reworking the grouping; the heuristic is deterministic
  and fit for the domain (first FILES basename, else first 3 title words).
  FILES: check_decisions.py, README.md, CHANGELOG.md
  STATUS: OPEN.

[2026-08-09 09:55] DECISION: batch 1+2 review fixes verified - OPEN decision resolved
  REASON: all 6 review fixes + fuzz tests + docs shipped via PR #16/#8; gates and drift guards green on master; reviewer list closed
  FILES: check_errors.py, check_decisions.py, start.py, _test_errors.py, _test_decisions.py, README.md, CHANGELOG.md
  SUPERSEDES: 2026-08-09 17:00
  STATUS: LOCKED.

[2026-08-09 09:56] DECISION: --stats command verified - OPEN decision resolved
  REASON: shipped via PR #9 with 10 tests (124 total); live demo on the real log works; drift guard green
  FILES: check_decisions.py, _test_decisions.py, README.md, CHANGELOG.md, AGENTS.md
  SUPERSEDES: 2026-08-09 18:00
  STATUS: LOCKED.

[2026-08-09 09:57] DECISION: _topic_of docs verified - OPEN decision resolved
  REASON: docstring + README note + CHANGELOG Docs shipped via PR #10; docs-only, 124 tests unchanged, gate green
  FILES: check_decisions.py, README.md, CHANGELOG.md
  SUPERSEDES: 2026-08-09 18:30
  STATUS: LOCKED.

[2026-08-09 10:04] DECISION: release v0.4.0 of agent-decision-log with the accumulated --stats, _topic_of docs, and resolve chore
  REASON: the [Unreleased] section has accumulated the --stats command, the _topic_of heuristic docs, and the OPEN-decision resolve chore since v0.3.0 - all verified (124 tests, lint 0/0, gates green); time to ship them
  FILES: CHANGELOG.md
  STATUS: LOCKED.

[2026-08-09 10:18] DECISION: add a PR-based push workflow section to the README
  REASON: live-page verification flagged the gap: the error-log README documents its PR flow while this repo's README does not, despite the same enforcement (branch protection + CI gate); the FAQ also still claimed 'no git gate', which the CI gate now contradicts
  FILES: README.md, CHANGELOG.md
  STATUS: LOCKED.

[2026-08-09 10:25] DECISION: apply the distilled --review proposals to rules.txt section 7
  REASON: the compounding loop produced 2 proposals (parser.py 3 reversals, config.yaml 2) with quoted REASONs; the rules.txt section 7 draft still shows the stale 10-decision generation - time to confirm and apply
  FILES: rules.txt
  STATUS: LOCKED.

[2026-08-10 17:50] DECISION: serialize log appends with a cross-process lock
  REASON: concurrent --decide/--revise/--resolve runs lost entries; the
    read-modify-write was unlocked and the last writer won. A sibling
    lock file (O_CREAT|O_EXCL, 5s wait, stale recovery) with a re-read
    inside the lock closes the race with stdlib only.
  FILES: check_decisions.py, _test_decisions.py
  STATUS: LOCKED.

[2026-08-10 10:00] DECISION: L10 locked-file read crash - degrade, never crash
  REASON: a locked log must not kill the tool; graceful empty read matches the workspace lesson
  FILES: check_decisions.py
  STATUS: LOCKED

[2026-08-10 19:14] DECISION: doc - HERE-relative default paths FAQ
  REASON: script-dir (HERE) defaults are undocumented; a scratch copy run without --log writes into the real repo log
  FILES: README.md
  STATUS: LOCKED.

[2026-08-10 19:26] DECISION: doc - README companion wording says two files, should say two tools
  REASON: companion section says 'Two files, same shape' but it is two tools/repos; error-log README says 'Two tools'
  FILES: README.md
  STATUS: LOCKED.

[2026-08-10 19:40] DECISION: fix unicode stdin double-encoding on Windows
  REASON: same stdout-only reconfigure class as error-log; piped unicode DECISION text would mojibake into decisions.txt on Windows
  FILES: check_decisions.py, _test_decisions.py
  STATUS: LOCKED.

[2026-08-10 20:29] DECISION: doc - FAQ documents Windows stdin unicode handling
  REASON: same gap as error-log: no user-facing note that piped unicode decision text is safe on Windows after the stdin fix
  FILES: README.md
  STATUS: LOCKED.

[2026-08-10 22:25] DECISION: typed refactor - type hints and dataclasses
  REASON: external review scored structure 8/20; dataclasses + type hints are stdlib-compatible and keep single-file adoption intact
  FILES: check_decisions.py
  STATUS: LOCKED.


[2026-08-11 09:30] DECISION: Ship professional packaging - pyproject, defaults guard, publish workflow
  REASON: close the distribution gap - pip-installable while keeping single-file + zero-dep promises
  FILES: pyproject.toml, check_decisions.py, ci.yml, publish.yml, README.md, CHANGELOG.md
  STATUS: LOCKED

================================================================================
5) TO ADD A NEW ENTRY
================================================================================
Run `python check_decisions.py --decide` (it scaffolds the entry for you),
or copy this template:

  [YYYY-MM-DD HH:MM] DECISION: <what you chose>
    REASON: <why - the alternative you considered>
    FILES: <files affected, optional>
    STATUS: LOCKED            (LOCKED / OPEN / REVISED)
