From 5107be3a85e7ea055dbf4af69d0b43b767a3a234 Mon Sep 17 00:00:00 2001 From: Brian M Hunt Date: Tue, 21 Apr 2026 10:30:57 -0400 Subject: [PATCH 1/5] Trim redundant preambles in hand-authored agent docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same motivation as the generator-preamble strip in PR #349 — every agent that loads these docs on session start pays the cost of redundant metadata that the title and section 1 already carry. Applied to three hand-authored files: - `agents/soul.md`: collapsed the 4-line "This document describes the philosophical foundation..." preamble into a single sentence that keeps the AI-agent targeting and the "why not how" framing without the meta-commentary wrapper. - `agents/glossary.md`: removed the 1-line "Domain-specific terms..." preamble. Title + "Core Concepts" section already carry that signal. - `agents/options.md`: compressed the 3-sentence opener into one line that keeps the singleton name, file location, and scope ("two mechanisms for adding options"). Left untouched: - `agents/testing.md` — 137 lines of how-to with inline code; compression risks clarity for marginal byte savings. - `agents/contract.md` / `agents/guide.md` — preambles already minimal (1–3 lines of pointer prose). Adversarial pass: Explore subagent. Flagged 1 valid item — the initial soul.md tagline dropped the explicit AI-agent signal and broke tone parity with peer docs. Resolved by rewriting to a longer sentence that restores both. Also identified options.md as a follow-up candidate from the same pass; applied inline. Co-Authored-By: Claude Opus 4.7 (1M context) --- tko.io/public/agents/glossary.md | 2 -- tko.io/public/agents/options.md | 4 +--- tko.io/public/agents/soul.md | 5 +---- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/tko.io/public/agents/glossary.md b/tko.io/public/agents/glossary.md index e996d87e..3c01647a 100644 --- a/tko.io/public/agents/glossary.md +++ b/tko.io/public/agents/glossary.md @@ -1,7 +1,5 @@ # TKO Glossary -Domain-specific terms for the TKO (Typed Knockout) framework. - ## Core Concepts - **Observable** (`ko.observable(value)`) — a value wrapper that notifies subscribers when it changes. The fundamental reactive primitive. diff --git a/tko.io/public/agents/options.md b/tko.io/public/agents/options.md index 88d21d03..3d136b27 100644 --- a/tko.io/public/agents/options.md +++ b/tko.io/public/agents/options.md @@ -1,8 +1,6 @@ # `ko.options.*` — Configurable Runtime Options -`ko.options` is TKO's runtime configuration object. It is a singleton `Options` -instance defined in `packages/utils/src/options.ts`. This page documents how -to add new options and which of the two available mechanisms to reach for. +`ko.options` is TKO's runtime configuration singleton, defined in `packages/utils/src/options.ts`. Two mechanisms for adding options — this page explains which to reach for. ## Two mechanisms — when to use which diff --git a/tko.io/public/agents/soul.md b/tko.io/public/agents/soul.md index c785c0b0..9e2b4931 100644 --- a/tko.io/public/agents/soul.md +++ b/tko.io/public/agents/soul.md @@ -1,9 +1,6 @@ # The Soul of Knockout -This document describes the philosophical foundation of Knockout and TKO. -Read this to understand *why* the framework works the way it does, not just -*how* to use it. If you're an AI agent working on this codebase, this is -the context behind every design decision. +Read this to understand *why* TKO is shaped the way it is, not just *how* to use it. AI agents working on this codebase: this is the context behind every design decision. ## The Core Insight From 539931baeab1dfea3d778974ecbcbaa591dbf374 Mon Sep 17 00:00:00 2001 From: Brian M Hunt Date: Tue, 21 Apr 2026 10:35:39 -0400 Subject: [PATCH 2/5] Small contract.md + testing.md trims MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more preamble/prose tightening candidates found in the same pass as the previous commit: - `agents/contract.md`: The meta-bullet under "## Replace X With Y" ("This section is about replacing ad-hoc DOM/event/state handling with bindings, not about binding- syntax style.") was mixed into a list of actionable replacement rules. Lifted out into a one-sentence lead-in above the list so the bullets stay pure guidance. - `agents/testing.md`: Trailing paragraph after the Option 1 example was three clauses that repeated what the example already showed. Compressed to one line, kept the `tko.js`-vendoring caveat intact. Adversarial pass: Explore subagent. Flagged 3 items; 2 valid, 1 rejected: - (valid) An earlier attempt to tighten the opener to `Scope: ...` broke tonal parity with peer agent docs and read as a metadata tag. Reverted to the original "Use this file when..." phrasing. - (valid) "unless vendored" alone was too generic in JS ecosystem terms (could imply npm / bundled). Restored "vendored locally" to preserve the specific workflow (manual `tko.js` copy into the project). - (rejected) Reviewer preferred the meta-bullet stay inside the Replace X With Y list for "softer framing". Kept the reorg — the meta-statement was a formatting bug in the actionable bullet list, not an aside. Co-Authored-By: Claude Opus 4.7 (1M context) --- tko.io/public/agents/contract.md | 5 +++-- tko.io/public/agents/testing.md | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tko.io/public/agents/contract.md b/tko.io/public/agents/contract.md index 69a47359..2863c00e 100644 --- a/tko.io/public/agents/contract.md +++ b/tko.io/public/agents/contract.md @@ -1,6 +1,6 @@ # TKO Agent Contract -Use this file when deciding how state, bindings, and DOM work should be divided in TKO examples and prototypes. +Use this file when deciding how to divide state, bindings, and DOM work in TKO examples and prototypes. ## Core Rule @@ -10,7 +10,8 @@ Use this file when deciding how state, bindings, and DOM work should be divided ## Replace X With Y -- This section is about replacing ad-hoc DOM/event/state handling with bindings, not about binding-syntax style. +Replace ad-hoc DOM/event/state handling with bindings. Not about binding-syntax style. + - If you are about to do `element.textContent = value`, use the `text` binding. - If you are about to do `element.innerHTML = markup`, first ask whether the content should be plain text instead; prefer the `text` binding by default. Use `html` only when rendering trusted HTML is truly the point. - If you are about to manually create, replace, or reconcile a repeated set of child nodes, use `foreach`. diff --git a/tko.io/public/agents/testing.md b/tko.io/public/agents/testing.md index e1dc3842..179e1b7b 100644 --- a/tko.io/public/agents/testing.md +++ b/tko.io/public/agents/testing.md @@ -35,7 +35,7 @@ Workflow: 3. Navigate Playwright to `http://localhost:8765/tko-test.html` 4. Read `document.title` or snapshot the DOM to verify -This is the fastest option — no esbuild and no network dependency on the playground, though Option 1 still fetches `https://tko.io/lib/tko.js` unless you vendor that file locally. Works for all `data-bind` code. +Fastest option — no esbuild, no playground. Still fetches `https://tko.io/lib/tko.js` unless vendored locally. Works for all `data-bind` code. ## Option 2: Playground via Playwright (JSX/TSX) From d485d7352ce6bd24743f794dc48a9aafb57de615 Mon Sep 17 00:00:00 2001 From: Brian M Hunt Date: Tue, 21 Apr 2026 10:41:15 -0400 Subject: [PATCH 3/5] Fix wrong DOM selectors in playground references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit testing.md + process.md instructed agents to query the playground DOM by `#id` (e.g. `#preview`, `#console-messages`, `#esbuild-status`, `#compile-time`, `#error-bar`). None of those IDs exist. The playground uses `data-role` attribute selectors throughout (`tko.io/src/playground/shell.ts`): - `[data-role="preview"]` — iframe (line 54) - `[data-role="console-messages"]` — console output container (line 61) - `[data-role="status"]` — generic status element shows "esbuild ready" label (shell.ts:67 + runner-iife.ts:64) - `[data-role="compile-time"]` — compile elapsed (line 68) - `[data-role="error-bar"]` — hidden until a build error (line 55) Replaced every `#foo` playground reference in both files with the correct attribute selector. The `#esbuild-status` → `[data-role="status"]` mapping is worth calling out specifically: the element is generic (handles loading → ready → error states), not esbuild-specific; the doc notes that the label text becomes "esbuild ready" so an agent grepping the snapshot still has the right string to look for. Not a regression — these selector bugs pre-date this branch. Found while reviewing testing.md for correctness after the earlier preamble-strip pass; AGENTS.md had already migrated its playwright flow to process.md in PR #349, so the fix had a single home (no stale copy left behind). Adversarial pass: Explore subagent cross-referenced every selector against `tko.io/src/playground/shell.ts` + `runner-iife.ts`. Result: clean, all five mappings match actual DOM. Co-Authored-By: Claude Opus 4.7 (1M context) --- tko.io/public/agents/process.md | 2 +- tko.io/public/agents/testing.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tko.io/public/agents/process.md b/tko.io/public/agents/process.md index eb222f2a..399d826c 100644 --- a/tko.io/public/agents/process.md +++ b/tko.io/public/agents/process.md @@ -77,7 +77,7 @@ For pages with runnable TSX examples, also run the headless Playwright flow: - Use `playwright-cli` in headless mode. Do not use headed/browser-stealing runs unless the user explicitly asks for them. - Prefer a live Astro dev server on `127.0.0.1:4321` so markdown/plugin edits reload while you work (`bun run dev` in `tko.io/`). - Verify each `Open in Playground` button on the page; if a page has multiple TSX examples, check every one, not just the first. -- Standard flow: `playwright-cli close-all`, `playwright-cli open http://127.0.0.1:4321/...`, inspect the snapshot for playground refs, click each button, switch to the playground tab, and confirm `#esbuild-status`, `#compile-time`, and `#error-bar`. +- Standard flow: `playwright-cli close-all`, `playwright-cli open http://127.0.0.1:4321/...`, inspect the snapshot for playground refs, click each button, switch to the playground tab, and confirm `[data-role="status"]` (shows "esbuild ready"), `[data-role="compile-time"]`, and `[data-role="error-bar"]`. - Treat docs example work as incomplete until the emitted playground payload compiles cleanly on the live site. Generator-owned files: see the note at the top of this document under "Never ship docs that reference things that don't exist on the target branch." diff --git a/tko.io/public/agents/testing.md b/tko.io/public/agents/testing.md index 179e1b7b..5573409b 100644 --- a/tko.io/public/agents/testing.md +++ b/tko.io/public/agents/testing.md @@ -53,22 +53,22 @@ const url = `https://tko.io/playground#${hash}` 4. The code auto-compiles and runs in the preview iframe 5. Read the iframe content or console output to verify -The playground forwards console messages from the iframe to the parent page — look for `#console-messages` in the DOM for console.log/error output. +The playground forwards console messages from the iframe to the parent page — look for `[data-role="console-messages"]` in the DOM for console.log/error output. ### Checking results -The preview iframe is `#preview`. To read its content: +The preview iframe is `[data-role="preview"]`. To read its content: ```js -const iframe = document.querySelector('#preview') +const iframe = document.querySelector('[data-role="preview"]') const body = iframe.contentDocument.body ``` -Console output appears in `#console-messages` as child elements. +Console output appears in `[data-role="console-messages"]` as child elements. ### Timing -esbuild-wasm takes a few seconds to initialize on first load. The playground shows "esbuild ready" in `#esbuild-status` when it's ready. Code auto-runs after compilation. +esbuild-wasm takes a few seconds to initialize on first load. The playground shows "esbuild ready" in `[data-role="status"]` when it's ready. Code auto-runs after compilation. ## Option 3: Testing doc page examples From 9707f5a1a312c9bc23dc0a18f8e8c22dbafc556b Mon Sep 17 00:00:00 2001 From: Brian M Hunt Date: Tue, 21 Apr 2026 10:47:27 -0400 Subject: [PATCH 4/5] soul.md: restore "Knockout/TKO" framing in opener MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot review on PR #351 noted that the file title ("The Soul of Knockout") and early sections describe Knockout's core model before discussing TKO's extensions (the Provider Architecture section explicitly differentiates TKO from Knockout 3.x). The previous trimmed opener said "TKO is shaped the way it is" — understated the lineage. Changed to "Knockout/TKO is shaped the way it is" so the opener matches the file title + the model-first framing that follows. Adversarial pass: Copilot (external reviewer on PR #351). Flagged 1, valid, addressed. Co-Authored-By: Claude Opus 4.7 (1M context) --- tko.io/public/agents/soul.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tko.io/public/agents/soul.md b/tko.io/public/agents/soul.md index 9e2b4931..4cc092b1 100644 --- a/tko.io/public/agents/soul.md +++ b/tko.io/public/agents/soul.md @@ -1,6 +1,6 @@ # The Soul of Knockout -Read this to understand *why* TKO is shaped the way it is, not just *how* to use it. AI agents working on this codebase: this is the context behind every design decision. +Read this to understand *why* Knockout/TKO is shaped the way it is, not just *how* to use it. AI agents working on this codebase: this is the context behind every design decision. ## The Core Insight From 0154e7231cad047dd88fbf8ad8b04b049bca49aa Mon Sep 17 00:00:00 2001 From: Brian M Hunt Date: Tue, 21 Apr 2026 10:57:49 -0400 Subject: [PATCH 5/5] gitignore: ignore `.claude/` wholesale, not just worktrees MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude Code drops local tooling artifacts under `.claude/` — `scheduled_tasks.lock` from `ScheduleWakeup`, `settings.local.json` from per-user settings, stray files from various subagent flows. Only `.claude/worktrees/` was previously ignored; the rest sat untracked-but-unignored, one accidental `git add .` away from landing on a branch. Broadened the pattern to `.claude/`. Verified: `git ls-files .claude/` returns empty, no historical commits have ever tracked anything under that directory (`git log --all -- .claude/` is empty), so no risk of masking existing tracked files. Fix prompted by finding `.claude/scheduled_tasks.lock` in the working tree after the earlier `ScheduleWakeup` call on this branch — a lockfile that "should not be possible" to leave around is now not possible. Adversarial pass: spot-verified inline — checked `git ls-files` + `git log --all` for any prior tracking of `.claude/` paths (none), confirmed the broadened pattern ignores every observable artefact (`scheduled_tasks.lock`, `settings.local.json`, stray `launch.json`, `worktrees/`). Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cf688e41..be48bc76 100644 --- a/.gitignore +++ b/.gitignore @@ -36,7 +36,7 @@ builds/**/meta .playwright-mcp .playwright-cli test-results/ -.claude/worktrees/ +.claude/ __screenshots__ .dts-tmp/ .nx/