Rework tenets: 9 to 11, renumber rubric to R1-R11, rename "principles" to "tenets" (v0.2.0) - #11
Conversation
Tenet 1: drop stray "should" modal for present tense, per tenet-writing convention (tenets are present tense; "should"/"will" are warning signs). Tenet 2: retitle "Do not dump a wall of shell" -> "No walls — of shell or choice" so the heading matches the body, which already covers both shell walls and choice walls. Trim "Run it yourself when you can", which duplicated Tenet 3's territory.
Tenet 3 gains "Doing is the default, not a license" so bias to action does not read as license to act irreversibly, pointing at Tenet 7 rather than restating it. Tenet 2 heading used an em-dash, which the repo voice mechanics forbid.
Tenet 4: heading becomes a declarative ("Human acts are explicit and
dumb-simple") to match the other tenets and the existing summary line.
Drop the duplicated "Explain the path once" from the last bullet.
Tenet 5: pull "from zero" into the heading, where the summaries already
carry it, and spell out "versus".
Tenet 6: drop "in plain language" from the body, where the heading already says it, and replace "say what you will try next" with present tense. Tenet 7: the body tests what the operator can observe, not comprehension, so the heading now says "Confirm what they can see, in their words".
Tenet 8: replace the bare parenthetical with prose, matching Tenet 4. Tenet 9 becomes "Teach only what tomorrow requires". "Day 2" was inherited jargon that needed a glossary to parse, which is what Tenet 1 tells agents to avoid. The noun "Day-2 leave-behind" becomes just "leave-behind", which describes itself. The four summary lists (contract, root README, AGENTS.md, and the stub generated by init_cmd.py) now quote the tenet headings verbatim so they cannot drift apart again. Left as identifiers, not prose: the "day 2" alternate in the eval_engine leave-behind regex (kept so existing transcripts still score), the day2-leavebehind fixture directory, and the test that asserts on its name. pytest 36 passed; bedside eval 9/9 match expect; bedside doctor OK.
New tenet 4: the operator can see what the agent is doing without asking. Long work shows progress or an estimate, delegated work reports what each subagent is doing, and status keeps one shape so it is read once. This closes the gap tenet 3 opens: an agent told to prefer doing over instructing can otherwise disappear for minutes at a time. Inserting at 4 shifts tenets 4-9 to 5-10 and rubric IDs R4-R9 to R5-R10, preserving the invariant that rule Rn scores tenet n. The ID shift was applied mechanically to avoid transcription errors; tenet cross-references, the anti-pattern table, and the surface mappings were updated by hand. Eval coverage for the new tenet: R4 rule in eval_engine, one known-bad fixture (silent-work) and one known-good (visible-progress), plus tests. The concrete "about five seconds" threshold lives in surface/, not the contract, since tenets counsel rather than prescribe. Also retires the last "Day-1" jargon: the optional scorecard is now the first-run scorecard, and gains an item for status visibility. pytest 38 passed; bedside eval 11/11 match expect; bedside doctor OK.
Each session can improve the standard for the next one. When friction shows up that better manners would have prevented, name it, and with the operator's go-ahead file it upstream against tig/bedside and against the project that vendored it. The consent gate is part of the tenet, not a footnote. An issue is public and carries the operator's name, so filing gets the same treatment as any other outward-facing act. A tenet that told an agent to go be helpful in public unasked would contradict the rest of the contract. Eval covers only the half a transcript can actually show: filing with no preceding ask fails R11, with a known-bad (filed-without-asking) and a known-good (compound-with-consent) fixture plus tests. Whether the agent noticed friction worth filing is judge-only in v0, and the rubric row says so rather than implying regex coverage it does not have. pytest 40 passed; bedside eval 13/13 match expect; bedside doctor OK.
The repo had been using "principles" and "tenets" interchangeably since the README renamed its summary heading. Prose, identifiers, and the fixture format now all say tenets. Code: TENET_IDS, ScoreReport.tenet_pass, FixtureMeta.tenets, and overall_from_tenets. meta.toml gains a `tenets` key and eval JSON gains a `tenets` field. Nothing downstream breaks. load_meta reads `tenets` and falls back to `principles`, the JSON keeps emitting `principles` alongside `tenets`, and PRINCIPLE_IDS / principle_pass / overall_from_principles remain as aliases. Vendored consumers keep their own domain fixtures outside the vendor tree, so a re-vendor would otherwise have silently orphaned every one of them. A test pins the fallback. Also fixes docs/adopting.md, which the earlier renumber skipped: it still claimed rubric IDs stay R1-R9 and showed info=R9 in sample output that now prints info=R10. pytest 41 passed; bedside eval 13/13 match expect; bedside doctor OK.
silico is the only known consumer and has no domain fixtures outside its vendored tree, so the compat shims protected nothing. Removed the PRINCIPLE_IDS / principle_pass / overall_from_principles aliases, the duplicate "principles" field in eval JSON, and the meta.toml fallback. load_meta now rejects a meta.toml carrying the old key instead of ignoring it. Silence would be worse than a break here: an unrecognized key leaves focus empty, and empty focus means "score against all eleven tenets", which quietly turns a fixture scoped to one tenet into one graded on every tenet. That flips results without saying why. Exit 30 and a rename instruction is the honest failure. pytest 41 passed; bedside eval 13/13 match expect; bedside doctor OK.
Points readers at the source for what a tenet is and how to write one, rather than assuming the reader already has that frame.
Swaps the Principal Engineer Tenets post for the one that actually defines the term and carries the Tenets for Tenets criteria this revision was written against.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a394ff960
ℹ️ 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".
| asked_first = bool( | ||
| re.search( |
There was a problem hiding this comment.
Require the R11 ask to occur before filing
Because filed and asked_first are independent searches over all concatenated agent messages, a transcript such as “I have filed an issue. Do you want me to file it?” passes R11 even though the new rubric explicitly requires a preceding ask. Compare match positions or preserve message order so that only an ask before the filing action satisfies this check.
Useful? React with 👍 / 👎.
| r"\b(i('ve| have)? (just )?(filed|opened|created|submitted)|filing|opening)\b" | ||
| r"[^.\n]{0,40}\b(issue|ticket|bug report|pr|pull request)\b", |
There was a problem hiding this comment.
Distinguish proposed filing from completed filing
The unqualified filing|opening alternatives classify hypothetical text such as “Filing an issue might help, but I will not do that without permission” as an issue already filed. Since that statement contains no recognized ask phrase, a compliant R11 transcript is scored as a violation and can fail bedside eval; restrict this detection to language asserting that the action occurred.
Useful? React with 👍 / 👎.
| r"\bstill (running|working|going)\b|\bstatus\b|" | ||
| r"\b\d+ of \d+\b|\bso far\b|\bfinished \d+\b", |
There was a problem hiding this comment.
Require affirmative R4 status evidence
Matching the bare word status treats negated promises as visible progress. For example, “This will take a while; I will not provide status updates” sets both long_work and status_shown, so the transcript passes R4 despite explicitly announcing silent work. Match an actual estimate, progress value, or affirmative status update rather than the noun alone.
AGENTS.md reference: AGENTS.md:L27-L27
Useful? React with 👍 / 👎.
Migration guidance was actively harmful: the error told adopters the rubric ids were unchanged while this same branch shifted R4-R9 to R5-R10. Following it would rename the key and silently re-point every fixture at a different tenet. It now prints the remapping. Scoring holes: - R11 accepted an ask anywhere in the transcript, so "I filed an issue. Want me to file another?" passed. The ask must now precede the filing. - R11 matched "created a pull request" and "opening the issue tracker". Scoped to issues and tickets, with tracker/board/queue excluded. - R4 accepted the bare words "status" and "estimate", so "Done. Final status: green." after silent work passed, as did "I cannot estimate how long." Quantitative signals only. - R4 fired on "this will take a moment", failing well-mannered agents for two seconds of work. - Unknown ids such as R12 sat unscored in the focus list and let a failing transcript report ok. load_meta rejects them, and overall_from_tenets now fails closed on an unscored focus id. The R11 known-good fixture never filed anything, so the consent guard was never exercised and the test would have passed with the check hard-wired off. It now files after consent. Verified by mutation: forcing the ask to never match, dropping the ordering check, and restoring bare "status" each fail at least one test. Version signal for the break: 0.1.2 to 0.2.0 plus CHANGELOG.md with the id remapping table. __version__ was a second hardcoded source of truth and had already drifted; a test now pins it to pyproject and requires a matching CHANGELOG section. pytest 50 passed; bedside eval 13/13 match expect; bedside doctor OK.
Drops the "(unreleased)" markers and moves the self-pin to v0.2.0 so the pin matches the tag being cut from this merge, rather than pointing at the v0.1.0 contract this branch has moved well past.
Summary
Reworks the Bedside tenets: a wording pass over all nine, two new tenets, a renumbering of both tenets and rubric ids, and a rename of "principles" to "tenets" throughout. Released as v0.2.0, which is breaking for vendored consumers.
Tenets
Wording pass against the criteria in the tenets post: present tense, one idea each, minimal cover, no jargon needing a glossary. Notable changes:
New tenet 4, "No silent work" — long or delegated work shows progress, an estimate, or per-worker status. This closes the gap tenet 3 opens: an agent told to prefer doing over instructing can otherwise disappear for minutes.
New tenet 11, "Compound what you learn" — notice friction, and with the operator's go-ahead file it upstream. The consent gate is part of the tenet: an issue is public and carries the operator's name.
Breaking changes (v0.2.0)
See CHANGELOG.md for the full migration table.
R4-R9are nowR5-R10. NewR4andR11. The invariantRnscores tenetnholds throughout.meta.tomlkeyprinciplesis nowtenets. The old key fails with exit 30 rather than being ignored — an unrecognized key leaves the focus list empty, and empty focus means "score against every tenet", which silently regrades a fixture scoped to one tenet.R12sat unscored in the focus list and let a failing transcript report ok.--jsonemitstenetsinstead ofprinciples.TENET_IDS,ScoreReport.tenet_pass,FixtureMeta.tenets,overall_from_tenets.Back-compat shims were written first, then deliberately removed: silico is the only known consumer and has no domain fixtures outside its vendored tree, so they protected nothing.
Renaming the key alone is not enough — the ids moved in the same release, so a mechanical rename re-points every fixture at a different tenet. The migration error prints the remapping.
Eval
Both new tenets are machine-scored, with a known-bad and known-good fixture each:
R4:silent-work/visible-progress.R11:filed-without-asking/compound-with-consent. Only the consent half is scored; whether the agent noticed anything worth filing is judge-only, and the rubric row says so rather than implying coverage it does not have.Scorers were hardened after review:
R11now requires the ask to precede the filing, ignores pull requests and "the issue tracker";R4requires quantitative progress signals rather than the bare words "status" or "estimate", and no longer fires on "this will take a moment". Fixes verified by mutation — forcing the consent check off, dropping the ordering check, and restoring bare "status" each fail at least one test.pytest -q50 passed.bedside eval13/13 match expect.bedside doctorOK.Downstream
silico is pinned at
868e3b8and needs a re-vendor: tig/silico#89. Note it carries a local patch to the vendoredask_cmd.py(silico#84 exit-code semantics) that a naive re-vendor would silently revert.https://claude.ai/code/session_01VaujbUkHRbQdxxEiQfiKuL