point the editor preview at the demo, and shorten the skill name
Four small things from one sitting, none of which would be reverted without the others: - .claude/launch.json describes the only dev server this repo has: make demo on localhost:8080. Deliberately not autoPort — examples/demo-site declares base: http://localhost:8080, so canonical, hreflang, OpenGraph and sitemap URLs are built from that port, and a reassigned one would make the absolute URLs on the page wrong while still rendering fine. - The skill is .claude/skills/feature-loop/, without the khosra- prefix. ADR-0054 records it, because ADR-0030 had named the prefixed form while settling the project name and decisions.md is append-only. - Makefile .PHONY was missing quiet and surface, added two commits ago. A file of either name in the repo root would have silently shadowed the target. - A latent row: the root listing's title reads "A Khosra Demo · A Khosra Demo", because base.html joins page title and site title unconditionally and at the root they are the same string. Found by looking at the served page — no test asserts a title. Theme layer, one if, and it waits for Phase G4.
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.0.1",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "demo",
|
||||||
|
"runtimeExecutable": "make",
|
||||||
|
"runtimeArgs": ["demo"],
|
||||||
|
"port": 8080
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -86,7 +86,7 @@ the test: `docs/architecture.md`.
|
|||||||
## 4. The loop (every request, no exceptions)
|
## 4. The loop (every request, no exceptions)
|
||||||
|
|
||||||
`Clarify → Plan → Implement → Verify → Document → Commit → Report`.
|
`Clarify → Plan → Implement → Verify → Document → Commit → Report`.
|
||||||
Procedure: `.claude/skills/khosra-feature-loop/SKILL.md`. The three gates people skip:
|
Procedure: `.claude/skills/feature-loop/SKILL.md`. The three gates people skip:
|
||||||
|
|
||||||
**Clarify.** Only questions whose answer changes the code or the bytes on disk. Max three,
|
**Clarify.** Only questions whose answer changes the code or the bytes on disk. Max three,
|
||||||
batched, up front, each with a **bold** default so silence answers. Never about naming, formatting,
|
batched, up front, each with a **bold** default so silence answers. Never about naming, formatting,
|
||||||
|
|||||||
+5
-1
@@ -7,7 +7,8 @@ before code, docs that stay true.
|
|||||||
constitution (always loaded). `docs/` is what the agent needs to build the
|
constitution (always loaded). `docs/` is what the agent needs to build the
|
||||||
engine — anything in it may be pulled into context on demand. `ideas/` and `reference/` sit outside
|
engine — anything in it may be pulled into context on demand. `ideas/` and `reference/` sit outside
|
||||||
`docs/` deliberately: storage, opened only when you name a file, swept by nothing.
|
`docs/` deliberately: storage, opened only when you name a file, swept by nothing.
|
||||||
`.claude/` holds the feature-loop skill and six commands. `scripts/` holds the gate.
|
`.claude/` holds the feature-loop skill (`skills/feature-loop/`), six commands, and `launch.json`.
|
||||||
|
`scripts/` holds the gate.
|
||||||
|
|
||||||
## How you use it
|
## How you use it
|
||||||
|
|
||||||
@@ -56,6 +57,9 @@ because a reference theme that grows taste stops being a reference (ADR-0026).
|
|||||||
edit it and serve it with `make demo`. It stays true by two gates: a coverage test in `internal/web` serves it
|
edit it and serve it with `make demo`. It stays true by two gates: a coverage test in `internal/web` serves it
|
||||||
through the real handler with one case per feature, and `verify.sh` runs `khosra check` over it. A feature added
|
through the real handler with one case per feature, and `verify.sh` runs `khosra check` over it. A feature added
|
||||||
without a case there is a feature the demo does not show, and the build says so (ADR-0051).
|
without a case there is a feature the demo does not show, and the build says so (ADR-0051).
|
||||||
|
`.claude/launch.json` points the editor's preview at that same `make demo` on `localhost:8080`, so
|
||||||
|
"look at it" and "test it" are the one site. It is the only dev server this repo has: the engine serves
|
||||||
|
a site root and there is nothing else to run.
|
||||||
|
|
||||||
**The agent names the layer as well as the primitive.** Content on disk, engine, theme, browser — and it builds
|
**The agent names the layer as well as the primitive.** Content on disk, engine, theme, browser — and it builds
|
||||||
at the outermost layer that can do the job (`CLAUDE.md` §2, `docs/architecture.md`). This exists because a whole
|
at the outermost layer that can do the job (`CLAUDE.md` §2, `docs/architecture.md`). This exists because a whole
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ SITE ?= $(KHOSRA_SITE)
|
|||||||
ADDR ?= localhost:8080
|
ADDR ?= localhost:8080
|
||||||
BIN := ./khosra
|
BIN := ./khosra
|
||||||
|
|
||||||
.PHONY: help build run check new demo test verify fmt tidy clean
|
.PHONY: help build run check new demo test verify quiet surface fmt tidy clean
|
||||||
|
|
||||||
help: ## list targets
|
help: ## list targets
|
||||||
@grep -hE '^[a-z]+:.*##' $(MAKEFILE_LIST) | sed 's/:[^#]*## /|/' | column -t -s '|'
|
@grep -hE '^[a-z]+:.*##' $(MAKEFILE_LIST) | sed 's/:[^#]*## /|/' | column -t -s '|'
|
||||||
|
|||||||
@@ -813,3 +813,17 @@ is discipline, and it says so instead of implying enforcement (rule 8).
|
|||||||
Revisit if: the surface grows past a few hundred lines, in which case it is per-package files rather than
|
Revisit if: the surface grows past a few hundred lines, in which case it is per-package files rather than
|
||||||
one; or `surface.md` churn starts drowning real diffs, which is the argument for generating it on demand
|
one; or `surface.md` churn starts drowning real diffs, which is the argument for generating it on demand
|
||||||
instead of tracking it.
|
instead of tracking it.
|
||||||
|
|
||||||
|
## ADR-0054 — The feature-loop skill drops its `khosra-` prefix
|
||||||
|
Date: 2026-08-01 · Status: accepted (amends ADR-0030's skill-name clause only; the rest of that naming
|
||||||
|
decision stands)
|
||||||
|
Decision: the skill directory is `.claude/skills/feature-loop/`, not `khosra-feature-loop`.
|
||||||
|
Why: the human asked, and the prefix was redundant — every file in this repository is khosra's, so a
|
||||||
|
`khosra-` prefix inside it distinguishes nothing. ADR-0030 named the skill as part of settling the
|
||||||
|
project's name, which made sense while `atelier` was still being erased; it does not survive contact
|
||||||
|
with the fact that the skill is only ever loaded from this repo.
|
||||||
|
Consequence: cheap — a shorter name in the one place it is written (`CLAUDE.md` §4) and in the skill
|
||||||
|
listing. ADR-0030 keeps its original text because `decisions.md` is append-only, so a reader who lands
|
||||||
|
there sees the old name; this entry is the pointer that makes it resolvable.
|
||||||
|
Revisit if: the skill is ever published or shared outside this repo, where an unprefixed `feature-loop`
|
||||||
|
would collide with everyone else's.
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ with a stated reason. A list nothing drains is a graveyard of known defects.
|
|||||||
| `date` stays in `Extra` after being lifted onto `Bundle.Date`, unlike `title`, `aliases`, `tags` and `order`, which are deleted | Spotted while adding `order`; the theme contract says `Extra` holds what the parser does not name, so one of the two is wrong. Harmless today — a template reading `.Extra.date` gets the raw YAML value | Whatever next reads `Extra` generically: feeds (queue 14) or `check` (17) |
|
| `date` stays in `Extra` after being lifted onto `Bundle.Date`, unlike `title`, `aliases`, `tags` and `order`, which are deleted | Spotted while adding `order`; the theme contract says `Extra` holds what the parser does not name, so one of the two is wrong. Harmless today — a template reading `.Extra.date` gets the raw YAML value | Whatever next reads `Extra` generically: feeds (queue 14) or `check` (17) |
|
||||||
| A gallery's images carry no `alt` | `width`/`height` now come from the original (ADR-0042), so only alt text is missing, and a filename does not supply one. An empty `alt` is honest for a picture the page has already introduced | Captions per gallery entry — a sidecar or a frontmatter list — if the reference theme ever needs them |
|
| A gallery's images carry no `alt` | `width`/`height` now come from the original (ADR-0042), so only alt text is missing, and a filename does not supply one. An empty `alt` is honest for a picture the page has already introduced | Captions per gallery entry — a sidecar or a frontmatter list — if the reference theme ever needs them |
|
||||||
| Sequence resolution rescans the index on every bundle request — two passes over every key, each doing a `Lookup` | Measured at the same time as the pictures (ADR-0044): a whole page is ~63µs, so this is not what costs anything. Remembering it would be a cache with no measurement behind it | A page render exceeding a few milliseconds, which is also what would revive the parked cache model |
|
| Sequence resolution rescans the index on every bundle request — two passes over every key, each doing a `Lookup` | Measured at the same time as the pictures (ADR-0044): a whole page is ~63µs, so this is not what costs anything. Remembering it would be a cache with no measurement behind it | A page render exceeding a few milliseconds, which is also what would revive the parked cache model |
|
||||||
|
| The root listing's `<title>` repeats itself — "A Khosra Demo · A Khosra Demo" | Spotted 2026-08-01 by looking at the served page, not by any test: `base.html` joins page title and site title unconditionally, and at the root those are the same string. Cosmetic, and the fix is one `if` in a template — theme layer, not engine | The first time the reference theme is worked on (Phase G4 touches it), or sooner if a feed or OpenGraph title inherits the same doubling |
|
||||||
| The picture memo is never evicted — one entry per picture on the site, for the life of the process | Correct for one author's site, and the alternative is an eviction policy nothing needs. It is keyed on size and modification time, so it cannot go stale, only grow | A site root large enough that memory matters, or a long-running process where pictures churn |
|
| The picture memo is never evicted — one entry per picture on the site, for the life of the process | Correct for one author's site, and the alternative is an eviction policy nothing needs. It is keyed on size and modification time, so it cannot go stale, only grow | A site root large enough that memory matters, or a long-running process where pictures churn |
|
||||||
|
|
||||||
## Open questions
|
## Open questions
|
||||||
|
|||||||
Reference in New Issue
Block a user