Fix/steering canonical example#85
Merged
Merged
Conversation
The four foundation steering files scaffolded by `ctx init` --
product.md, tech.md, structure.md, workflow.md -- were still
their original placeholder bodies in this project. With
`inclusion: always` and `priority: 10`, that means every tool
call in every AI session has been injecting "Describe the
product, its goals, and target users" and similar fill-in-the-
blank prompts into the agent's context as if they were
behavioral rules.
ctx is the canonical example of ctx usage. A clone-and-read
reader sees scaffolded placeholders and concludes the maintainer
didn't fill them in -- which is precisely what happened. This
commit fixes the example by example, before any docs or
tooling changes.
Each file is now project-specific and intentionally non-
overlapping with CONSTITUTION.md / CONVENTIONS.md / CLAUDE.md:
steering carries the "behavioral rules tied to prompt" layer
that adds to those, rather than duplicating them.
- product.md (50 lines): load-bearing constraints (local-first,
single binary, git-friendly, tool-agnostic, no telemetry) and
explicit out-of-scope items (cloud sync, embedded LLM,
AI-tool lock-in).
- tech.md (63 lines): Go 1.26 statically linked, foreign-
language assets via //go:embed (cross-reference to
internal/assets/README.md), separately-published VS Code
extension, hard constraints (no CGO, no runtime deps, no
network in normal operation), companion MCP servers.
- structure.md (66 lines): top-level directory table; where new
files go (extend existing internal/ packages, sibling tools/
for dev tooling about embedded assets, editors/ for
separately-published deliverables); where they do not (not in
internal/assets/ unless actually embedded).
- workflow.md (70 lines): branch-before-commit, never-push, DCO
sign-off, Spec trailer on every commit, lint+test before
commit, conventional subject prefixes, no `_ =` discards / no
panic, persistence cadence (ctx commit / decision / learning
add as you go).
The self-documenting HTML comment from each scaffold ("delete
this comment once you've customized the file") was removed, per
its own instruction.
This commit fixes the symptom on this project only. The
underlying class of bug -- unmodified placeholders silently
contaminating every prompt -- needs the tombstone mechanism
proposed by the maintainer (tombstone string in scaffold + load-
time skip + opt-out flag); a follow-up commit will land that.
Spec: specs/internal-assets-readme.md
Signed-off-by: Jose Alekhinne <jose@ctx.ist>
Unfilled foundation steering files scaffolded by `ctx steering init` were silently injected into the agent context packet on every tool call. With `inclusion: always` and `priority: 10` defaults, that meant "Describe the product, its goals, and target users" and similar fill-in-the-blank prompts were being prepended to every agent turn until the user customized them. This affected every steering consumer: `ctx agent` (Claude Code / Codex hook path), MCP `ctx_steering_get` (mid-task Claude fetches), and `ctx steering sync` (Cursor / Cline / Kiro native exports). This commit introduces a literal "tombstone" marker that the scaffold writes into each foundation body. The marker is HTML- comment-shaped (invisible in Markdown rendering, distinctive enough for reliable detection) and language-neutral (literal string match, not natural-language heuristic, so non-English body customizations still remove it). The user removes the line as part of customizing the file. As long as the line is present, every consumer skips the file: - `ctx agent` (internal/cli/agent/core/steering/steering.go): LoadBodies skips tombstoned files and emits a warn.Warn line per skip so direct CLI users see the breadcrumb. Hook contexts swallow stderr (per hooks.json's `2>/dev/null`); the goal there is just to stop the contamination, not to nag. - MCP ctx_steering_get (internal/mcp/handler/steering.go): same skip + warn.Warn. MCP host (Claude Code) surfaces subprocess stderr in its MCP server logs. - `ctx steering sync` (internal/steering/sync.go): SyncTool and StaleFiles both skip tombstoned files. Tombstoned files appear in the SyncReport's Skipped list rather than being silently written into `.cursor/rules/`, `.clinerules/`, or `.kiro/steering/`. Files: - internal/config/steering/steering.go: defines Tombstone as a package-level const (single source of truth; tombstone.go in internal/steering/ re-exports for convenience). - internal/steering/tombstone.go + tombstone_test.go: the detection function `HasTombstone(body string) bool`, plus five unit tests covering present / absent / empty / partial-match / mid-body cases. - internal/config/warn/warn.go: adds SteeringUnfilled format string for the stderr breadcrumb. (Audit conventions require user-facing strings to live in config/, not as inline literals in handler code.) - internal/assets/commands/text/write.yaml: adds the tombstone line to each of the four foundation body templates (product, tech, structure, workflow). New `ctx steering init` runs scaffold with the marker; existing pre-change scaffolds do not have it (see migration note below). - internal/steering/sync_test.go: adds two integration tests: SyncTool_SkipsTombstonedFile (verifies the native export skip) and StaleFiles_SkipsTombstonedFile (verifies the staleness check skip). Migration note: existing users with pre-change unfilled scaffolded files do NOT have the new marker, so the load-time skip won't catch them; they continue to leak placeholders until either re-scaffolded or manually edited. The follow-up docs reweight (commit pending) will surface this. What this commit does not do: - It does not make `ctx steering init` refuse to re-run when existing files still have tombstones. That was a secondary ask; the load-time skip stops the actual harm, and forcing re-init to error would interfere with idempotency. Can be added as a separate follow-up if needed. - It does not add an enhanced `--no-steering` flag that also removes the steering directory. `ctx init --no-steering-init` already exists for opt-out; the directory-removal extension was tagged "maybe" in the proposal and is left for a follow- up if usage shows the need. Spec: specs/internal-assets-readme.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
The earlier section "1. Initialize Context" carried five paragraphs of steering guidance buried inside it -- the four foundation files, the inclusion-mode defaults, the "open each file and replace the placeholder content" call to action, and the opt-out flag. In practice readers walked past the prose, deferred steering customization, and never came back. The canonical example of this failure mode was visible in ctx's own repo: even the maintainer had not filled in his own scaffolded steering files (fixed in commit a2e2c29). This commit reweights the Quick Start so steering gets the narrative weight its consequences warrant: - Step 1 (Initialize Context) keeps the `ctx init` invocation and adds a brief forward-pointer mentioning the four foundation files exist as placeholders. The five-paragraph steering deep-dive moves out. - NEW Step 2 (Customize Your Steering Files) is the promoted beat. Frames steering as "behavioral rules prepended to every AI prompt," lists the four files with what to fill in, and -- this is the new content from the tombstone mechanism in commit 415b1d6 -- explicitly states that scaffolded files ship with a tombstone marker and are silently skipped on every load path until the marker is removed. Includes the opt-out path (`--no-steering-init`) for users who don't want steering at all. - Steps 3-7 (was 2-6) renumber. The chronological order is preserved: init scaffolds the files, then the user customizes them, then activates the project. The new ordering reflects what users actually need to do, not what hides easily in the prose. site/ regenerated via `make site`. Only the source MD page and its two consumers (search.json + the page's own index.html) changed; the nav structure itself didn't, so the rebuild is small. Spec: specs/internal-assets-readme.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
CONSTITUTION mandates "No Broken Windows" / "Completion Over Motion": fix obvious issues when encountered, no half measures. The brand convention `ctx` (monotype backtick wherever possible, frontmatter titles being the documented exception) had drifted across the entire docs tree. A programmatic sweep caught 236 bare `ctx` tokens across 81 source files and wrapped each one in backticks, preserving content already inside backtick spans and code fences. The sweep respects: - Triple-backtick fenced code blocks, including indented fences inside MkDocs `!!!` admonitions (caught a regression on first pass where indented JSON inside admonitions was corrupted; FENCE regex now matches `^\s*` + triple-backtick to handle both root-level and indented fences). - Existing inline-code spans on the same line (parser tracks backtick pairs and never wraps `ctx` inside an already- protected range). - Frontmatter reserved keys (title, name, description, icon) and image alt-text (![ctx]) -- per the documented exception for frontmatter titles, which avoid backticks entirely. - Link-reference definitions: `[name]: url "title"` lines. - The copyright-header comment block at the top of every file: `# / ctx:`. - Package identifiers via `@`: `ctx@activememory-ctx` left intact (added `@` to the word-exclusion set after seeing this pattern in install snippets). Known false-positives that the detector flags but the transform correctly left alone: 13 multi-line inline-code spans (the open backtick is on one line, the close on the next). CommonMark permits this; the transform's line-at-a- time logic detects the unclosed-on-this-line state and treats the rest of the line as protected, which is the right behavior. The detector is line-scoped, so it can't see across line boundaries and registers false positives. Two outright corruptions surfaced during validation and were fixed manually: - docs/home/context-files.md:532 -- a multi-line code span the transform misjudged in its second-line content, leaving ``ctx` steering preview` (double-backtick + orphan close). Reverted to the original `ctx steering preview`. - docs/reference/comparison.md:218 -- same pattern: the transform produced ``ctx` serve` from a multi-line span; reverted to `ctx serve`. One YAML frontmatter breakage on docs/blog/2026-02-03-the- attention-budget.md: the sweep wrapped `ctx` inside a `topics:` list-item, producing `- `ctx` primitives` which is invalid YAML (a value starting with backtick is not a valid unquoted scalar). The fix follows the documented frontmatter exception -- drop backticks in YAML metadata, since the bare word is fine in that surface (YAML topics are tags-like metadata, not rendered prose). site/ regenerated via `make site`. The sweep touched 81 source files; the regen produced corresponding changes in the published site output (every page's nav also rebuilds when the source set changes, hence the larger total file count). Spec: specs/internal-assets-readme.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
After the brand-backtick sweep (commit 61aab85) surfaced three classes of breakage (admonition-indented fences, multi-line inline-code spans, YAML list-item values), the underlying skip-set requirements for any future programmatic sweep across docs/ are worth persisting. The next contributor doing em-dash replacement, brand rename, or i18n string extraction will hit the same edge cases. Spec: specs/internal-assets-readme.md Signed-off-by: Jose Alekhinne <jose@ctx.ist>
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.
No description provided.