Skip to content

docs: describe loopwright by its principles, not its stack (#13) - #17

Merged
SamuelDenani merged 9 commits into
feat/rfc-5-core-principlesfrom
task/13-principles-first-identity
Oct 7, 2026
Merged

SamuelDenani merged 9 commits into
feat/rfc-5-core-principlesfrom
task/13-principles-first-identity

Conversation

@SamuelDenani

Copy link
Copy Markdown
Owner

What and why

loopwright described itself through its stack and its directory layout in the four
places that carry its identity. This makes the process opinion lead and the stack
follow, so the source repo and every repo that adopts it tell the same story that
docs/loopwright/principles.md (landed in #11) tells.

The most consequential of the four is .loopwright/claude-md-section.md.
install.sh:30 syncs it into every host repo and install.sh:53-63 splices it into
that repo's CLAUDE.md between the marker comments — it is how loopwright introduces
itself to everyone who adopts it, and it overwrites each adopter's marker region on
their next install run. This repo's own CLAUDE.md marker region is that block
(verified byte-identical), so that edit is one text applied twice and guarded by a
byte-identity sync check.

Part of #13

Spec: docs/specs/issue-13.md

The one line whose truth value changed

Everything else here is reframing. README.md:142-143 was an actual correction:

Two rules hold the whole thing together: the gate is the only source of truth for "done", and merging is always the human's decision.

P8 makes the merge half a default that a host can opt out of, so the absolute claim
was wrong. It now reads:

Two rules hold the whole thing together: "done" is the gate's verdict, never the judgement of whoever merges, and an irreversible action needs a human unless automating it has been explicitly opted into — loopwright ships no such opt-in today, so nothing in the harness merges. Both are stated in full in docs/loopwright/principles.md (P2 and P8).

P8's opt-in knob does not exist in code yet (RFC #5 records this in its Risks), so
the text states the rule without naming a config key, and says plainly that no opt-in
ships today. "Nothing in the harness merges" was verified against the code, not just
the doc: no gh pr merge, auto-merge or merge_method call exists under .claude/,
.github/, .loopwright/scripts/, install.sh or setup.sh, and
.claude/skills/babysit-pr/SKILL.md:56 reads "Merging is the user's decision — never
merge.
"

The second site of that absolute rule is docs/loopwright/loop-harness.md:66, which
belongs to #12, not to this PR.
A reader who greps for the old phrasing will still
find it there until #12 lands — this branch is not half-finished.

Nothing factual was removed, with that one exception

Every requirement fact survives; it just stops being the identity:

Fact Still stated at
Node ≥ 20.11, and a package.json is required README.md:181
npm, pnpm and yarn all work README.md:117, :183
Engine at .loopwright/scripts/, tests at .loopwright/tests/ CLAUDE.md:6
cd .loopwright && npx vitest run runs them CLAUDE.md:7 (verbatim)
The layer is vendored under .loopwright/ .loopwright/claude-md-section.md:6
RFC-driven issues, an agentic execution loop, a CI quality gate .loopwright/claude-md-section.md:7

How "leads with the process opinion" was made checkable

So this was not a matter of taste, each rewritten lead had to pass a literal test: the
first sentence names a concrete opinion, and does not contain the stack/mechanism
words for that site before the opinion appears. docs/loopwright/quality-gate.md:3-5
was the tone to match. All three leads scored FAIL before and PASS after.

Plan recap, with per-step commits

Step What Commit
1 README identity leads — lead, ## Your toolchain is a detail, the :91 clause, the :173 parenthetical c01c0ee
2 README "Two rules" reconciled with P2/P8, principles.md row added first in "How it's wired" be9571f, ab9ee43
3 The shared adopter block, in both files at once da0bf75
4 CLAUDE.md:1-6 preamble — a separate site, above the marker 27edb2b
5 package.json description only abf29b0
6 Requirement sweep, sync re-check, path guard, one gate run —
— Final-review fixes c60d8d4, 611bc5f

CLAUDE.md holds two independent texts and only one is shared, which is why steps
3 and 4 are separate: :1-6 is the preamble above <!-- loopwright:start -->, unique
to this repo and shared with nothing; the marker region is the injected block. An
earlier review missed the preamble, so it got its own step.

Rulings I made

Recorded here because this is the only place they reach a human.

  1. README.md:141-144 restates P1 and I left it. The paragraph "State lives in
    artifacts — the refined RFC on the issue, a committed spec in docs/specs/, one
    commit per plan step, the PR conversation…" duplicates P1's second clause. Task: Strip opinions from loop-harness.md, leaving mechanics #12's
    orchestrator found it; it is in my file but outside my acceptance criteria. My plan
    was already accepted and committed and steps were running when it surfaced, so I
    declined to re-scope mid-execution. Follow-up issue wanted. It is also stricter
    than the harness actually is — /grill-rfc keeps its task spine and sub-issue
    drafts session-scoped and uncommitted, with no carve-out stated.
    If wrong: one duplicated statement of P1 survives after both Task: Strip opinions from loop-harness.md, leaving mechanics #12 and Task: Describe loopwright by its principles, not its stack #13 merge,
    and a reader may believe the harness commits more state than it does. The fix is a
    ~4-line follow-up in a file no other task owns; re-scoping mid-run risked a
    plan/spec mismatch across five remaining steps.

  2. The spec's propagation command was denied by a permission classifier; I accepted a
    verified equivalent.
    awk … > CLAUDE.md.tmp && mv CLAUDE.md.tmp CLAUDE.md was
    refused as irreversible local destruction. The coder did not request a permission
    rule, re-issue it through another tool, or delegate it — it ran the installer's awk
    verbatim to a temp file, applied that content, and proved byte-identity. I
    re-verified independently
    : running install.sh's own splice to a scratchpad file
    and diffing gives zero difference, so CLAUDE.md is exactly what the installer
    produces. I did not run the blocked command myself.
    If wrong: an adopter's next install could produce a different CLAUDE.md than this
    repo ships. Mitigated by running the installer's actual awk program, with its actual
    marker literals, against the real section file.

  3. I treated a dropped "today" as a failed verification, not a deferrable minor.
    The spec mandates "ships no such opt-in today" and the first Step 2 text omitted
    it. Bare present tense reads as a standing commitment never to automate merging —
    the inverse of P8. Sent back for one fix round (ab9ee43).
    If wrong: one round-trip spent on a single word. Had I deferred it, the README
    would have asserted the opposite of the principle this RFC exists to state.

  4. CLAUDE.md:5 was fixed because it contradicted the doc it cites. "The engine
    that enforces them lives in .loopwright/scripts/" attributed all twelve
    opinions to that directory, but principles.md:175-176 says "nothing under
    .loopwright/scripts/ depends on Claude, agents, skills or sessions" — P1, P6, P8,
    P9, P10 and P11 are enforced under .claude/ or not yet at all. The clause was new
    in this branch, so not inherited. Now reads "Its engine lives in …" (c60d8d4).
    If wrong: an agent asking what enforces test-first is sent to the wrong directory,
    in the first file every agent in this repo reads.

  5. I left four minors the final review voted to leave. See below.

  6. No native task list exists in this background session, so the ledger plus this PR
    body are the whole record of progress.
    If wrong: the user loses a live task-list view mid-run; the delivered diff is
    unaffected.

Deferred minors, consciously left

  • README.md:93-94 — "loopwright fixes the metric vocabulary and the verdict, never
    which tool measures each metric" is universally quantified, but 3 of 5 collectors ship
    exactly one adapter (tsc, npm-audit, jscpd); real choice exists only for lint
    and tests. Accurate as a P12 boundary claim, and the adapter table immediately below
    is the disclosure.
  • README.md:146-147 — the gate half compresses P2 to its first sentence and omits
    "and review findings resolved". Not a regression (the old text had the identical gap),
    and the sentence signposts the compression by pointing at P2 and P8 in full.
  • README.md:149 — "the harness" is not defined in README.md, whose own word is
    "the loop". Vocabulary preference; "harness" is what principles.md:110-113 uses.
  • package.json:4 — the old description's explicit "a CI quality gate that agents
    cannot cheat
    " is now implied by "green must be earned" rather than stated. Not on
    the spec's must-survive list, and package.json is "private": true, so this string
    is never published.

Two further items were examined and ruled not defects: the shared block's
.loopwright/ location claim is loose (the loop ships in .claude/, CI in .github/)
but is byte-preserved from the pre-change text and is a fact the spec protects; and
"a committed baseline" is briefly untrue between install.sh and setup.sh, before a
host records one.

Verification

  • Gate: passed — 2 warnings, 6 improvements, identical to the pre-change baseline,
    confirming no metric moved. Both warnings are pre-existing and not from this branch:
    typecheck collector unconfigured, and audit.high = 2 (brace-expansion,
    js-yaml). No audit.ignore entry was added — both have upstream fixes and
    CLAUDE.md forbids ignoring an advisory that does. .loopwright/baseline.json and
    .loopwright/config.json are untouched.
  • Sync check IN-SYNC, and CLAUDE.md is byte-identical to install.sh's own awk
    output.
  • Scope: exactly five paths — README.md, CLAUDE.md,
    .loopwright/claude-md-section.md, package.json, docs/specs/issue-13.md.
    docs/loopwright/loop-harness.md does not appear; Task: Strip opinions from loop-harness.md, leaving mechanics #12 owns it and was executing
    against it in parallel, and the no-overlap guarantee is what made that safe.
  • package.json changed only description (structural compare: key order preserved,
    no other field differs).
  • No test was written. .loopwright/config.json scopes sources.roots to .mjs
    under .loopwright/scripts and .loopwright/tests, so markdown and one JSON string
    move no metric; a vitest case asserting on prose would itself be a defect. Each step
    substituted a runnable check with recorded before/after output instead.

🤖 Generated with Claude Code

SamuelDenani and others added 9 commits October 7, 2026 19:23
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…les doc (#13)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ries (#13)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…13)

The preamble said "The engine that enforces them lives in
`.loopwright/scripts/`", attributing enforcement of all twelve opinions to
that directory one line after citing the doc that denies it:
`docs/loopwright/principles.md:175-176` states the engine has zero coupling
to Claude, agents, skills or sessions. Six of the twelve `enforced by:`
pointers live under `.claude/`, so an agent following this line to find what
enforces test-first would find nothing there.

"Its engine lives in" drops the false attribution and also resolves the
sentence's double "them" (the opinions, then the tests).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The old lead's "a CI quality gate ... plus the loop that feeds it" was its
only statement that the product has two halves, and roughly half the README
is about the loop half. Dropping it left `README.md:131` ("The gate is the
enforcement half. The other half is how work reaches it:") introducing that
duality cold.

Sentence 2 now carries the category fact, so sentence 1 stays the opinion and
the lead still carries the committed baseline, the earned-vs-bought question,
and the verdict as a comment an agent can act on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

✅ Quality gate passed

commit 6860074 · baseline ece7656 · 2 warning(s) · 6 improvement(s) 📈

⚠️ 2 warning(s) — not blocking
Check Baseline Now Verdict
⚠️ TypeScript errors — n/a collector not configured — see docs/loopwright/quality-gate.md
⚠️ High advisories 0 2 regressed 2 (tolerance 0)

High advisories

  • brace-expansion — high: brace-expansion: Quadratic-time expansion of the {a},b} rewrite causes CPU denial of service · fix available — upgrade it
  • js-yaml — high: js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources · fix available — upgrade it
📊 All metrics
Check Baseline Now Verdict
✅ Failing tests 0 0 holding
✅ Failing test suites 0 0 holding
⚠️ TypeScript errors — n/a collector not configured — see docs/loopwright/quality-gate.md
✅ Lint errors 0 0 holding
✅ Lint warnings 0 0 holding
✅ Critical advisories 0 0 holding
⚠️ High advisories 0 2 regressed 2 (tolerance 0)
✅ Suppressed advisories 0 0 holding
📈 Line coverage 84.67% 85.01% improved 0.34%
📈 Branch coverage 78.93% 79.44% improved 0.51%
📈 Function coverage 89.65% 89.71% improved 0.06%
📈 Statement coverage 85.01% 85.41% improved 0.40%
📈 Duplicated code 0.90% 0.88% improved 0.02%
✅ Highest function complexity 14 14 holding
📈 Average function complexity 1.81 1.80 improved 0.01
✅ Oversized files 0 0 holding
✅ Skipped tests 0 0 holding
✅ Focused tests (.only) 0 0 holding
✅ Tests with no assertion 0 0 holding
✅ Coverage-ignore hints 1 1 holding
✅ Type suppressions (@ts-ignore etc.) 2 2 holding
✅ Inline lint suppressions 2 2 holding
✅ Empty catch blocks 0 0 holding

📈 This PR improves 6 metric(s). Run node .loopwright/scripts/quality-gate.mjs --update-baseline and commit .loopwright/baseline.json to lock the gain in.


Generated by .loopwright/scripts/quality-gate.mjs · reproduce locally with node .loopwright/scripts/run-report.mjs --all && node .loopwright/scripts/quality-gate.mjs · full reports are in the workflow artifacts.

@SamuelDenani
SamuelDenani marked this pull request as ready for review October 7, 2026 23:39
@claude

claude Bot commented Oct 7, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@SamuelDenani
SamuelDenani merged commit 4a9f175 into feat/rfc-5-core-principles Oct 7, 2026
4 checks passed
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.

1 participant