docs(mdcode): restructure section 7 of the actions guide for narrative - #435
Merged
Merged
Conversation
Section 7 was ordered by machinery: resolve/bind/apply, then how rows are found, then guards. The payoff of the whole guide -- the constraint declared in section 2 finally stopping a write -- arrived 150 lines in, behind a six-name list of which field names count as identifying and a paragraph on type-driven predicate dropping. The two judge subsections were 58% of the section and carried nine bold notes between them. It now runs on one question: what happens when somebody tries the write. Three kinds of rule in escalating order, each shown allowing or stopping a real call. ### What a run does resolve, bind, apply -- figure 3 ### When a rule stops the call an expression guard refuses ### When the rule is a sentence --judge, the verdict, the reason ### When the judge needs a fact --judge-reads-store ### Which rows a call touches demoted to reference at the end Reference detail is cut to what changes something a reader writes. The six identifying field names become one sentence naming the pattern; the judge's read caps stop being quotable numbers; the SELECT-wrap internals go. Somebody whose field is called `label` can no longer confirm from the guide that it counts, which is the accepted cost. Paragraphs that argued rather than informed are gone: the defence of refusing over running unchecked, the note explaining why kcmd is not an approver, and the reason given for showing all three `on_violation` branches from one rule. The judge subsections carry seven bold notes where they carried nine. 394 -> 340 lines, 2250 -> 1757 prose words. 129 of those lines are fenced blocks, which is the floor the section cannot go below. Three headings are renamed, and the six inbound links to them are updated: `#a-guard-settled-in-words` -> `#when-the-rule-is-a-sentence` (actions.md 414 and 1388, demo/semantic-model/agent/README.md 215), `#a-guard-that-reads-a-row` -> `#when-the-judge-needs-a-fact` (actions.md 461, reference.md 89), `#why-a-guarded-action-is-refused` -> `#when-a-rule-stops-the-call` (actions.md 1371). `#7-run-it` is unchanged. Every anchor link under toolbox/mdcode resolves: 204 links across 32 pages. Fenced blocks move but do not change. One is dropped: the resolution SQL, which figure 3 already shows. Every other fenced line is byte-identical.
libei
force-pushed
the
actions-guide-s7-narrative
branch
from
September 16, 2026 06:35
986f497 to
61c1596
Compare
libei
marked this pull request as ready for review
September 16, 2026 14:19
This was referenced Sep 16, 2026
libei
added a commit
that referenced
this pull request
Sep 16, 2026
…rgument (#439) Section 8 ran a 152-line unheaded preamble (43% of the section) before its first heading, and the reader met `[NOT RUNNABLE]` 215 lines before learning why it was there. The section was doing two jobs in one stream -- making an argument and serving as the reference for the derivation -- which want opposite orders. Six headings, each with one job. The preamble drops to 15 lines because the derivation and its three products are named up front. Also corrects one claim (`kcmd agent tools` does resolve the store its profile binds), carries a writing pass over the result, and updates the section 7 cross-reference renamed by #435. All five fenced blocks are byte-identical: 0 lines removed, 0 added.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Section 7 of the actions guide, restructured for narrative. No new claims about
the runtime: this is reordering, cutting, and two accuracy repairs made while
compressing.
What was wrong
The section was ordered by machinery. Resolve/bind/apply, then how rows are
found, then guards. The payoff of the whole guide — the constraint declared in
section 2 finally stopping a write — arrived 150 lines in, behind a six-name
list of which field names count as identifying and a paragraph on type-driven
predicate dropping.
### Why a guarded action is refused, the actual message,got 26 lines;
### Which rows a call touchesgot 71.The two judge subsections were 58% of the section and carried nine bold notes
between them, each a true fact and collectively a wall.
What it is now
One question: what happens when somebody tries the write. Three kinds of rule
in escalating order, each shown allowing or stopping a real call.
### What a run does### When a rule stops the call### When the rule is a sentence--judge, the verdict, the reason### When the judge needs a fact--judge-reads-store### Which rows a call touchesTable: the new order of section 7 and the question each subsection answers.
The opening is untouched — it was settled in #434.
394 → 340 lines, 2250 → 1757 prose words. 129 of the remaining lines are fenced
blocks, which is the floor.
Reference detail cut to what changes something a reader writes
name,full_name,fullname,title,label,display_name, case-insensitive, first-declared wins) become onesentence naming the pattern. Accepted cost: somebody whose field is called
labelcan no longer confirm from the guide that it counts.each capped in rows and in the size of a value" rather than 4 / 20 / 200.
SELECT * FROM (...) AS judge_read LIMIT 21wrap goes. What stays is theconsequence: a write can still land through a function on PostgreSQL, and
nothing confines a read to the tables your model binds.
shows it.
Paragraphs that argued rather than informed
Three, all the class #434 was cut back for:
model declares would be worse than no runtime at all…") → one clause;
as the end of the matter" → dropped, the quoted escalate sentence speaks for
itself;
rules showing one each" → "so one rule shows all three branches".
Also dropped: the paragraph explaining why the demo names no expression in
guards, which section 2 already covers, and the sentence defending figure 3'sshorter lookup.
The judge subsections now carry seven bold notes where they carried nine.
Two repairs found while compressing
**Keep the rule settleable from a few rows.**briefly read "A judge that stillcan't tell answers that the rule doesn't hold". The source instructs the judge
to answer that way; it does not guarantee it. Restored to "is instructed to
answer".
**The rule is settled before the transaction opens.**ended "A rule abouteither belongs in an
expression", where either pointed at a state and arace. Both are now named.
Claims checked against the source
guardshas a say in a call" — broadened from "can refuse a call like this"run_action.ts:37-38: "a rule takes effect where something references it, andguardsis that reference for an action"run_action.ts:492filterson_violation: warnout of the guard set before the refusal testprimary_keybinds" (singular)run_action.ts:995: the key predicate is added only whenkeyColumns.length === 1run_action.ts:990-991and the composite-key error at:1012-1017Table: each compressed claim and the source that settles it.
Three headings renamed, six inbound links updated
#a-guard-settled-in-words#when-the-rule-is-a-sentencedemo/semantic-model/agent/README.md215#a-guard-that-reads-a-row#when-the-judge-needs-a-fact#why-a-guarded-action-is-refused#when-a-rule-stops-the-callTable: the renamed anchors and every link that points at them.
The demo README link was outside the
docs/tree my first grep covered, and across-file checker found it. Every anchor link under
toolbox/mdcodenowresolves — 204 links across 32 pages — and a repository-wide grep for the old
anchors returns nothing.
#7-run-itis unchanged, so the four links to it and reference.md:80 areuntouched. The in-section self-reference at the end of
### When the judge needs a factbecame "the race described above", since the two subsections are nowadjacent.
Fenced blocks
Blocks move, and one is dropped. Every other fenced line is byte-identical to
fa683d6:84 fence markers → 82.
Checks
Prose wrap ≤ 80: clean. Internal anchors: 36 headings, 0 broken links. Banned
constructions: 0. "we": 0. Sentences over 40 words in section 7: 4 → 1, and
that one is the checker reading a lowercase
kcmdas mid-sentence rather thanas the start of a new one.
Rebased onto
fa683d6(#433, section 8). Two conflicts, both where #433 revisedthe same §8 sentences my anchor swap touched; #433's prose was kept and only the
anchor changed.
Interaction with #436 — one link, whichever merges second
#436 restructures section 8 and is branched off the same
fa683d6. Merging bothleaves one dead anchor, and git reports no conflict at the site:
The sentence
[refusal from section 7](#why-a-guarded-action-is-refused) arrives here insteadsits atfa683d6line 1443 and at07a54bcline 1361 — #436relocated it within section 8, so git can't match this PR's rename to it and
keeps #436's copy with the old anchor. The one conflict git does report is
elsewhere and resolves by taking #436's side.
Every other inbound link survives: the sites at
07a54bcactions.md 414, 461,1263, 1497, reference.md 89 and
demo/semantic-model/agent/README.md215 areunmoved from main, so the rename applies automatically. The reverse direction is
clean — nothing here points at the section 8 anchors #436 renames.
Whichever lands second updates that one anchor to
#when-a-rule-stops-the-call.Reported to the session that owns #436.
Still true after this PR
Section 7 says "Nothing in kcmd evaluates an expression against live data
today". #421 falsifies that sentence when it lands.
The
action listblock still showspayments/TransferFundsand was builtfrom the guide's own fenced YAML rather than captured from a live run. Worth
diffing against one; not in this PR.