kss explainer · 04 · the .kss/ file system

Where everything lives.

kss state is plain markdown under .kss/ at the project root. No database, no compiled state, no hidden caches — every artifact is a file you can grep, diff, and commit. This page surfaces who writes which file, who reads it, how it changes over time, and which design choices are worth knowing about before you start naming things.

The findings below capture the design choices most people don't notice on first read. The tabs that follow are the full surface — switch across root / codebase / topics / spikes to see every file.

Finding 01

Presence of SUMMARY.md = shipped.

No separate "status: shipped" flag. The filesystem itself encodes the state. A milestone folder with PLAN.md but no SUMMARY.md is active; once SUMMARY appears, it's shipped.

Finding 02

One pointer, and it lives in frontmatter.

There is no .kss/STATE.md. The single non-derivable fact — active_topic — sits in PROJECT.md frontmatter. The active milestone is derived: read that topic's STATE.md active_milestone. One pointer, zero double-writes.

Finding 03

Reruns overwrite — except the parts that shouldn't.

STACK overwrites whole on every map-codebase rerun; STRUCTURE / CONVENTIONS overwrite their body but preserve a ## Learned fence. VOCABULARY is fully append-only. The shape changes; what distill taught it sticks.

.kss/ at a glance
.kss/
├── PROJECT.md identity + pointer
├── CANONICAL-KB.md append · cross-topic
├── codebase/ 4 files · STACK / STRUCTURE / CONVENTIONS / VOCABULARY
├── topics/ one folder per topic · 5 state files + milestones/ · archived stay put
└── spikes/ date-prefixed folders · throwaway with verdict

Two files sit at the very root of .kss/. PROJECT.md carries identity, the topics index, the single active pointer, and cross-topic handoffs; CANONICAL-KB.md accumulates distilled knowledge over time. There is no longer a .kss/STATE.md — the project pointer moved into PROJECT.md frontmatter.

PathWritten byRead byNotes
.kss/PROJECT.md identity pointer · frontmatter append · ## Carryover scaffold-project · new-topic · complete-milestone all skills Durable identity + topics index. Frontmatter holds active_topic — the single project pointer (with last_session / last_updated). A ## Carryover (cross-topic handoffs) section collects trigger-gated items logged by complete-milestone and claimed by new-topic. Archived topics' rows move to a ## Archived Topics heading here.
.kss/CANONICAL-KB.md append · cross-topic distill all skills (implicit context) Durable learnings & gotchas distilled from LOG / SEEDS / spike findings across all topics. One of distill's four destinations (the others: codebase ## Learned fences and VOCABULARY.md). The closest thing to "what we've learned about this project."

Four files capture the shape and language of the codebase. Three overwrite on each map-codebase rerun (because the codebase changes); the fourth is append-only (because vocabulary sticks).

PathWritten byRead byNotes
codebase/STACK.md overwrite map-codebase start-session · plan-milestone Languages, frameworks, runtimes, package managers, key infra. Snapshot-style — rerun map-codebase to refresh.
codebase/STRUCTURE.md overwrite · body preserved · ## Learned map-codebase (body) · distill (## Learned) start-session · plan-milestone Directory tree, module map, entry points. Body overwrites on rerun; a ## Learned fence (structure facts written by distill) is preserved across reruns — without that, remapping would wipe distilled knowledge.
codebase/CONVENTIONS.md overwrite · body preserved · ## Learned map-codebase (body) · distill (## Learned) start-session · plan-milestone Naming, formatting, idioms. The "don't fight the style" reference. Body overwrites on rerun; the ## Learned fence (pattern facts from distill) is preserved across reruns.
codebase/VOCABULARY.md append · seeded map-codebase (seed) · distill (grow) start-session · all skills Domain terms with definitions. Append-only — survives map-codebase reruns. Seeded once, then grown by distill from session terminology.

Every topic gets a folder under .kss/topics/<slug>/. Five state files at the topic root, plus a milestones/ subdirectory for the finite chunks of work inside.

