{"id":"2847fb6a-55ed-42f9-81eb-608336a064ba","slug":"saidwhen","kind":"skill","name":"saidwhen","summary":"Decision provenance for AI-assisted development. Every requirement traces to a decision, every decision to the human answer behind it — plain markdown (OKF), no server, no database. Your agent asks on","owner":"h4nz4","repoUrl":"https://github.com/h4nz4/saidwhen","license":"MIT","licenseTier":"permissive","trust":"community","stars":2,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-07-08T00:05:38.000Z","addedAt":"2026-10-22T01:27:57.935Z","logoUrl":"https://avatars.githubusercontent.com/u/18464660?u=c11b1994be0bad9c92e747d6553cfe3cf00cab5a&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["databases","files-documents","cloud-infra"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-22T23:38:12.530Z","sample":false,"url":"https://conduits.dev/tools/saidwhen","language":"Python","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<p align=\"center\"><img src=\"assets/logo.png\" width=\"180\" alt=\"saidwhen logo\"></p>\r\n\r\n# saidwhen\r\n\r\n[![CI](https://github.com/h4nz4/saidwhen/actions/workflows/ci.yml/badge.svg)](https://github.com/h4nz4/saidwhen/actions/workflows/ci.yml)\r\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\r\n[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](validator/validate.py)\r\n[![Dependencies: none](https://img.shields.io/badge/dependencies-none-brightgreen.svg)](validator/validate.py)\r\n[![Format: OKF](https://img.shields.io/badge/format-OKF-orange.svg)](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)\r\n\r\n> Your project's wiki, maintained by your agents — and actually trustworthy.\r\n\r\n**saidwhen** is an agent-maintained project wiki in a loop with\r\n[OpenSpec](https://github.com/Fission-AI/OpenSpec). One\r\n[OKF](https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md)\r\nbundle of plain markdown serves three readers at once: **agents** read it as\r\nproject memory before every task, the **spec workflow** draws on it and\r\nfeeds it, and **humans** browse it as a compiled wiki site. What makes it\r\ntrustworthy is built-in provenance plumbing: every entry knows *who said it,\r\nwhen, and what would reopen it* — so agents can challenge stale knowledge\r\ninstead of blindly obeying or silently ignoring it. No server, no database,\r\nno vector index, no SDK.\r\n\r\n```\r\n spec requirement          decision                 attributed fact\r\n┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐\r\n│ \"MUST use magic  │────▶│ chose magic links│────▶│ users are        │\r\n│  link login\"     │ why?│ over OAuth       │ who │ external, no IdP │\r\n│                  │     │ because...       │said?│ —ivan, 2026-07-08│\r\n└──────────────────┘     └──────────────────┘     └──────────────────┘\r\n```\r\n\r\nSix months later someone asks \"can we add OAuth?\" — the agent follows the\r\nlinks, finds it was rejected and why, and asks only: *\"decided 2026-07-08\r\nbecause users have no IdP — is that still true?\"* No re-litigating, no\r\nre-interviewing, no blind obedience.\r\n\r\n## The loop\r\n\r\n- **In:** exploring or proposing an [OpenSpec](https://github.com/Fission-AI/OpenSpec)\r\n  change consults the wiki first and pulls the relevant facts, constraints,\r\n  and decisions into the proposal — by link, not by re-asking you.\r\n- **Out:** archiving a change writes the crystallized knowledge back and\r\n  updates the architecture pages it altered — and an optional\r\n  [Stop hook](skills/wiki-opsx-archive/scripts/wiki-after-openspec.py) makes\r\n  it automatic, blocking only when the wiki has fallen behind an archive and\r\n  staying silent (zero tokens) when it hasn't.\r\n- **Checked:** the [validator](validator/validate.py) resolves every link,\r\n  flags citations of superseded decisions, and maps a PR's changed files\r\n  back to the decisions that govern them.\r\n- **Rendered:** CI compiles the bundle into a browsable wiki site on every\r\n  push ([latest build](https://github.com/h4nz4/saidwhen/actions/workflows/ci.yml)\r\n  → `wiki-site` artifact) — rich pages for humans, zero extra tokens for\r\n  agents, regenerated instead of maintained. The output is plain static\r\n  HTML: host it anywhere, or render the single-file `wiki.html` and open it\r\n  from disk.\r\n\r\n## Quickstart (5 minutes)\r\n\r\n1. Install the skills — one command:\r\n   - **Any agent** (Claude Code, Cursor, Codex, 20+ others):\r\n     `npx skills add h4nz4/saidwhen`\r\n   - **Claude Code** (full suite as a plugin):\r\n     `/plugin marketplace add h4nz4/saidwhen` then\r\n     `/plugin install saidwhen@saidwhen`\r\n   - **Or copy** directories from [skills/](skills/) into your agent's skills\r\n     folder — `.claude/skills/` (Claude Code), `.agents/skills/` (Codex), or\r\n     your agent's equivalent ([install matrix](skills/README.md)). Minimal\r\n     set: `wiki-init`, `wiki-explore`, `wiki-capture`.\r\n2. Ask your agent to set up the wiki — `wiki-init` scaffolds `docs/knowledge/`\r\n   and offers the [AGENTS.md snippet](skills/wiki-init/assets/snippet.md), the\r\n   ambient fallback for agents without Agent Skills support.\r\n3. Work normally. Your agent now reads `docs/knowledge/` before asking you\r\n   anything, and records facts and decisions as they crystallize.\r\n\r\nOptional: vendor [validator/validate.py](validator/validate.py) (one stdlib\r\nfile) and run `python validate.py docs/knowledge` in CI — the wiki-capture\r\nskill also bundles it. [OpenSpec](https://github.com/Fission-AI/OpenSpec)\r\nuser? Install the `wiki-opsx-*` skills — that's the loop above.\r\n\r\n## The trust layer measurably works\r\n\r\nThe wiki's integrity behaviors — recall instead of re-planning, the delta\r\nquestion instead of blind obedience, no fabricated citations — and the 2.0\r\nwiki-first claims are backed by pre-registered experiments with published\r\ntranscripts across five rounds, zero rubric exceptions.\r\n\r\n| Claim | Evidence | Result |\r\n|---|---|---|\r\n| Recalls rejected features instead of re-planning them | [round 1](evidence/experiment/results.md) | 6/6 vs control 0/6, p ≈ 0.0011 |\r\n| Reopens stale decisions via their own revisit triggers — no blind obedience | [rounds 2+3](evidence/experiment/round3/results.md) | 6/6 vs 0/6, p ≈ 0.0011 |\r\n| Shapes ordinary proposals around recorded constraints | [rounds 2+3](evidence/experiment/round3/results.md) | 6/6 vs 0/6, p ≈ 0.0011 |\r\n| Handles uncovered topics without fabricating provenance | [round 3](evidence/experiment/round3/results.md) | 6/6 vs 0/6, p ≈ 0.0011; 9/9 clean on the fabrication probe |\r\n| Same behavior when delivered as an auto-triggering skill — on two different agent CLIs | [round 4](evidence/experiment/round4-skill-trigger/results.md) | 36/36 runs pass both rubrics; skill auto-triggered 24/24 |\r\n| **Wiki-first is more accurate AND cheaper** on the same consult prompts (onboarding + conflicting-rewrite) | [round 6](evidence/experiment/round6-consult/results.md) | 6/6 vs 0/6, p ≈ 0.0011; **−33% billable tokens/session**, p ≈ 0.0076 |\r\n\r\nFull write-up: [evidence/VALIDATION.md](evidence/VALIDATION.md). Honest\r\nlimitations included (single model family, demo-sized wikis, unblinded\r\nscoring with published raw outputs; round 6 ran lean — 12 sessions at low\r\nreasoning effort — per a recorded owner directive, with all amendments\r\nregistered before the first run).\r\n\r\n### And this repo runs on it\r\n\r\n[docs/knowledge/](docs/knowledge/) is saidwhen's own live bundle, not a demo. Why is\r\nthe product wiki-first now? [The decision](docs/knowledge/decisions/okf-wiki-pivot.md)\r\nanswers, linked to the [owner interview](docs/knowledge/interviews/2026-07-08-wiki-pivot.md)\r\nthat justified it — the same chain the diagram above promises you. CI\r\nvalidates the bundle, renders the site, and checks this README against the\r\nbundle for broken links *and* citations of superseded decisions, on every\r\npush. saidwhen itself is developed with\r\n[OpenSpec](https://github.com/Fission-AI/OpenSpec) through the `wiki-opsx-*`\r\nskills we ship: the loop you get is the one we use daily.\r\n\r\n## Docs that don't rot\r\n\r\nAny in-repo markdown — architecture notes, `docs/`, even your `AGENTS.md` —\r\ncan carry the same why-links as specs — like this real one:\r\n([why](example/knowledge/decisions/magic-link-auth.md)). Then\r\n\r\n```\r\npython validator/validate.py docs/knowledge --check-specs AGENTS.md --check-specs openspec/specs\r\n```\r\n\r\nfails CI when a link breaks **or when a cited decision has been superseded**:\r\nthe doc leaning on a stale why gets flagged, with its successor named. Docs\r\nstop silently outliving the decisions under them.\r\n\r\nThe reverse direction works too: give a decision a `scope:` of the paths it\r\ngoverns, and\r\n\r\n```\r\ngit diff --name-only main | python validator/validate.py docs/knowledge --check-diff -\r\nWHY   decisions/eur-only.md (accepted) governs: index.html\r\n```\r\n\r\ntells a PR review — human or agent — which recorded decisions a change\r\ntouches, before it quietly rebuilds something already rejected. Advisory\r\noutput; it never fails the run.\r\n\r\n## What's in the box\r\n\r\n| Layer | What | Where |\r\n|---|---|---|\r\n| **Bundle convention** | Wiki layout, concept types, fact-form capture, linking rules, decision lifecycle, upkeep and render contracts. One page, versioned. | [CONVENTION.md](CONVENTION.md) |\r\n| **Behaviors** | Tool-agnostic prompts: [read-first](behaviors/read-first.md), [capture](behaviors/capture.md), [bootstrap](behaviors/bootstrap.md), [component-upkeep](behaviors/component-upkeep.md), [gc](behaviors/gc.md). The validated wording. | [behaviors/](behaviors/) |\r\n| **Skills** | Drop-in [Agent Skills](https://agentskills.io/home) (open standard, any supporting agent): init, bootstrap, explore, capture, render, gc, [OpenSpec](https://github.com/Fission-AI/OpenSpec) loop. The ambient [AGENTS.md snippet](skills/wiki-init/assets/snippet.md) ships inside wiki-init as the fallback. | [skills/](skills/) |\r\n| **Renderer** | Bundle → browsable static wiki site. Stdlib, one file, disposable output. | [render/](render/) |\r\n| Demo | TaskLite — browse a working knowledge chain on GitHub. | [example/](example/) |\r\n| Validator | Frontmatter, links, evidence and attribution rules, docs-rot and diff checks. Stdlib, one file. | [validator/](validator/) |\r\n| Proof | Protocols, 54 raw transcripts, scoring, statistics. | [evidence/](evidence/) |\r\n\r\n## How it's different from agent-memory tools\r\n\r\nMemory tools capture **everything ambiently** (transcripts, embeddings) and\r\nhope retrieval finds the needle. saidwhen captures **at the moment knowledge\r\ncrystallizes** — the point of highest signal — as attributed facts a human\r\ncan browse on GitHub and an agent can cite by path. It is a format and a\r\nbehavior, not a platform: produced without an SDK, consumed without an\r\nintegration, portable between agents, and it degrades gracefully to\r\nwell-organized docs.\r\n\r\n## License\r\n\r\n[MIT](LICENSE). Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md),\r\nespecially the rule about re-validating behavior edits.\r\n"}