Skip to content

docs(agents): add KO/ViewComponent guidelines from review#348

Merged
brianmhunt merged 10 commits intomainfrom
docs/llm-guidance-mb-imports
Apr 21, 2026
Merged

docs(agents): add KO/ViewComponent guidelines from review#348
brianmhunt merged 10 commits intomainfrom
docs/llm-guidance-mb-imports

Conversation

@brianmhunt
Copy link
Copy Markdown
Member

@brianmhunt brianmhunt commented Apr 20, 2026

Summary

Ports architectural review guidelines from a downstream MinuteBox CodeRabbit review config (NetPleadings/MinuteBox#9518) back upstream into TKO's public LLM-facing docs. Rules reworded for TKO primitives (LifeCycle, BindingHandler, ComponentABC, ko.subscribable) β€” no app-specific references.

Skipped MB rules 4 (method/file size), 5 (empty catch), and style nits β€” not framework-level.

Credit

Guidelines originate from NetPleadings/MinuteBox#9518 by @jameskozlowskimb with input from @ctcarton. Ported upstream and reworded for TKO primitives.

Changes

tko.io/public/llms.txt

3 new Gotchas bullets: flat JSX attrs vs params={{…}} wrapper, no observable/computed/subscribe inside a computed evaluator, || undefined for binary HTML attrs. Caveman-compressed. New /agents/process.md pointer added to agent-docs list.

tko.io/public/agents/contract.md

  • DOM Mutation Containment β€” DOM APIs belong inside BindingHandler subclasses; explicit violation list + safe zones.
  • Component Design: Binding Handlers and Component View Models β€” narrow BH scope (one DOM task), component-as-renderer-only.
  • Component Communication via ko.subscribable β€” pub/sub over observable-of-function for imperative commands between components and binding handlers.

tko.io/public/agents/guide.md

  • Observables vs computed dependency management β€” this.computed / this.subscribe preference in LifeCycle subclasses; never create reactive primitives inside a computed evaluator.
  • Reactive styling β€” two example patterns (computed className, data-attr + CSS selector), not a mandate; codebases should pick one and stay consistent.
  • JSX scope rule β€” JSX inside components / top-level tko.jsx.render only, not orphan utility modules.
  • Component params in JSX β€” each param as its own attribute.
  • 3 new Gotchas bullets: null (not false) for empty HTML computeds; binary attr || undefined; prefer named computed variables over inline.

tko.io/public/agents/process.md (new)

  • Never ship docs that reference things that don't exist on the target branch β€” mandatory pre-staging checklist.
  • Adversarial review is mandatory β€” how-to, in-scope/out-of-scope list, audit-trail format.
  • Credits section naming the MinuteBox PR.

AGENTS.md

  • One-line mandate + link for "Never ship broken references" (full rule in process.md).
  • One-paragraph mandate for adversarial review (in-scope trigger, dark-factory motivation, audit-trail pointer); full how-to in process.md.
  • Failure-modes list gains a bullet for docs referencing non-existent packages/APIs/spec paths.
  • Net line delta vs main: ~+7 (down from ~+55 before the extract).

tko.io/public/agents/verified-behaviors/*.md

Left untouched. These files are regenerated from packages/*/verified-behaviors.json on every build, so hand-edits would have been wiped at CI time.

Verification

  • bun run build in tko.io/: 65 pages, clean build.
  • All CI checks passing on latest commit.
  • New sections confirmed present in dist/ output.

Port architectural rules from NetPleadings/MinuteBox#9518 (CodeRabbit
review config) back into TKO's public LLM-facing docs. Terminology
normalized to TKO primitives (LifeCycle/BindingHandler/ComponentABC,
ko.subscribable) β€” no MinuteBox-specific references.

- llms.txt: 3 new Gotchas bullets
  - flat JSX attrs vs `params={{…}}` wrapper
  - no observable/computed/subscribe inside a computed evaluator
  - `|| undefined` for binary HTML attrs

- agents/contract.md: 3 new sections
  - "DOM Mutation Containment" β€” DOM-API calls belong in BindingHandler
  - "Component Design" β€” narrow BH scope, component-as-renderer-only
  - "Component Communication via `subscribable`" β€” pub/sub over
    observable-of-function for imperative commands

- agents/guide.md: 4 new subsections + 3 new Gotchas bullets
  - Observables vs computed dependency management
  - Computed styling via attributes (data-attr + CSS over computed class)
  - JSX scope rule
  - Component params in JSX
  - null (not false) for empty HTML computeds, `|| undefined` for
    binary attrs, named-variable computeds over inline

- agents/verified-behaviors/
  - computed.md: new "Anti-patterns" section w/ observable-in-computed
    leak + test sketch
  - lifecycle.md: "Usage guidance" for this.computed/this.subscribe
  - utils-jsx.md: binary HTML attr omit-on-falsy behavior
  - debug.md: generated stub (no-tests-found) matching package-docs
    template

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 20, 2026 20:23
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 20, 2026

Warning

Rate limit exceeded

@brianmhunt has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 35 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 35 minutes and 48 seconds.

βŒ› How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 861fffa3-eaac-48cc-a116-3b8089bf2e05

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 4adc87d and 5f9ad79.

πŸ“’ Files selected for processing (4)
  • AGENTS.md
  • tko.io/public/agents/guide.md
  • tko.io/public/agents/process.md
  • tko.io/public/llms.txt
πŸ“ Walkthrough

Walkthrough