PathWritten byRead byNotes
topics/<slug>/TOPIC.md identity marker · status new-topic · complete-milestone --archive-topic start-session · plan-milestone · complete-milestone Topic identity, success bar, key decisions. Frontmatter status: active|archivedarchiving flips this flag, it does not move the folder. Skills exclude status: archived topics from active listings. Stable otherwise — edit only when scope genuinely changes.
topics/<slug>/STATE.md content · durable pointer · active_milestone transient · ## Scratch wrap-up · start-session start-session Current Position + Blockers for THIS topic (durable). Frontmatter active_milestone is the single source of truth for the active milestone. A ## Scratch fence isolates rot-prone env facts; start-session re-verifies Scratch instead of re-asserting it. (There is no project-level STATE.md.)
topics/<slug>/LOG.md append · newest-on-top wrap-up start-session · distill Session-by-session entries. Terse — what shipped, what blocked, what's next. Newest entry at the top so cold-loading the page surfaces recent context first.
topics/<slug>/SEEDS.md append capture distill Parked items, each with a trigger condition. Seeds without triggers are refused by capture — items that can't fire on a condition just rot.
topics/<slug>/MILESTONES.md append · newest-on-top complete-milestone start-session Shipped milestone summaries. Newest at the top. The "what shipped in this topic, in order" reference.
topics/<slug>/milestones/<v>-<slug>/PLAN.md content plan-milestone start-session · complete-milestone The plan for this specific milestone. Anchors the work — drift mid-execution is mitigated by re-reading this.
topics/<slug>/milestones/<v>-<slug>/SUMMARY.md marker complete-milestone distill · MILESTONES.md author Presence of this file is the signal. Folder with PLAN but no SUMMARY → active milestone. Folder with both → shipped. No flags, no metadata; just the filesystem.
topics/<slug>/milestones/<v>-<slug>/note-YYYYMMDD-*.md content (optional) wrap-up (optional) · spike start-session Optional session notes. Date-prefixed for natural ordering. Written when wrap-up has more to record than fits in LOG.md.

Spikes are throwaway exploration with verdicts — they live outside the active topic tree so they don't pollute current work. (Wondering where archived topics go? They don't move — see the note below.)

PathWritten byRead byNotes
spikes/YYYYMMDD-<slug>/README.md content · verdict spike distill · complete-milestone Question, approach, findings, and a verdict (keep / drop / promote). Date-prefixed folder name. Throwaway by design — the verdict is what matters, not the artifact.
.kss/archive/ legacy · not created (collision checks only) No longer a folder move. Archiving sets status: archived in TOPIC.md and moves the topic's row to PROJECT.md ## Archived Topics — the directory stays in topics/. .kss/archive/ is legacy only; existing dirs are left in place and still checked for slug collisions.
Related paths · outside .kss/

Files kss uses, elsewhere.

  • ~/kss-skill-reports/<skill>.md personal Misfire reports written by skill-autopsy. Per-user, never committed to plugin source. Path is intentional — keeps your friction out of public artifacts.
  • ~/.kss-source optional Single-line file containing the path to your local clone of the marketplace. Only relevant if you fork to apply autopsy diffs locally. Plain installs ignore it.
  • /tmp/explorer-<slug>.html ephemeral Throwaway HTML artifacts from explore-html. May pull from CDN. Don't expect them to persist.
  • .kss/topics/<slug>/explorers/*.html optional Persistent HTML artifacts (if explore-html was asked to save under a topic). Offline-safe — vanilla or vendored libraries only.
Conventions · file-format rules

Hold the shape together.

  • YAML frontmatter on every state file. Easy to grep, easy to parse, easy to diff.
  • Newest-on-top in LOG.md and MILESTONES.md. Cold-load shows recent context first. No scrolling to find "where am I."
  • Slugs are kebab-case. auth-rewrite, not AuthRewrite or auth_rewrite.
  • Dates: ISO YYYY-MM-DD in frontmatter; YYYYMMDD as folder/file prefixes. Sortable both ways. Hyphens for prose, no hyphens for paths.
  • Active vs. shipped milestone is marked by SUMMARY.md presence. No status flag.
  • Active vs. archived topic is a status: archived flag in TOPIC.md — not a folder move. The directory stays in topics/; grep 'status: archived' is the trail. Resolves the old inconsistency with "presence is the marker — don't move folders."
  • Seeds require triggers. No exceptions. Items without trigger conditions rot — capture refuses them.
  • Detect-and-offer, never silently mutate. Skills detect a condition and offer the next action behind a one-keystroke confirm; they never auto-fire a state change.
  • Never auto-commit. Skills modify files; you commit. Trust is earned by being legible.
  • Single project pointer. active_topic lives in PROJECT.md frontmatter — there is no .kss/STATE.md. The active milestone is derived from the active topic's STATE.md active_milestone (its single source of truth). start-session migrates any legacy .kss/STATE.md on first run.
  • Durable vs. transient state. Topic STATE.md keeps durable Position/Blockers; rot-prone env facts go under a ## Scratch fence. start-session re-verifies Scratch rather than re-asserting it.
  • Cross-topic handoffs live in PROJECT.md ## Carryover. complete-milestone logs trigger-gated items there; new-topic offers to claim them.
  • distill has four destinations. Learnings/gotchas → CANONICAL-KB; structure & pattern facts → codebase ## Learned fences (preserved across map-codebase reruns); terms → VOCABULARY.