From 600fbf70b0c4f143da88301e225dabb40be14868 Mon Sep 17 00:00:00 2001 From: choiyounggi <74581798+choiyounggi@users.noreply.github.com> Date: Thu, 17 Sep 2026 14:04:03 +0900 Subject: [PATCH] =?UTF-8?q?knowledge:=20ingest=204=20verified=20insight(s)?= =?UTF-8?q?=20=E2=80=94=20superseding=20a=20knowledge=20record=20(1=20new?= =?UTF-8?q?=20page,=201=20drop)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dev-loop/INGEST_REPORT.md | 219 +++++++----------- log.md | 1 + ...pe-hatch-uses-as-a-knowledge-gap-signal.md | 2 +- .../retiring-a-provisional-marker.md | 2 +- .../spec-document-gates.md | 1 + .../superseding-a-knowledge-record.md | 86 +++++++ wiki/qa/index.md | 1 + 7 files changed, 173 insertions(+), 139 deletions(-) create mode 100644 wiki/qa/document-verification/superseding-a-knowledge-record.md diff --git a/.dev-loop/INGEST_REPORT.md b/.dev-loop/INGEST_REPORT.md index 0e5c4f3..53c4437 100644 --- a/.dev-loop/INGEST_REPORT.md +++ b/.dev-loop/INGEST_REPORT.md @@ -1,150 +1,95 @@ -# Knowledge flush — 4 insight(s) +# Knowledge flush — 5 insight(s) -Claimed queue ids: `c6c76b1cb2d35bf9`, `028fcf4648303397`, `1c4620e3aadaf0b7`, `56f4dbc8fb5997f8`. -All four were handled (2 new pages, 3 amended pages); none dropped. +Claimed queue ids: `44e28bb8c99c1d0c`, `f2d90d5048826870`, `fb7d73874bac6eaa`, +`5f3e5eb58ec373e4`, `6e83a02b449a8dff`. All five are plan-gap rows emitted by +`skills/wiki-plan/scripts/emit-gaps.sh` — decisions a wiki-plan marked +`[no-wiki]`. Result: 1 new page (4 rows merged into it), 1 row dropped. ## Verified best-practice -**1. `c6c76b1cb2d35bf9` — precedence tests must stage the competing condition at the deciding iteration** (→ `confidence: verified`) - -Claim: a test asserting that exit condition A wins over B must make B become true in -the same poll/iteration in which A reaches its threshold; a B staged earlier makes the -assertion hold under either ordering of the checks. - -- https://arxiv.org/abs/1909.04770 (Vera-Pérez, Danglot, Monperrus, Baudry, 2019) — fetched - this session. An undetected mutant has three causes, the first being that "the test - inputs are not sufficient to infect the state of the program". That is exactly this - failure: if B fires before A can activate, the reordering mutant is never reached in a - state where it can infect the outcome. -- https://pitest.org/quickstart/basic_concepts/ — a surviving mutant means no test - distinguishes the mutated program; a kill is attributed to the covering test, which is - why the precedence test itself (not merely the file) must redden. -- https://testing.googleblog.com/2021/04/mutation-testing.html — detection is measured by - inserting the fault and requiring failure, not by branch coverage. -- Field measurement (dev-loop `watch-status.sh`, three "R6 precedence" bats cases): moving - the exit-8 block above the failed/done check left all three green. Re-staging the - competing status transition to the same tmux-stub capture count that confirms the - two-poll witness made the same swap red. - -**2. `028fcf4648303397` — never confirm a pane witness from a capture taken in the same iteration as a key-send** (→ merged as `verified` material into an existing `verified` page) - -Claim: when a poll loop both sends keys (auto-recover `Enter`, resend) and reads a state -witness from the pane, it must skip the capture entirely on the iteration that sent keys. - -- Reproduced locally this session (tmux, macOS, `sh` pane): with the newest status line - reading `STATE=BLOCKED`, sending a command that worked 0.4s before printing left the - same-iteration `capture-pane` still showing `STATE=BLOCKED`; the next poll showed - `STATE=RUNNING`. The same sequence with an instantly-printing command had already - repainted within the same iteration — so the check's outcome is set by the target's work - time, which is why the gate belongs on "did this iteration send keys", not on a delay. -- Mechanism already sourced on the target page: https://man7.org/linux/man-pages/man1/tmux.1.html - (`send-keys` writes keys into the pane; `capture-pane` copies visible contents — neither - reports consumption) and https://man7.org/linux/man-pages/man3/termios.3.html. -- Field evidence: dev-loop code review of task `t3-blocked-consume`, finding F1 — the exit-8 - "still blocked" witness was confirmed from a same-poll capture, so a just-repaired worker - could be escalated; gating on the recovery flag fixed it, and removing the gate under - mutation woke the witness one poll early. - -**3. `1c4620e3aadaf0b7` — graphify's installed hooks miss the `git pull` path** (→ `verified`) - -Claim: `graphify hook install` covers `post-commit` and `post-checkout` only, while the -"PR merged upstream → `git pull`" path fires `post-merge`, so the graph goes stale while -`hook status` reports installed. - -- https://git-scm.com/docs/githooks — fetched this session: `post-commit` "is invoked by - git-commit"; `post-merge` "is invoked by git-merge, which happens when a `git` `pull` is - done on a local repository"; `post-checkout` "is also run after git-clone, unless the - `--no-checkout` (`-n`) option is used". -- Local reproduction (git 2.50.1, macOS): in a clone carrying all three hooks, a - fast-forward `git pull` fired `post-merge 0` alone; a divergent `git pull` that created a - merge commit also fired `post-merge 0` and **no** `post-commit`; a fresh `git clone` of - that repository carried no non-sample hooks. -- Source read: `graphifyy 0.4.23` `hooks.py:186-187` installs `"post-commit"` and - `"post-checkout"` only; `grep -c post-merge hooks.py` → 0. -- **Correction applied to the candidate's stated reasoning:** the submitted note said git - "does not run hooks on clone". Per the docs and the reproduction, `git clone` *does* run - `post-checkout` — the reason a clone gets no graph is that hooks are not copied by clone, - so none exist to run. The page carries the corrected reason. - -**4. `56f4dbc8fb5997f8` — a grounding gate's escape hatch must emit a gap record at the point it grants the pass** (→ `confidence: field-tested`) - -Claim: an escape hatch (`[no-wiki]`, a suppression comment) is the most valuable signal a -knowledge base gets, and a gate that only decides pass/fail destroys it; the record must be -emitted by the gate, not requested in prose. - -- https://docs.github.com/en/code-security/code-scanning/managing-code-scanning-alerts/resolving-code-scanning-alerts - — fetched this session: dismissing an alert requires choosing a reason, "the dismissal - comment is added to the alert timeline", it is readable as `dismissed_comment` on the - alerts API, and dismissed alerts stay in the Closed list for review. This is the canonical - shape of a *recorded* escape hatch. -- https://github.blog/changelog/2025-07-01-delegated-alert-dismissal-for-code-scanning-is-now-generally-available/ - — fetched this session: reviewers can "provide a comment when approving/rejecting alert - dismissal requests", and dismissal requests are created, listed and reviewed through - dedicated REST API endpoints — the review of a hatch use is itself recorded and readable - outside the UI. -- Local field measurement (this repo, 1.22.0): `skills/wiki-plan/scripts/plan-gate.sh:166` - passes an ungrounded decision with `[ "$basis" = "[no-wiki]" ] && continue` and records - nothing, while `skills/wiki-plan/SKILL.md:135` asks in prose for the decision to be "noted - as an ingest candidate". Against 276 non-index wiki pages, `log.md` carries exactly one - `gap` entry (2026-07-11). -- No external source states the general rule as a directive, so this stays **field-tested** - rather than verified; the GitHub precedent supports the mechanism, not the general claim. +**Candidates `f2d90d5048826870`, `fb7d73874bac6eaa`, `5f3e5eb58ec373e4`, `6e83a02b449a8dff` +(all t3-status, issue #195)** — the four rows are facets of one reusable lesson: +how to change a cited knowledge/decision record that turned out wrong. + +| Claim | Source checked | How verified | +|-------|----------------|--------------| +| Keep the reversed record, mark it superseded, reference the replacement | https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions | Live-fetched 2026-09-17; quote: "If a decision is reversed, we will keep the old one around, but mark it as superseded. (It's still relevant to know that it *was* the decision, but is *no longer* the decision.)" and "may be marked as 'deprecated' or 'superseded' with a reference to its replacement" | +| Amend-in-place vs. stand-alone successor is a real, named distinction | https://www.rfc-editor.org/rfc/rfc2223.txt §12 | Raw text read with curl; *Updates* = supplement that "cannot stand on its own", *Obsoletes* = "can be used alone, without reference to the older document" | +| Status is an optional field whose value carries the successor | https://adr.github.io/madr/ | Live-fetched; template status values `proposed / rejected / accepted / deprecated / … / superseded by ADR-0123`, marked "These are optional elements" | +| Validity status lives apart from the document's content and can change later | https://www.rfc-editor.org/faq/ | Raw page read with curl; "the status of an RFC can change", published on the info page and a status-changes list | + +Correction made during verification: the candidates' evidence cited a Stack +Overflow answer for the Obsoletes/Updates semantics, and a first fetch of +RFC 7322 §4.1.4 returned a summary that *added* definitions the RFC does not +contain. Reading the raw RFC 7322 text showed §4.1.4 only gives the header +format; the definitions are in RFC 2223 §12, which is what the page cites. +The candidates' secondary sources (ctaverna.github.io, docsio.co, the +runenwerk issue) were not needed and are not cited. + +Directive 7 of the page (log the transition under the existing `revise`-class +verb) has no external source; it is stated conditionally ("when nothing parses +the verb set mechanically") and rests on the field context of issue #195. +Confidence: **verified** (directives 1–6 are backed by the primary sources above). + +**Candidate `44e28bb8c99c1d0c` (t1-reviewer, README agents-tree line)** — not a +best-practice claim. It is a one-repo scope ruling ("add one README line, leave +README.ko.md and the sibling reviewer lines alone"). No transferable trigger or +directive; nothing to verify. **Dropped.** ## Existing-layer check -Routed via `INDEX.md` → domain `index.md` → every page whose "load when" overlapped. - -Pages read: testing-quality-tests-that-cannot-fail, testing-quality-policy-at-several-return-sites, testing-quality-completion-predicates, testing-quality-surviving-mutant-equivalence-triage, infrastructure-agent-orchestration-pane-delivery-confirmation, infrastructure-agent-orchestration-code-graph-as-orientation-layer, platforms-processes-driving-a-tui-in-a-tmux-pane, qa-document-verification-spec-document-gates, infrastructure-agent-orchestration-session-completion-gates, infrastructure-agent-orchestration-autonomous-decision-rulings - -(Directory-level scans of `wiki/testing/quality/`, `wiki/platforms/processes/`, -`wiki/infrastructure/agent-orchestration/` plus keyword sweeps for `no-wiki`, `post-merge`, -`capture-pane`/`send-keys`, and `precedence` over the whole wiki preceded these reads.) - -| Insight | Overlap found | Outcome | -|---------|---------------|---------| -| 1 precedence | `tests-that-cannot-fail` carries a co-occurring-writer edge case (two writers of one flag) and `policy-at-several-return-sites` carries per-site mutation — both are about *coverage of one site*, neither about *which of two live conditions wins* | **New page**, cross-linked to both; no conflicting directive | -| 2 pane witness | `pane-delivery-confirmation` already rules that a pane *diff* is not delivery evidence (echo direction). The new rule is the opposite direction — a stale capture *falsely confirming* a witness | **Merged** into that page (Do-this #6, 1 edge row, 1 Instead-of row, 2 sources); 1 pointer row added to `driving-a-tui-in-a-tmux-pane` | -| 3 graphify hooks | `code-graph-as-orientation-layer` already gates on freshness and its Sources line already names `hook install` post-commit/post-checkout — the hook-coverage consequence was missing | **Merged** into that page (2 edge rows, 2 sources, 1 clause on directive 1) | -| 4 escape hatch | `session-completion-gates` and `spec-document-gates` cover gate *authoring*; none covers what a gate does with its own exemptions. Keyword sweep for `no-wiki`/`escape hatch`/`knowledge gap` returned no owning page | **New page** in the existing `agent-orchestration` category | - -Conflicts flagged: none — no existing directive is contradicted. -Related links added both ways: `tests-that-cannot-fail`, `policy-at-several-return-sites`, -`completion-predicates` ↔ the new precedence page; `session-completion-gates`, -`autonomous-decision-rulings`, `spec-document-gates` ↔ the new escape-hatch page. - -Lint after the edits: `wiki-structure-checks.js` → **278 pages, 13 indexes, 0 findings**; -`wiki-lint-prohibitions.js` → no findings on any touched page (the 2 repo-wide violations it -reports are pre-existing, in `plans/` and `tests/fixtures/`). New pages are 67 and 69 body -lines; amended pages are 92, 92 and 65 — all under the 120-line cap. +Routed via `INDEX.md` → qa (document deliverables / document-verification), and +cross-checked infrastructure (agent-orchestration, where the gap-queue page +lives) and backend (api-versioning, the nearest "deprecation" page). + +Pages read: qa-document-verification-retiring-a-provisional-marker, infrastructure-agent-orchestration-escape-hatch-uses-as-a-knowledge-gap-signal, qa-document-verification-spec-document-gates, backend-common-api-design-api-versioning-and-breaking-changes + +- `grep -rli "supersed|ADR|architecture decision" wiki/` → 4 hits, none about + the lifecycle of a record: retiring-a-provisional-marker covers removing + `[추정]`/TBD markers inside one document; escape-hatch-uses covers emitting + gap rows; the other two only mention the word. +- `grep '^status:'` over the wiki → 0 pages; AGENTS.md has no lifecycle field + (issue #195 is what introduces it). No existing directive conflicts. +- Result: **new page** `wiki/qa/document-verification/superseding-a-knowledge-record.md` + (72 body lines). The four t3-status rows were merged into it rather than + ingested as four pages: supersede-vs-overwrite (D8) → Do-this 1–3, status vs. + confidence (D9) → Do-this 5, absent-means-active template line (D14) → + Do-this 6, `revise` verb (D7) → Do-this 7. +- Related links added both ways: retiring-a-provisional-marker, + spec-document-gates, escape-hatch-uses-as-a-knowledge-gap-signal. +- `wiki/qa/index.md` document-verification table +1 row; `log.md` +1 ingest entry. +- Checks after the edit: `node scripts/wiki-structure-checks.js wiki` → + 279 pages / 13 indexes / 0 findings; `node scripts/wiki-lint-prohibitions.js wiki` + → directives 75, violations 0 (bats pin unchanged at 75); + wiki-structure-checks / wiki-lint-prohibitions / wiki-lint-model-era bats → 0 failures. ## Open-PR check -Listed with `gh pr list --repo choiyounggi/dev-loop --state open --search "head:knowledge/"` — -12 open heads: #191, #190, #189, #188, #187, #186, #185, #183, #182, #181, #180, #179. -Each head was fetched and its **added** wiki lines (`git diff pr-N -- wiki/`) -grepped for `post-merge|graphify|graph.json|no-wiki|capture-pane|send-keys|precedence|knowledge gap`. - -| Candidate | Overlapping open head | Verdict | -|-----------|----------------------|---------| -| 1 precedence | none — #189's `proving-a-critical-section-is-lock-protected` and `sequential-dispatch-assumption-under-concurrency` are concurrency-window tests, not exit-condition ordering; its only `precedence` hits are Gradle property precedence (#179) | **new** | -| 2 pane witness | none — #183's single `send-keys` hit is a pointer row in a stdin-vs-send-keys edge case | **new** | -| 3 graphify hooks | #185 edits the *same page* but adds an unrelated row (`update` exits 1 on a >5,000-node HTML viz); #186 only mentions this page in an INGEST_REPORT dedup note | **new** (no content overlap; noted below as a textual merge risk) | -| 4 escape hatch | none — #189's `gate-evidence-exit-code-class` is about a gate's own exit-code classes, not about recording exemptions | **new** | - -Merge-risk note for the reviewer: **#185 and this PR both append to -`wiki/infrastructure/agent-orchestration/code-graph-as-orientation-layer.md`** (different -edge-case rows and different source bullets). Whichever lands second may need a one-hunk -textual merge; the content does not conflict semantically. +Open `knowledge/*` heads listed 2026-09-17: #205, #191, #190, #189, #188, #187, +#186, #185, #183, #182, #181, #180, #179. Each head was fetched and +`git diff origin/main origin/ -- wiki/` grepped for +`supersed|superseded_by|status: retired|decision record|obsoletes` → 0 added +lines on every head. Nearest neighbour: #186's +`model-coupled-guidance-aging-detector` — it detects pages that may have aged; +it says nothing about what to do with a refuted record, so no overlap. + +| Candidate | Verdict | +|-----------|---------| +| `f2d90d5048826870` (log verb for supersede/retire) | new | +| `fb7d73874bac6eaa` (ingest third case: page wrong as a whole) | new | +| `5f3e5eb58ec373e4` (status vs. confidence) | new | +| `6e83a02b449a8dff` (template optional status lines) | new | +| `44e28bb8c99c1d0c` (README agents-tree line) | drop — not generalizable (not a pending duplicate) | + +Note for the reviewer: issue #195 (t3-status) will itself add `status` / +`superseded_by` to AGENTS.md. This page is the general practice behind that +schema, written so it stays correct whether or not #195 has landed. ## Routing decision -| Insight | Target | New category? | -|---------|--------|---------------| -| 1 | `testing/quality/precedence-between-competing-exit-conditions.md` (**new page**) | No — `testing/quality` already owns "can this test actually fail" | -| 2 | `infrastructure/agent-orchestration/pane-delivery-confirmation.md` (**merge**), + 1 pointer row in `platforms/processes/driving-a-tui-in-a-tmux-pane.md` | No | -| 3 | `infrastructure/agent-orchestration/code-graph-as-orientation-layer.md` (**merge**) | No | -| 4 | `infrastructure/agent-orchestration/escape-hatch-uses-as-a-knowledge-gap-signal.md` (**new page**) | No — `agent-orchestration` already carries the gate-authoring pages (`session-completion-gates`, `autonomous-decision-rulings`); a `knowledge-base` category would hold one page and split gate knowledge across two places | - -Plumbing: `wiki/testing/index.md` +1 row; `wiki/infrastructure/index.md` +1 row and two -extended "load when" lines (pane-delivery-confirmation, code-graph-as-orientation-layer); -`log.md` +1 `ingest` entry. +- 4 t3-status rows → `qa / document-verification / + superseding-a-knowledge-record` (new page, existing category). The category + already owns ADR/RFC/spec document lifecycle pages + (retiring-a-provisional-marker, editing-a-gated-document), so no new + category was needed. +- 1 t1-reviewer row → no page (dropped). diff --git a/log.md b/log.md index 5a1a698..9722fe0 100644 --- a/log.md +++ b/log.md @@ -105,3 +105,4 @@ Append-only. Format: `## [YYYY-MM-DD] superseded by ` — + when nothing parses the verb set mechanically. Add a verb only when a + consumer needs to select these entries by verb. + +## Edge cases + +| Case | Then | +|------|------| +| Only one directive of a multi-directive record is refuted | Amend that directive in place and log the revision; superseding is for a record wrong as a whole | +| The successor is itself superseded later | Point each record at its direct successor; a reader follows the chain, and the lint checks each hop resolves | +| A tool loads records by glob, not through the index | Filter on the status field in that tool, or superseded guidance is loaded as current | +| The old record's id encodes a category the successor does not share | Keep the old id as is; ids are citation targets, and the pointer carries the move | +| Two records supersede one (a split) | Hold a list of successor ids, and state in each successor which part it took over | + +## Instead of + +| If you are about to | Do this instead | Why | +|---------------------|-----------------|-----| +| Delete the refuted record and create the new one | Mark it superseded, point at the successor, keep the file | Every plan or review that cited the old path becomes a dead link, and the reason for the change is lost | +| Overwrite the record's body with the opposite directive under the same id | Create the successor under a new id | Citations made under the old directive now silently assert the new one | +| Add `superseded` as one more confidence value | Add a separate status field | Confidence describes the evidence at writing time; folding validity into it erases how well the old claim was supported | +| Write `status: active` into every existing record | Treat absence as active | A key that is identical on every record carries no information and makes the migration diff the size of the corpus | + +## Sources + +- https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions — Nygard's ADR definition: "If a decision is reversed, we will keep the old one around, but mark it as superseded. (It's still relevant to know that it *was* the decision, but is *no longer* the decision.)"; a changed decision "may be marked as 'deprecated' or 'superseded' with a reference to its replacement" +- https://adr.github.io/madr/ — the MADR template carries status as optional front matter with the value form `superseded by ADR-0123` ("These are optional elements. Feel free to remove any of them.") +- https://www.rfc-editor.org/rfc/rfc2223.txt — §12 "Relation to other RFCs": *Updates* marks a supplement that "cannot stand on its own"; *Obsoletes* marks a document that "can be used alone, without reference to the older document" +- https://www.rfc-editor.org/faq/ — "the status of an RFC can change" after publication, and the status is published on the RFC's info page and a list of status changes, apart from the document text +- Field context 2026-09-17 (dev-loop issue #195): a 276-page agent wiki had no status field, so a refuted page could only be deleted, which broke the page paths recorded in earlier plan documents diff --git a/wiki/qa/index.md b/wiki/qa/index.md index 18a4e9a..bfc7ef5 100644 --- a/wiki/qa/index.md +++ b/wiki/qa/index.md @@ -42,6 +42,7 @@ Match your situation to a "load when" line; load only matching pages. | [generated-reference-drift-gates](document-verification/generated-reference-drift-gates.md) | Writing or reviewing the reference material that enumerates a closed vocabulary an agent will emit tokens from (DSL verbs, config keys, diagnostic codes, enum members) in a plugin/skill/SDK; deciding whether to hand-write that list or generate it from the owning constant; choosing what gates a generated document beyond a `--check` diff; a documented token compiles to a silent no-op instead of an error | | [retiring-a-provisional-marker](document-verification/retiring-a-provisional-marker.md) | Turning provisional markers (`[추정]`, TBD, "assumed", DRAFT) into settled statements in an ADR/RFC/spec that has been through review rounds, so the document also carries a review checklist and a round history referring to those markers; a checklist row stayed `[x]` on evidence you just deleted; a coordinator's marker count and yours disagree while you read the same file | | [editing-a-gated-document](document-verification/editing-a-gated-document.md) | Editing or rewording a document that grep/regex gates or a lint config check; a gate fails on wording whose meaning did not change; reflowing prose a test asserts as a verbatim phrase (CI red on one platform only); describing what an upstream spec says without tripping a "do not redefine it" gate; a check matches the pattern your own document quotes; recording an audit verdict inside the document that was audited; deciding which checks to re-run after editing a gated document | +| [superseding-a-knowledge-record](document-verification/superseding-a-knowledge-record.md) | A cited record (ADR, wiki page, runbook, spec section) is refuted or replaced and you are choosing between amending in place, deleting, or superseding it; adding a lifecycle field (`status`, `superseded_by`) to a record schema; deciding whether validity belongs in the confidence field; deciding whether existing records need a backfilled default status | ## environments