This PR adds and updates documentation to establish stricter architectural guidance around DOM mutation containment, binding handler responsibilities, component design patterns, JSX usage rules, and lifecycle management in Knockout applications. It also introduces new agent process verification requirements and documentation quality standards.

Changes

Cohort / File(s) Summary
Binding & Component Architecture Guidance
tko.io/public/agents/contract.md, tko.io/public/agents/guide.md
Introduces new sections defining DOM mutation containment rules (mutations only in BindingHandler), binding handler design constraints, component view model patterns, component communication via subscribable, JSX attribute rules, and lifecycle-aware observable/computed/subscription creation guidelines.
Verified Behaviors Documentation
tko.io/public/agents/verified-behaviors/computed.md, tko.io/public/agents/verified-behaviors/lifecycle.md, tko.io/public/agents/verified-behaviors/utils-jsx.md
Adds anti-patterns section warning against creating observables/computeds/subscriptions inside computed evaluators, new usage guidance for LifeCycle subclasses, and explicit behavior for binary HTML attributes (omit when null/undefined/false).
Documentation Standards & Index
tko.io/public/llms.txt, AGENTS.md
Updates documentation index descriptions and adds new agent process rules: mandatory doc verification (trackedness, package/spec path existence), mandatory adversarial review with failure-mode enumeration, and audit trail requirements in PR descriptions.
Configuration
.gitignore
Adds *.original.md to ignored files.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hop along the binding path so fine,
Where DOM lives in containment's line,
No leaks in computed, clear lifecycle's call,
Architecture guides us, protecting us all! ✨

πŸš₯ Pre-merge checks | βœ… 5
βœ… Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage βœ… Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check βœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check βœ… Passed Check skipped because no linked issues were found for this pull request.
Title check βœ… Passed The PR title directly describes the main change: adding KO/ViewComponent architectural guidelines ported from a MinuteBox review into TKO's public documentation.
Description Check βœ… Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
πŸ§ͺ Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/llm-guidance-mb-imports

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d7d76d4e8d

ℹ️ 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".

