Skip to content

docs(mdcode): restructure section 7 of the actions guide for narrative - #435

Merged
libei merged 1 commit into
GoogleCloudPlatform:mainfrom
libei:actions-guide-s7-narrative
Sep 16, 2026
Merged

libei merged 1 commit into
GoogleCloudPlatform:mainfrom
libei:actions-guide-s7-narrative

Conversation

@libei

@libei libei commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

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 touches got 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.

subsection what it answers
### What a run does resolve, bind, apply — figure 3
### When a rule stops the call a non-advisory 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

Table: 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

  • The six identifying field names (name, full_name, fullname, title,
    label, display_name, case-insensitive, first-declared wins) become one
    sentence naming the pattern. Accepted cost: somebody whose field is called
    label can no longer confirm from the guide that it counts.
  • The judge's read caps stop being quotable numbers — "a small budget of reads,
    each capped in rows and in the size of a value" rather than 4 / 20 / 200.
  • The SELECT * FROM (...) AS judge_read LIMIT 21 wrap goes. What stays is the
    consequence: a write can still land through a function on PostgreSQL, and
    nothing confines a read to the tables your model binds.
  • One fenced block is dropped, the resolution SQL, because figure 3 already
    shows it.

Paragraphs that argued rather than informed

Three, all the class #434 was cut back for:

  • the defence of refusing over running unchecked ("Quietly ignoring a rule your
    model declares would be worse than no runtime at all…") → one clause;
  • "Nothing in kcmd is an approver, and a refusal that left this out would read
    as the end of the matter" → dropped, the quoted escalate sentence speaks for
    itself;
  • "because one rule showing all three branches is easier to follow than three
    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's
shorter 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 still
can'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 about
either belongs in an expression", where either pointed at a state and a
race. Both are now named.

Claims checked against the source

claim source
"Only a constraint the action names in guards has 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, and guards is that reference for an action"
"a call that a non-advisory expression guards" run_action.ts:492 filters on_violation: warn out of the guard set before the refusal test
"comparing the input against the column your entity's primary_key binds" (singular) run_action.ts:995: the key predicate is added only when keyColumns.length === 1
"A name is also the only way to reach an entity keyed on several columns" run_action.ts:990-991 and the composite-key error at :1012-1017

Table: each compressed claim and the source that settles it.

Three headings renamed, six inbound links updated

old anchor new anchor sites
#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

Table: the renamed anchors and every link that points at them.

The demo README link was outside the docs/ tree my first grep covered, and a
cross-file checker found it. Every anchor link under toolbox/mdcode now
resolves — 204 links across 32 pages — and a repository-wide grep for the old
anchors returns nothing.

#7-run-it is unchanged, so the four links to it and reference.md:80 are
untouched. The in-section self-reference at the end of ### When the judge needs a fact became "the race described above", since the two subsections are now
adjacent.

Fenced blocks

Blocks move, and one is dropped. Every other fenced line is byte-identical to
fa683d6:

-```sql
-SELECT account_id FROM account
-WHERE account_id = @ref0 OR name = @ref LIMIT 2
-```

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 kcmd as mid-sentence rather than
as the start of a new one.

Rebased onto fa683d6 (#433, section 8). Two conflicts, both where #433 revised
the 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 both
leaves one dead anchor, and git reports no conflict at the site:

MISSING ANCHOR docs/semantic-model/actions.md -> actions.md#why-a-guarded-action-is-refused
32 pages, 204 anchor links, 1 broken

The sentence [refusal from section 7](#why-a-guarded-action-is-refused) arrives here instead sits at fa683d6 line 1443 and at 07a54bc line 1361 — #436
relocated 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 07a54bc actions.md 414, 461,
1263, 1497, reference.md 89 and demo/semantic-model/agent/README.md 215 are
unmoved 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 list block still shows payments/TransferFunds and was built
from the guide's own fenced YAML rather than captured from a live run. Worth
diffing against one; not in this PR.

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
libei force-pushed the actions-guide-s7-narrative branch from 986f497 to 61c1596 Compare September 16, 2026 06:35
@libei
libei marked this pull request as ready for review September 16, 2026 14:19
@libei
libei merged commit 985c75b into GoogleCloudPlatform:main Sep 16, 2026
7 checks passed
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.
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