- **Cannot apply bindings twice** to the same DOM node β€” throws error.
- **`dispose()` on computed/subscriptions** stops updates. After disposal, reading returns last cached value.
- **HTML-producing computeds** should return `null` for empty output, not `false` or an empty fragment β€” bindings and JSX observers handle `null` cleanly.
- **Binary HTML attributes** (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute when the value is `null`, `undefined`, or `false`. Use `|| undefined` in computeds to make "no attribute" explicit: `disabled={this.computed(() => shouldBeDisabled() || undefined)}`. Never return the string `"false"` β€” it keeps the attribute set.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Correct binary-attribute false/null semantics

This gotcha states that binary attributes are omitted when the value is null or false, but packages/utils.jsx/src/JsxObserver.ts removes attributes only for undefined and otherwise stringifies the value via setAttributeNS, so false/null become present attributes ("false"/"null"). For boolean HTML attrs like disabled, presence keeps the attribute active, so code generated from this guidance can leave controls disabled when the computed returns false; please align this rule (and the copied wording in verified-behaviors/utils-jsx.md) with actual runtime behavior.

Useful? React with πŸ‘Β / πŸ‘Ž.

Stub was locally generated during an earlier run while the
codex/tko-mcp-debug-plan branch (which introduces packages/debug)
was in the working tree. That package is not merged to main, so
the doc referenced a package that does not exist in this branch's
scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ports Knockout/ViewComponent architectural guidance into TKO’s public LLM-facing docs, adding new β€œgotchas” and expanding agent documentation and β€œverified behaviors” references to align with TKO primitives (LifeCycle, BindingHandler, ComponentABC, ko.subscribable).

Changes:

  • Add new JSX/computed/HTML attribute gotchas to llms.txt and the main agent guide.
  • Add contract guidance for DOM mutation containment, component/BH responsibilities, and component communication via ko.subscribable.
  • Extend β€œverified behaviors” docs (including a new @tko/debug stub) with additional lifecycle/computed/jsx guidance.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tko.io/public/llms.txt Adds new gotchas for JSX params flattening, computed anti-patterns, and binary HTML attributes.
tko.io/public/agents/verified-behaviors/utils-jsx.md Documents JSX binary HTML attribute behavior (needs correction to match implementation).
tko.io/public/agents/verified-behaviors/lifecycle.md Adds lifecycle β€œusage guidance” section (currently not aligned with β€œverified behaviors” contract).
tko.io/public/agents/verified-behaviors/debug.md Adds generated no-tests-found stub for @tko/debug.
tko.io/public/agents/verified-behaviors/computed.md Adds an β€œAnti-patterns” section (currently not test-backed per the directory’s stated contract).
tko.io/public/agents/guide.md Adds extended guidance on lifecycle-owned reactivity, JSX usage, styling via attributes, component params, and new gotchas (includes binary-attr wording that needs correction).
tko.io/public/agents/contract.md Adds architectural contract rules around DOM mutation containment and component/BH communication patterns.

Comment on lines +33 to +51

## Anti-patterns

- Creating observables, computeds, or subscriptions **inside** a computed's evaluator leaks instances. The evaluator re-runs on every dependency change, producing a new un-disposed subscriber each time, so memory and subscriber count grow without bound.
Test sketch:
```ts
const dep = ko.observable(0)
const instances: KnockoutObservable<number>[] = []
const leaky = ko.computed(() => {
const obs = ko.observable(dep() + 1)
instances.push(obs)
return obs()
})
expect(instances.length).toBe(1)
dep(1); expect(instances.length).toBe(2)
dep(2); expect(instances.length).toBe(3)
```
Fix: create the observable/subscription once outside the computed, or inside a `LifeCycle` subclass constructor where `this.subscribe` / `this.computed` own disposal.
Related specs: `packages/lifecycle/spec/LifeCycleBehaviors.ts` (disposal semantics).
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new "Anti-patterns" entry is in the "verified-behaviors" directory, but it doesn't cite a spec that actually verifies the described leak, and it includes a "test sketch" rather than a real test reference. Given the file header says non-test-backed behaviors do not belong here, either add/point to a concrete spec that covers this behavior (and cite it as "Specs:"), or move this guidance to /agents/guide.md (and keep this file strictly test-backed).

Suggested change
## Anti-patterns
- Creating observables, computeds, or subscriptions **inside** a computed's evaluator leaks instances. The evaluator re-runs on every dependency change, producing a new un-disposed subscriber each time, so memory and subscriber count grow without bound.
Test sketch:
```ts
const dep = ko.observable(0)
const instances: KnockoutObservable<number>[] = []
const leaky = ko.computed(() => {
const obs = ko.observable(dep() + 1)
instances.push(obs)
return obs()
})
expect(instances.length).toBe(1)
dep(1); expect(instances.length).toBe(2)
dep(2); expect(instances.length).toBe(3)
```
Fix: create the observable/subscription once outside the computed, or inside a `LifeCycle` subclass constructor where `this.subscribe` / `this.computed` own disposal.
Related specs: `packages/lifecycle/spec/LifeCycleBehaviors.ts` (disposal semantics).

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +36

## Usage guidance

- Prefer `this.computed(...)` over standalone `ko.computed(...)` inside a `LifeCycle` subclass β€” the computed is added to the instance's disposal set automatically.
- Prefer `this.subscribe(observable, callback)` over `observable.subscribe(callback)` inside a `LifeCycle` subclass for the same reason.
- Do not create observables, computeds, or subscriptions inside a computed's evaluator β€” see the anti-pattern in `computed.md`.
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Usage guidance" section adds non-test-backed recommendations to a "verified-behaviors" doc whose header states that behaviors not covered by unit tests do not belong here. Please either (a) move this guidance into /agents/guide.md, or (b) explicitly connect each bullet to an existing spec (using the same "Specs:" convention as the rest of the file) so readers can verify the claim from tests.

Suggested change
## Usage guidance
- Prefer `this.computed(...)` over standalone `ko.computed(...)` inside a `LifeCycle` subclass β€” the computed is added to the instance's disposal set automatically.
- Prefer `this.subscribe(observable, callback)` over `observable.subscribe(callback)` inside a `LifeCycle` subclass for the same reason.
- Do not create observables, computeds, or subscriptions inside a computed's evaluator β€” see the anti-pattern in `computed.md`.

Copilot uses AI. Check for mistakes.
Specs: `packages/utils.jsx/spec/jsxBehaviors.ts`
- JSX-created nodes can carry native bindings and participate in component rendering and observable-array diff updates.
Specs: `packages/utils.jsx/spec/jsxBehaviors.ts`
- Binary HTML attributes (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute when the observable/computed value is `null`, `undefined`, or `false`; any other value (including the string `"false"`) sets the attribute. Use `|| undefined` in computeds to express "no attribute" explicitly.
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The claim that binary HTML attributes are omitted when the value is null or false doesn't match the current JSX implementation: JsxObserver.setNodeAttribute only removes attributes when the unwrapped value is undefined; null/false are stringified and set (e.g., disabled="false" still leaves the attribute present). Please update this bullet to reflect that omission only happens via undefined, and keep || undefined (or an explicit conditional) as the recommended way to remove the attribute.

Suggested change
- Binary HTML attributes (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute when the observable/computed value is `null`, `undefined`, or `false`; any other value (including the string `"false"`) sets the attribute. Use `|| undefined` in computeds to express "no attribute" explicitly.
- Binary HTML attributes (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute only when the observable/computed value is `undefined`; `null` and `false` are stringified and set, so even `disabled="false"` still leaves the attribute present. Use `|| undefined` in computeds, or an explicit conditional, to express "no attribute" explicitly.

Copilot uses AI. Check for mistakes.
- **Cannot apply bindings twice** to the same DOM node β€” throws error.
- **`dispose()` on computed/subscriptions** stops updates. After disposal, reading returns last cached value.
- **HTML-producing computeds** should return `null` for empty output, not `false` or an empty fragment β€” bindings and JSX observers handle `null` cleanly.
- **Binary HTML attributes** (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute when the value is `null`, `undefined`, or `false`. Use `|| undefined` in computeds to make "no attribute" explicit: `disabled={this.computed(() => shouldBeDisabled() || undefined)}`. Never return the string `"false"` β€” it keeps the attribute set.
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Gotcha says binary HTML attributes are omitted when the value is null, undefined, or false, but JSX attribute setting currently only removes attributes when the value is undefined (other values, including null/false, are stringified and set). Please revise the wording to avoid implying that null/false automatically omit the attribute, and keep the guidance focused on returning undefined (e.g., via || undefined) to ensure removal.

Suggested change
- **Binary HTML attributes** (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute when the value is `null`, `undefined`, or `false`. Use `|| undefined` in computeds to make "no attribute" explicit: `disabled={this.computed(() => shouldBeDisabled() || undefined)}`. Never return the string `"false"` β€” it keeps the attribute set.
- **Binary HTML attributes** (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) should return `undefined` when you want JSX to remove the attribute. Use `|| undefined` in computeds to make "no attribute" explicit: `disabled={this.computed(() => shouldBeDisabled() || undefined)}`. Do not rely on `null` or `false` to omit the attribute, and never return the string `"false"` β€” it keeps the attribute set.

Copilot uses AI. Check for mistakes.
- Bare `ko.observable()` and `ko.observableArray()` are safe anywhere β€” they are containers and do not re-evaluate.
- Inside a class using the `LifeCycle` mixin (for example `BindingHandler`, `ComponentABC`, or anything produced by `LifeCycle.mixInto`), prefer `this.computed(...)` over standalone `ko.computed(...)` and `this.subscribe(observable, cb)` over `observable.subscribe(cb)` β€” both are auto-disposed when the instance is torn down.
- In plain view models without `LifeCycle`, `ko.computed(...)` and `observable.subscribe(...)` are fine; call `dispose()` on them when you are done.
- **Never** create `ko.observable()`, `ko.computed()`, or call `.subscribe()` inside a computed's evaluator. The evaluator runs on every dependency change, so new observables/subscriptions pile up and never dispose β€” memory and CPU grow unbounded. Create them once outside the computed, or in a `LifeCycle`-enabled constructor.
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section states that creating ko.observable() inside a computed evaluator causes instances to pile up and never dispose. In @tko/computed, dependency tracking disposes subscriptions to prior dependencies on each evaluation, so creating an observable inside an evaluator doesn't inherently leak unless you retain references or create unmanaged subscriptions/computeds. Please narrow this guidance to the cases that actually leak (e.g., creating subscriptions or computeds inside the evaluator) or reword it as a performance/clarity anti-pattern rather than an unbounded leak for plain observables.

Suggested change
- **Never** create `ko.observable()`, `ko.computed()`, or call `.subscribe()` inside a computed's evaluator. The evaluator runs on every dependency change, so new observables/subscriptions pile up and never dispose β€” memory and CPU grow unbounded. Create them once outside the computed, or in a `LifeCycle`-enabled constructor.
- Avoid creating reactive objects inside a computed's evaluator. Creating `ko.computed()` instances or calling `.subscribe()` there can accumulate unmanaged work unless you dispose them manually, because the evaluator runs on every dependency change. Creating a plain `ko.observable()` there does not inherently leak, but it is usually a performance/clarity anti-pattern unless it is purely temporary and you do not retain references to it. Prefer creating observables, computeds, and subscriptions once outside the evaluator, or in a `LifeCycle`-enabled constructor.

Copilot uses AI. Check for mistakes.
Comment thread tko.io/public/llms.txt Outdated
- `ko.applyBindings(...)` returns a Promise
- Inside `ko-foreach`, binding-context vars use strings: `ko-text="$data"` (not `{$data}`)
- Component JSX params: pass each constructor param as its own attribute (`<my-card out={x} onEdit={fn} />`), never wrap in `params={{...}}` β€” JSX attrs flatten into one constructor arg, so wrapping double-nests to `{ params: {...} }`
- Never create `ko.observable()`, `ko.computed()`, or `.subscribe()` inside a computed evaluator β€” re-runs leak instances
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Gotcha asserts that creating ko.observable() inside a computed evaluator leaks instances. @tko/computed disposes prior dependency subscriptions on each evaluation, so plain observables created inside the evaluator don't necessarily accumulate unless references are retained; the leak risk is much clearer for creating subscriptions/computeds inside the evaluator. Please adjust the wording to avoid stating a guaranteed leak for ko.observable() and focus on the cases that actually leak or on the performance implications.

Suggested change
- Never create `ko.observable()`, `ko.computed()`, or `.subscribe()` inside a computed evaluator β€” re-runs leak instances
- Avoid creating `ko.observable()`, `ko.computed()`, or `.subscribe()` inside a computed evaluator β€” `ko.computed()` and `.subscribe()` can accumulate unless disposed, while `ko.observable()` usually just creates unnecessary transient instances unless references are retained

Copilot uses AI. Check for mistakes.
Preventive rule added after shipping an orphan verified-behaviors
stub (`debug.md`) in the preceding commit β€” the file referenced
`@tko/debug`, a package that exists only on an unmerged branch
(`codex/tko-mcp-debug-plan`). Stub had leaked into the working
tree from a prior generator run.

- New subsection under "Agent-First Documentation": mandatory
  verification checklist (git ls-files, package existence, spec
  paths, URLs) before staging any doc file.
- Added as a failure mode under "Review Your Own Change
  Adversarially".

Rationale: shipping docs that name non-existent entities is
worse than no doc at all β€” it misleads every future reader
(human or agent) who trusts the docs as a contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tko.io/public/agents/contract.md (1)

76-76: Optional: Consider simplifying "because" clauses for conciseness.

Static analysis suggests these phrases could be more concise:

  • Line 76: "a handler that is complex because its single DOM task is inherently complex" β†’ "a handler whose single DOM task is inherently complex"
  • Line 89: "a component that is large because it composes many small child components" β†’ "a component that composes many small child components"

Also applies to: 89-89

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tko.io/public/agents/contract.md` at line 76, Replace verbose "because"
clauses with shorter relative phrasing in the descriptive lines: change the
phrase "a handler that is complex because its single DOM task is inherently
complex" (in contract.md) to "a handler whose single DOM task is inherently
complex" and similarly change "a component that is large because it composes
many small child components" to "a component that composes many small child
components" to improve conciseness while preserving meaning.
πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tko.io/public/agents/verified-behaviors/utils-jsx.md`:
- Around line 33-34: The docs say binary attributes (disabled, readonly, hidden,
required, checked, selected) should be omitted for null/undefined/false, but
JsxObserver currently only omits on undefined; update the attribute-update logic
in JsxObserver.ts (the function handling setAttributeNS/attribute writes around
the node.setAttributeNS(ns, name, String(value)) calls) to treat null and false
the same as undefined by normalizing value => undefined for these specific
attribute names before calling setAttributeNS or removeAttribute, add unit tests
in packages/utils.jsx/spec/jsxBehaviors.ts to cover null and false cases, and
regenerate packages/utils.jsx/verified-behaviors.json so the verified behaviors
match the new behavior.

---

Nitpick comments:
In `@tko.io/public/agents/contract.md`:
- Line 76: Replace verbose "because" clauses with shorter relative phrasing in
the descriptive lines: change the phrase "a handler that is complex because its
single DOM task is inherently complex" (in contract.md) to "a handler whose
single DOM task is inherently complex" and similarly change "a component that is
large because it composes many small child components" to "a component that
composes many small child components" to improve conciseness while preserving
meaning.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e8f188c-074b-44b5-b9ab-ff5eab20946a

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 6629d63 and d7d76d4.

πŸ“’ Files selected for processing (7)
  • tko.io/public/agents/contract.md
  • tko.io/public/agents/guide.md
  • tko.io/public/agents/verified-behaviors/computed.md
  • tko.io/public/agents/verified-behaviors/debug.md
  • tko.io/public/agents/verified-behaviors/lifecycle.md
  • tko.io/public/agents/verified-behaviors/utils-jsx.md
  • tko.io/public/llms.txt

Comment on lines +33 to +34
- Binary HTML attributes (`disabled`, `readonly`, `hidden`, `required`, `checked`, `selected`) omit the attribute when the observable/computed value is `null`, `undefined`, or `false`; any other value (including the string `"false"`) sets the attribute. Use `|| undefined` in computeds to express "no attribute" explicitly.
Specs: `packages/utils.jsx/spec/jsxBehaviors.ts`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify binary HTML attribute rendering behavior with null/false values

echo "=== Searching for binary attribute preprocessing logic ==="
rg -n -C5 'disabled|readonly|hidden|required|checked|selected' packages/utils.jsx/src/ --type ts

echo ""
echo "=== Searching for null/false to undefined conversion ==="
rg -n -C5 'null.*undefined|false.*undefined' packages/utils.jsx/src/JsxObserver.ts

echo ""
echo "=== Looking for attribute value normalization ==="
ast-grep --pattern $'function $FUNC($$$) {
  $$$
  if ($VALUE === null || $VALUE === false) {
    $$$
  }
  $$$
}'

Repository: knockout/tko

Length of output: 536


🏁 Script executed:

# Find and examine JsxObserver.ts file
find . -name "JsxObserver.ts" -type f

Repository: knockout/tko

Length of output: 95


🏁 Script executed:

# Read the utils.jsx spec file to understand expected behavior
find . -path "*/packages/utils.jsx/spec/jsxBehaviors.ts" -type f

Repository: knockout/tko

Length of output: 97


🏁 Script executed:

# Read the documentation file being reviewed
find . -path "*/tko.io/public/agents/verified-behaviors/utils-jsx.md" -type f

Repository: knockout/tko

Length of output: 110


🏁 Script executed:

# Check sizes of the files
wc -l ./packages/utils.jsx/src/JsxObserver.ts ./packages/utils.jsx/spec/jsxBehaviors.ts ./tko.io/public/agents/verified-behaviors/utils-jsx.md

Repository: knockout/tko

Length of output: 222


🏁 Script executed:

# Read JsxObserver.ts around lines 398-408
sed -n '390,420p' ./packages/utils.jsx/src/JsxObserver.ts

Repository: knockout/tko

Length of output: 1120


🏁 Script executed:

# Read the spec file
cat ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 37565


🏁 Script executed:

# Read the documentation file
cat ./tko.io/public/agents/verified-behaviors/utils-jsx.md

Repository: knockout/tko

Length of output: 2236


🏁 Script executed:

# Search for binary attribute tests in the spec file
grep -n "disabled\|readonly\|hidden\|required\|checked\|selected" ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 38


🏁 Script executed:

# Search for tests that check attribute removal with null/false
grep -n -B3 -A3 "null\|false" ./packages/utils.jsx/spec/jsxBehaviors.ts | grep -A5 -B5 "attribute"

Repository: knockout/tko

Length of output: 1683


🏁 Script executed:

# Search for where setNodeAttribute is called
grep -n "setNodeAttribute" ./packages/utils.jsx/src/JsxObserver.ts

Repository: knockout/tko

Length of output: 434


🏁 Script executed:

# Look for NativeProvider.addValueToNode to see if it does preprocessing
find . -name "*NativeProvider*" -type f

Repository: knockout/tko

Length of output: 163


🏁 Script executed:

# Read NativeProvider.ts to see if addValueToNode handles binary attributes
cat ./packages/provider.native/src/NativeProvider.ts

Repository: knockout/tko

Length of output: 2203


🏁 Script executed:

# Get more context around setNodeAttribute calls
sed -n '360,380p' ./packages/utils.jsx/src/JsxObserver.ts

Repository: knockout/tko

Length of output: 663


🏁 Script executed:

# Search for "binary" in the codebase to find relevant code
rg -n "binary" --type ts

Repository: knockout/tko

Length of output: 361


🏁 Script executed:

# Read the full JsxObserver.ts to understand the attribute handling flow
cat ./packages/utils.jsx/src/JsxObserver.ts

Repository: knockout/tko

Length of output: 13764


🏁 Script executed:

# Search spec file for tests on binary attributes like "disabled", "checked", etc.
grep -n "disabled\|checked\|readonly\|hidden\|required\|selected" ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 38


🏁 Script executed:

# Search for any tests involving null or false on attributes
grep -n -B5 -A10 "attributes.*null\|attributes.*false" ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 38


🏁 Script executed:

# Look for tests that verify attribute removal
grep -n -B3 -A3 "removeAttribute" ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 38


🏁 Script executed:

# Let's verify the documented behavior by checking the verified-behaviors.json file
find . -name "verified-behaviors.json" -path "*/utils.jsx/*" -type f

Repository: knockout/tko

Length of output: 100


🏁 Script executed:

# Let's also test the actual behavior by creating a small test to see what happens
# Read any existing attribute-related test to understand how they test attribute behavior
grep -n "attributes:" ./packages/utils.jsx/spec/jsxBehaviors.ts | head -20

Repository: knockout/tko

Length of output: 1720


🏁 Script executed:

# Look for the test that verifies toggles observable attribute
grep -n -B2 -A8 "toggles an observable attribute" ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 479


🏁 Script executed:

# Read the verified-behaviors.json file
cat ./packages/utils.jsx/verified-behaviors.json

Repository: knockout/tko

Length of output: 1564


🏁 Script executed:

# Check the test that toggles empty observable attribute (just before the one we found)
grep -n -B2 -A8 "toggles an empty observable attribute" ./packages/utils.jsx/spec/jsxBehaviors.ts

Repository: knockout/tko

Length of output: 469


Fix documented binary HTML attribute behavior or update documentation to match implementation.

The documentation states that binary HTML attributes (disabled, readonly, hidden, required, checked, selected) omit the attribute when the value is null, undefined, or false. However, the code in JsxObserver.ts:398-410 only removes attributes when value === undefined. For null and false values, the code calls node.setAttributeNS(ns, name, String(value)), which renders "null" and "false" as attribute values rather than omitting them.

Additionally, this behavior is not covered by any tests in packages/utils.jsx/spec/jsxBehaviors.ts and is not included in packages/utils.jsx/verified-behaviors.json (which is generated from unit tests). Either implement the documented behavior with proper preprocessing to convert null and false to undefined for binary attributes, or update the documentation to reflect the actual implementation that only omits attributes for undefined values.

πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tko.io/public/agents/verified-behaviors/utils-jsx.md` around lines 33 - 34,
The docs say binary attributes (disabled, readonly, hidden, required, checked,
selected) should be omitted for null/undefined/false, but JsxObserver currently
only omits on undefined; update the attribute-update logic in JsxObserver.ts
(the function handling setAttributeNS/attribute writes around the
node.setAttributeNS(ns, name, String(value)) calls) to treat null and false the
same as undefined by normalizing value => undefined for these specific attribute
names before calling setAttributeNS or removeAttribute, add unit tests in
packages/utils.jsx/spec/jsxBehaviors.ts to cover null and false cases, and
regenerate packages/utils.jsx/verified-behaviors.json so the verified behaviors
match the new behavior.

Brian M Hunt and others added 4 commits April 20, 2026 16:36
Promotes the previously-soft "independent second pass" guidance
into a hard requirement, scoped to changes that affect package
behavior, public API, tests, agent-facing docs, CI, or build/
config. Proportionality carve-out excludes typos, whitespace,
and the adversarial review's own report (terminates recursion).

How-to covers: fresh subagent, brief with artefact + claim only
(withhold author reasoning to prevent anchoring), enumerate
failure modes before checking correctness, verify findings
defensively (not as licence to override), route out-of-scope
findings to follow-ups rather than ballooning the PR, and
record the pass outcome in the PR description so compliance
is auditable.

Written in response to shipping an orphan doc stub in commit
d7d76d4 β€” single-pair-of-eyes review missed it. Rule itself
reviewed adversarially before landing; the six findings from
that pass (self-reference termination, single-pair leak on
verification, proportionality, gaming via leading questions,
missing audit trail, PR-scope conflict) are all folded into
this wording.

Adversarial pass: Explore subagent. Result: flagged 6; all
addressed in this commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply the caveman:compress skill to files that are purely LLM-facing
(llms.txt + verified-behaviors/*.md). Drops articles, filler, and
hedging without touching code, backticked identifiers, URLs, or
spec paths.

Byte savings per file:
- tko.io/public/llms.txt:                              1%
- tko.io/public/agents/verified-behaviors/computed.md: 7%
- tko.io/public/agents/verified-behaviors/lifecycle.md:7%
- tko.io/public/agents/verified-behaviors/utils-jsx.md:5%

Files already dense, so savings are modest β€” kept anyway because
every downstream agent that loads the agent-facing pack pays the
token cost on every session.

Dual-audience docs (AGENTS.md, agents/guide.md, agents/contract.md)
intentionally left uncompressed β€” human contributors read them.

.gitignore: add `*.original.md` so future compress runs don't leak
their local backups into commits.

Adversarial pass: Explore subagent. Flagged 1 (computed.md
fragment-header dropped the If/then conditional β†’ meaning
ambiguous). Resolved: restored "If … , not belong in this
directory." phrasing in that one line. Other diffs accepted β€”
meaning preserved under caveman article/pronoun drops.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "Good: computed attribute + CSS selector" example had
`const isActive = this.computed(() => this.isActive() || undefined)`,
where the local variable `isActive` shadows the class method
`this.isActive()`. JS scoping makes the inner call resolve to
the method, so the example was not actually broken β€” but a
novice reader could reasonably mistake it for a self-referential
computed. Renamed the local to `activeAttr` so the two names
no longer collide.

Adversarial pass: Explore subagent on full PR diff. Flagged 1
high (shadowing confusion in this example). Also flagged two
items verified as false positives: "not belong" fragments in
caveman-compressed files (grammatically terse but unambiguous),
and `tko.jsx.render` (defined on the bundled `tko` global at
builds/reference/src/index.ts β€” already documented in existing
guide.md counter/todo examples).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`tko.io/scripts/generate-verified-behaviors.mjs` rebuilds every
`tko.io/public/agents/verified-behaviors/*.md` file from the
package-local `verified-behaviors.json` curated sources on every
`prebuild` / `predev` run (and therefore every CI build via
`deploy-docs.yml`). Hand-edits to those markdown files are
transient and would have been wiped the next time anyone ran
`bun run dev` or the site was deployed.

Reverted to the generator's canonical output on `main`:
- tko.io/public/agents/verified-behaviors/computed.md
- tko.io/public/agents/verified-behaviors/lifecycle.md
- tko.io/public/agents/verified-behaviors/utils-jsx.md

That also undoes the caveman compression on those three files β€”
the generator emits natural-English from the JSON, so compression
would be re-undone on the first build. Compression on
`llms.txt` stands (no generator owns it).

Content that was in those reverts now lives only in the
hand-authored docs where it belongs per verified-behaviors
charter ("If behavior not covered by unit tests, it does not
belong in this directory"):

- Observable-inside-computed leak: `agents/guide.md` Gotchas
  (strengthens the existing "Don't create computeds/subscriptions
  inside computeds" bullet to include observables + subscriptions).
- `this.computed` / `this.subscribe` preference: `agents/guide.md`
  under "Observables vs computed dependency management".
- Binary HTML attr `|| undefined`: `agents/guide.md` Gotchas +
  `llms.txt` Gotchas. (No spec in `packages/utils.jsx/spec`
  covers the null/undefined/false omission behavior, so it cannot
  be added as a verified entry β€” would need a test first.)

Adversarial pass: caught by the "Docs Verification" pre-check,
not by a subagent β€” running `bun run dev` would have regenerated
the three files and silently dropped 3 commits' worth of edits.
Audit trail added here.

Follow-up: if someone wants those additions as verified entries,
the path is (1) add a test to the owning package's spec, (2) add
a behavior entry to that package's `verified-behaviors.json`,
(3) rerun the generator. Not this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

πŸ€– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@AGENTS.md`:
- Line 191: The package-existence verification currently only runs "ls
packages/<name>" which misses valid public packages under builds/, so update the
rule to check both locations (packages/<name> and builds/<name>) or perform a
single lookup that searches both directories and verifies a matching
package.json; replace references to the lone check "ls packages/<name>" in the
doc/guideline text with the broadened check logic/description so docs no longer
flag legitimate packages like "@tko/build.knockout" as orphans.

In `@tko.io/public/agents/verified-behaviors/computed.md`:
- Line 4: The directory gate sentence in computed.md is ungrammatical; replace
"If behavior not covered by unit tests, not belong in this directory." with a
clear grammatical rule such as "Behaviors not covered by unit tests do not
belong in this directory." or "If a behavior is not covered by unit tests, it
does not belong in this directory." Update the line in computed.md accordingly
to use one of these corrected phrasings so the normative rule is clear and
grammatical.
πŸͺ„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a30784ec-5433-4306-aa27-7365a9abdedc

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d7d76d4 and 4adc87d.

πŸ“’ Files selected for processing (7)
  • .gitignore
  • AGENTS.md
  • tko.io/public/agents/guide.md
  • tko.io/public/agents/verified-behaviors/computed.md
  • tko.io/public/agents/verified-behaviors/lifecycle.md
  • tko.io/public/agents/verified-behaviors/utils-jsx.md
  • tko.io/public/llms.txt
βœ… Files skipped from review due to trivial changes (2)
  • .gitignore
  • tko.io/public/llms.txt
🚧 Files skipped from review as they are similar to previous changes (3)
  • tko.io/public/agents/verified-behaviors/utils-jsx.md
  • tko.io/public/agents/verified-behaviors/lifecycle.md
  • tko.io/public/agents/guide.md

Comment thread AGENTS.md Outdated
1. `git ls-files <path>` β€” is it tracked? If not, where did it come from?
- If it was emitted by a generator (e.g. `tko.io/scripts/generate-verified-behaviors.mjs`), re-run the generator on a clean checkout of the target branch and diff. If the generator does not produce it, it is stale β€” do not ship it.
- If it was hand-written on a different branch, confirm that branch has merged into the target. `git log --all -- <path>` and `git branch --contains <commit>` will show where it lives.
2. For each package name in the doc: `ls packages/<name>` and confirm a matching `package.json`. Orphan `@tko/*` references mislead both humans and downstream agents.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟑 Minor

Broaden package existence check to include builds/* packages

ls packages/<name> is incomplete for valid public packages like @tko/build.knockout, which live under builds/. This verification rule can misclassify legitimate references as invalid.

πŸ’‘ Suggested doc fix
-2. For each package name in the doc: `ls packages/<name>` and confirm a matching `package.json`. Orphan `@tko/*` references mislead both humans and downstream agents.
+2. For each package name in the doc: confirm a matching `package.json` exists in either `packages/*` or `builds/*` (for example, by searching package names rather than assuming one root). Orphan `@tko/*` references mislead both humans and downstream agents.
As per coding guidelines: "Never ship documentation that references packages, exports, functions, spec paths, or URLs that do not exist on the target branch".
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` at line 191, The package-existence verification currently only
runs "ls packages/<name>" which misses valid public packages under builds/, so
update the rule to check both locations (packages/<name> and builds/<name>) or
perform a single lookup that searches both directories and verifies a matching
package.json; replace references to the lone check "ls packages/<name>" in the
doc/guideline text with the broadened check logic/description so docs no longer
flag legitimate packages like "@tko/build.knockout" as orphans.

Comment thread tko.io/public/agents/verified-behaviors/computed.md Outdated
@brianmhunt brianmhunt changed the title docs(agents): add KO/ViewComponent guidelines from MinuteBox review docs(agents): add KO/ViewComponent guidelines from review Apr 21, 2026
Brian M Hunt and others added 3 commits April 21, 2026 08:41
AGENTS.md is loaded on every agent session β€” token cost amortized
forever. Two recently-added process blocks ("Never ship docs that
reference things that don't exist" + "Adversarial review is
mandatory") were ~50 lines combined. Moved the how-to detail to a
new hand-authored doc `tko.io/public/agents/process.md`; AGENTS.md
keeps the one-line mandate, in-scope trigger, and dark-factory
motivation inline so the rule still fires from session load.

Changes:
- `AGENTS.md`: two heavy subsections collapsed to one-paragraph
  mandates with links to process.md; failure-modes list + existing
  narrative retained inline.
- `tko.io/public/agents/process.md`: new file carrying the full
  how-to, in-scope/out-of-scope list, adversarial-review
  checklist, audit-trail format, and generator-ownership warning
  for verified-behaviors. Includes a credits section naming the
  MinuteBox PR that seeded the imported architectural rules.
- `tko.io/public/llms.txt`: added `/agents/process.md` to the
  agent-docs list so downstream agents discover it.

Line delta vs `main` for AGENTS.md: +5 (down from +55 before the
refactor).

Credit: architectural review guidelines originally from
NetPleadings/MinuteBox#9518 by @jameskozlowskimb with input from
@ctcarton β€” ported upstream and reworded for TKO primitives.

Adversarial pass: Explore subagent. Flagged 4 items; 1 valid
(lost dark-factory motivation β€” restored one sentence inline), 3
false positives (link-resolution claim wrong for repo-relative
markdown paths that Claude Code follows natively; in-scope list
claim wrong because list stayed inline in prose; circular-ref
claim wrong because the bidirectional link is content vs. rules,
not a cycle).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous wording cast Pattern B (computed data-attr + CSS selector)
as the "correct" approach and Pattern A (computed className / inline
style) as an anti-pattern. That's a style preference, not a framework
rule β€” both produce the same runtime behaviour; consistency within a
codebase matters more than the choice. Rewrote the section to
present both patterns symmetrically with trade-offs each way.

Key change: "Do not use computeds to switch CSS class names …"
becomes "Reactive styling: two valid patterns … Pick one and apply
it consistently."

Adversarial pass: Explore subagent. Flagged 2 valid items in the
trade-offs list β€” (1) Pattern A's "rule stays in component file"
claim incomplete when class body lives in a separate stylesheet;
(2) Pattern B's "avoids class-name string concatenation" read as
pro-B framing disguised as neutral. Both tweaked to acknowledge
Pattern A's template-literal / class-map mitigation and the
split-visibility caveat. Result: balanced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two non-mandate issues surfaced:

1. The "Computed styling via attributes" section was written as if
   the two shown patterns exhausted the choice. They don't β€” CSS
   custom properties driven from a computed, classless inline
   style objects, component-scoped style blocks, and CSS-in-JS
   tokens are all reasonable in TKO. Section reframed as "two
   examples among several" under a "Reactive styling" heading,
   with the named parenthetical listing the other valid
   approaches. Emphasis stays on consistency within a codebase,
   not on picking a particular pattern.

2. The adversarial-review audit trail was documented as going
   into the PR description. That breaks the contract a PR
   description is meant to honour (why the change exists, what
   problem it solves) and feels like editing someone else's
   artefact for process metadata. Moved the audit line to the
   **commit message** that introduces the in-scope change, one
   line per in-scope commit. Explicit "do not add review
   outcomes to the PR description" clause in process.md.
   Squash-merge caveat added: copy audit lines into the squash
   target message manually if the merge rewrites commit
   messages.

Also tightened wording consistency between AGENTS.md and
process.md ("commit message that introduces the in-scope
change" now appears in both).

Adversarial pass: Explore subagent. Flagged 3 valid (commit-
scope ambiguity, squash-merge vulnerability, cross-file wording
drift) β€” all three addressed. Verdict after fixes: ship.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@brianmhunt brianmhunt merged commit 265b354 into main Apr 21, 2026
9 checks passed
@brianmhunt brianmhunt deleted the docs/llm-guidance-mb-imports branch April 21, 2026 12:56
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.

2 participants