Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/memory/_shared/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Optional top-level field (7t5a). A YAML sequence of glob/pathspec patterns ident

**Purpose — attribution, NOT exclusion.** `test_paths` does NOT strip lines from the impact universe — it *attributes* the already-scaffolding-excluded lines to tests vs. implementation, so reviewers see the split (e.g. "140 impl / 400 test") instead of one conflated number. This is orthogonal to `true_impact_exclude`, which removes scaffolding/doc *noise* from the universe entirely. Tests are first-class deliverables (constitution principle VII, Test Integrity), not scaffolding noise — adding test patterns to `true_impact_exclude` was explicitly rejected because it would conflate the two axes and destroy the test-coverage signal.

**No kit default (Portability, constitution principle V).** fab-kit is language-agnostic; there is no universal test-file pattern (`*_test.go`, `test_*.py`, `*.spec.ts` all differ by language). The kit MUST NOT ship a default `test_paths` list — each project declares its own. The scaffold (`src/kit/scaffold/fab/project/config.yaml`) carries only a commented-out `# test_paths: []` placeholder so users discover the knob. This repo dogfoods it with `test_paths: ["**/*_test.go"]`.
**No kit default (Portability, constitution principle V).** fab-kit is language-agnostic; there is no universal test-file pattern (`*_test.go`, `test_*.py`, `*.spec.ts` all differ by language), so the kit MUST NOT ship a hardcoded default `test_paths` list. Instead, the value is **detected per project at setup**: the scaffold (`$(fab kit-path)/scaffold/fab/project/config.yaml`) ships a standing annotated example comment block (Go/Python/JS-TS/Java-Kotlin patterns + the `:(glob)`/anti-substring note) above a `{TEST_PATHS}` placeholder, and `/fab-setup config` create-mode auto-detects the project's ecosystem from on-disk marker files (`go.mod`→Go, `pyproject.toml`→Python, etc.) and fills the anchored pattern **non-interactively**. Unrecognized or inline-test stacks (e.g. Rust) are left empty — the breakdown then collapses to a single total. Existing projects are backfilled by the `2.7.1-to-2.8.0` migration (same detection; skips projects that already set `test_paths`). This repo dogfoods it with `test_paths: ["**/*_test.go"]`.

**Glob/pathspec format.** Include patterns are applied as `:(glob)<pattern>` magic pathspecs in the test-only `git diff --shortstat` pass, so wildcards behave like `.gitignore`-style globs — notably `**` matches across directory boundaries, so `**/*_test.go` matches both root-level `foo_test.go` and nested `pkg/foo_test.go`. (Without `:(glob)`, plain git pathspec rules treat `*` as not crossing `/`, silently missing root-level test files and under-counting tests.) The pass combines these includes with the same `:(exclude)` args derived from `true_impact_exclude`, so tests are counted within the scaffolding-excluded universe; when `true_impact_exclude` is empty, the pass runs with the includes alone (tests attributed within the raw universe).

Expand Down
4 changes: 2 additions & 2 deletions docs/memory/distribution/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ description: "How the kit is packaged, shipped & configured — .kit/ structure,
|------|-------------|
| [distribution](distribution.md) | How `src/kit/` is distributed — Homebrew formula (2 binaries direct + 2 via `depends_on`), `fab` router (always-route policy), `fab-kit` lifecycle, `fab init` bootstrap, `fab upgrade-repo` (offline-first default = installed binary's `systemVersion`; `--latest` opts into the GitHub-API newest-release path; explicit arg wins; `dev`/unstamped → network fallback — 1hmj), release workflow (3 binaries, 12 cross-compiled, `SHA256SUMS` for kit-* archives, `just test` gate before tag/build + `go-version-file` single-sourcing — tb6f), hardened auto-download (bounded HTTP timeouts, version-keyed flock + atomic rename, digest verification) + fail-loud lifecycle exit contracts (`init`/`update`/`upgrade-repo`/`sync`), `wt shell-setup` wrapper; the `shll.ai/fab-kit` public docs site — README-slice pull (`ReadmeSlice.astro`) + producer-side README-conformance obligation (tail boundary at `## Development`, diagram SVGs by absolute raw URL, absolute external slice links — except README→`docs/site/` links kept repo-relative for the site rewrite) + `docs/` audience-axis layout (pull surface is exactly `README.md` + `docs/site/**`; `docs/site/**` pulled + rendered one page per file at `/tools/fab-kit/<path>`, §9 ACTIVE) |
| [kit-architecture](kit-architecture.md) | `src/kit/` structure (binary-free; `spec.md` template removed in j6cs; `schemas/` removed in c5tr — scaffold no longer seeds `stage_directives`), three-binary architecture (fab router + fab-kit + fab-go), router always-route policy + shared `LifecycleCommands` allowlist table with contract/collision drift tests (ye8r), `fab-kit sync` (post-state version guard, fail-loud deployment writes, version threading from init/upgrade, stamp-after-success upgrade), agent integration, versioning, monorepos, underscore file ecosystem, `fab pane` command group, `fab shell-init`, hidden `fab help-dump`, shared `internal/lines` + `internal/atomicfile` helpers (hv7t), widened `internal/config` single config.yaml parser (ye8r); tb6f: Go 1.26 + cobra v1.10 toolchain, fab-kit `sync.go` split (semver/prereqs/scaffold/skills + orchestrator), golden byte-stability suite as the standing yaml parity arbiter, yaml.v3-stays-pinned decision, `src/benchmark/` tombstoned; frlo: new `reference/` shipped content dir (read via `$(fab kit-path)/reference/...`, holds the `fkf.md` normative extract) + the whole-`src/kit/`-copied-verbatim packaging invariant (new kit content ships with no Go/packaging change); 2fm8: `templates/memory.md` added — canonical FKF memory-file template, the third artifact template, read on demand via `$(fab kit-path)/templates/memory.md` (ships verbatim, no Go/packaging/migration change) |
| [migrations](migrations.md) | Migration system — dual-version model, migration file format, binary-owned discovery (`fab migrations-status [--json]` / `DiscoverMigrations`), `/fab-setup migrations` subcommand (delegates discovery, applies LLM-driven), brew-install migration, `1.8.0-to-1.9.0` migration (tasks-stage collapse + plan.md), `1.9.1-to-1.9.2` migration (`true_impact_exclude` config field), `1.9.7-to-1.10.0` migration (spec-stage collapse, four-state spec.md→plan.md case table), `2.1.6-to-2.2.0` migration (drops dead `stage_directives` + defensive `model_tiers`; preserves `stage_hooks`), `2.2.0-to-2.3.0` migration (fully-commented `agent.tiers` reference block, comment-sentinel idempotency), `2.5.5-to-2.6.0` migration (freeze-on-write `log.md` re-baseline — `fab memory-index --rebuild` + commit, `--rebuild` binary pre-check, no `fab/`/`.status.yaml` change), `2.6.6-to-2.7.0` migration (drop the index `Last Updated` column → two-column index re-baseline — `fab memory-index` + commit, rendered-output binary pre-check, no `fab/`/`.status.yaml` change, VERSION bump to `2.7.0`), version drift detection (`upgrade-repo` mechanical detection + silent self-stamp + TTY-gated styled reminder), `fab/.kit-migration-version` creation |
| [setup](setup.md) | `/fab-setup` skill — structural bootstrap (sync-first order since szxd: doctor → config → constitution → `fab sync`), subcommand architecture (config, constitution, migrations — version handling delegated to a single `fab migrations-status --json` run), delegation pattern with `fab-kit sync`; stage_directives editor removed, semver one-liner restored at the three-way branch, fab_version fresh-create fallback, Next Steps re-aligned to the State Table (c5tr); scaffold fragment merge fails loudly (jznd) and its `.gitignore` dedup is gitignore-aware — variant coverage + negation hard-stop, `.envrc` stays literal (mqiq) |
| [migrations](migrations.md) | Migration system — dual-version model, migration file format, binary-owned discovery (`fab migrations-status [--json]` / `DiscoverMigrations`), `/fab-setup migrations` subcommand (delegates discovery, applies LLM-driven), brew-install migration, `1.8.0-to-1.9.0` migration (tasks-stage collapse + plan.md), `1.9.1-to-1.9.2` migration (`true_impact_exclude` config field), `1.9.7-to-1.10.0` migration (spec-stage collapse, four-state spec.md→plan.md case table), `2.1.6-to-2.2.0` migration (drops dead `stage_directives` + defensive `model_tiers`; preserves `stage_hooks`), `2.2.0-to-2.3.0` migration (fully-commented `agent.tiers` reference block, comment-sentinel idempotency), `2.5.5-to-2.6.0` migration (freeze-on-write `log.md` re-baseline — `fab memory-index --rebuild` + commit, `--rebuild` binary pre-check, no `fab/`/`.status.yaml` change), `2.6.6-to-2.7.0` migration (drop the index `Last Updated` column → two-column index re-baseline — `fab memory-index` + commit, rendered-output binary pre-check, no `fab/`/`.status.yaml` change, VERSION bump to `2.7.0`), `2.7.1-to-2.8.0` migration (detect + fill `test_paths` from on-disk markers + refresh the scaffold example comment block, sentinel-guarded, preserves non-empty user values, config-only, VERSION bump to `2.8.0`), version drift detection (`upgrade-repo` mechanical detection + silent self-stamp + TTY-gated styled reminder), `fab/.kit-migration-version` creation |
| [setup](setup.md) | `/fab-setup` skill — structural bootstrap (sync-first order since szxd: doctor → config → constitution → `fab sync`), subcommand architecture (config, constitution, migrations — version handling delegated to a single `fab migrations-status --json` run), delegation pattern with `fab-kit sync`; stage_directives editor removed, semver one-liner restored at the three-way branch, fab_version fresh-create fallback, Next Steps re-aligned to the State Table (c5tr); scaffold fragment merge fails loudly (jznd) and its `.gitignore` dedup is gitignore-aware — variant coverage + negation hard-stop, `.envrc` stays literal (mqiq); Config Create-Mode non-interactively detects + fills `test_paths` from on-disk markers via the `{TEST_PATHS}` placeholder, with a visible note (5qf5) |
10 changes: 9 additions & 1 deletion docs/memory/distribution/migrations.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
type: memory
description: "Migration system — dual-version model, migration file format, binary-owned discovery (`fab migrations-status [--json]` / `DiscoverMigrations`), `/fab-setup migrations` subcommand (delegates discovery, applies LLM-driven), brew-install migration, `1.8.0-to-1.9.0` migration (tasks-stage collapse + plan.md), `1.9.1-to-1.9.2` migration (`true_impact_exclude` config field), `1.9.7-to-1.10.0` migration (spec-stage collapse, four-state spec.md→plan.md case table), `2.1.6-to-2.2.0` migration (drops dead `stage_directives` + defensive `model_tiers`; preserves `stage_hooks`), `2.2.0-to-2.3.0` migration (fully-commented `agent.tiers` reference block, comment-sentinel idempotency), `2.5.5-to-2.6.0` migration (freeze-on-write `log.md` re-baseline — `fab memory-index --rebuild` + commit, `--rebuild` binary pre-check, no `fab/`/`.status.yaml` change), `2.6.6-to-2.7.0` migration (drop the index `Last Updated` column → two-column index re-baseline — `fab memory-index` + commit, rendered-output binary pre-check, no `fab/`/`.status.yaml` change, VERSION bump to `2.7.0`), version drift detection (`upgrade-repo` mechanical detection + silent self-stamp + TTY-gated styled reminder), `fab/.kit-migration-version` creation"
description: "Migration system — dual-version model, migration file format, binary-owned discovery (`fab migrations-status [--json]` / `DiscoverMigrations`), `/fab-setup migrations` subcommand (delegates discovery, applies LLM-driven), brew-install migration, `1.8.0-to-1.9.0` migration (tasks-stage collapse + plan.md), `1.9.1-to-1.9.2` migration (`true_impact_exclude` config field), `1.9.7-to-1.10.0` migration (spec-stage collapse, four-state spec.md→plan.md case table), `2.1.6-to-2.2.0` migration (drops dead `stage_directives` + defensive `model_tiers`; preserves `stage_hooks`), `2.2.0-to-2.3.0` migration (fully-commented `agent.tiers` reference block, comment-sentinel idempotency), `2.5.5-to-2.6.0` migration (freeze-on-write `log.md` re-baseline — `fab memory-index --rebuild` + commit, `--rebuild` binary pre-check, no `fab/`/`.status.yaml` change), `2.6.6-to-2.7.0` migration (drop the index `Last Updated` column → two-column index re-baseline — `fab memory-index` + commit, rendered-output binary pre-check, no `fab/`/`.status.yaml` change, VERSION bump to `2.7.0`), `2.7.1-to-2.8.0` migration (detect + fill `test_paths` from on-disk markers + refresh the scaffold example comment block, sentinel-guarded, preserves non-empty user values, config-only, VERSION bump to `2.8.0`), version drift detection (`upgrade-repo` mechanical detection + silent self-stamp + TTY-gated styled reminder), `fab/.kit-migration-version` creation"
---
# Migrations

Expand Down Expand Up @@ -118,6 +118,14 @@ A migration file for the transition to the system shim model. The migration:
- **Idempotent (Constitution III).** Re-running `fab memory-index` + commit on an already two-column tree is a no-op diff (nothing to commit), and the two-column pre-check still passes. After the baseline, `fab memory-index --check` exits **0 or 1, never 2** (a re-baselined tree is provably never destructive-loss); the `--check` exit-code contract is unchanged.
- **Version bump.** `src/kit/VERSION` is bumped to `2.7.0` (the migration's target version) — a behavior change to a shipped CLI warrants a minor bump, matching the catalog's `2.5.5-to-2.6.0` / `2.4.2-to-2.5.0` feature-migration convention.

### `2.7.1-to-2.8.0` Backfill Migration (detect & fill `test_paths` — 5qf5)

`src/kit/migrations/2.7.1-to-2.8.0.md` backfills `test_paths` in existing projects' `fab/project/config.yaml`, mirroring the new Config Create-Mode detection (see [setup.md](/distribution/setup.md) § Config Create-Mode Detects & Fills `test_paths`). `test_paths` drives the `/git-pr` impact breakdown's test/impl split, ships language-specific with no kit default, and most projects never set it — so the split silently does nothing. The migration has two effects: (a) **refresh the scaffold's `test_paths` example comment block** so users keep an editing reference even when the key stays empty, and (b) **detect + fill `test_paths`** from on-disk marker files via the same anchored marker→ecosystem table the create-mode skill uses (Go/Python/JS-TS/Java-Kotlin/.NET; Rust & unrecognized → empty, since inline `#[cfg(test)]` tests are not glob-addressable).

- **Config-only, no binary/`.status.yaml` change.** Unlike the re-baseline migrations above (`2.5.5-to-2.6.0`, `2.6.6-to-2.7.0`), this one needs **no binary capability pre-check** — `impact.go` already consumes any non-empty `test_paths` verbatim, and detection is pure prompt logic (Constitution I). It is the config-field-add shape, like `1.9.1-to-1.9.2` (`true_impact_exclude`) and `2.2.0-to-2.3.0` (`agent.tiers`): Summary / Pre-check / Changes / Verification, atomic write.
- **Idempotent + value-preserving (Constitution III).** Pre-check skips entirely when `config.yaml` is absent. The comment-block refresh is **sentinel-guarded** on the `# Examples (uncomment/adapt the line for your stack):` line (re-run no-op). The fill happens **only when `test_paths` is absent or empty** — a user's hand-set non-empty value is preserved unchanged (only the comment block refreshes). Report lines mirror the create-mode notes (detected ecosystem + patterns, or "no test convention detected → left empty").
- **Version bump.** `src/kit/VERSION` is bumped to `2.8.0` (the migration's target version) — an additive config-feature change is a minor bump, matching the catalog's feature-migration convention.

### Version Drift Detection

- **`fab upgrade-repo`**: after sync, runs `DiscoverMigrations` against the target version's cached `migrations/` dir and the current `fab/.kit-migration-version` (mechanical relevance check, not string inequality). Three terminal cases:
Expand Down
19 changes: 18 additions & 1 deletion docs/memory/distribution/setup.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
type: memory
description: "`/fab-setup` skill — structural bootstrap (sync-first order since szxd: doctor → config → constitution → `fab sync`), subcommand architecture (config, constitution, migrations — version handling delegated to a single `fab migrations-status --json` run), delegation pattern with `fab-kit sync`; stage_directives editor removed, semver one-liner restored at the three-way branch, fab_version fresh-create fallback, Next Steps re-aligned to the State Table (c5tr); scaffold fragment merge fails loudly (jznd) and its `.gitignore` dedup is gitignore-aware — variant coverage + negation hard-stop, `.envrc` stays literal (mqiq)"
description: "`/fab-setup` skill — structural bootstrap (sync-first order since szxd: doctor → config → constitution → `fab sync`), subcommand architecture (config, constitution, migrations — version handling delegated to a single `fab migrations-status --json` run), delegation pattern with `fab-kit sync`; stage_directives editor removed, semver one-liner restored at the three-way branch, fab_version fresh-create fallback, Next Steps re-aligned to the State Table (c5tr); scaffold fragment merge fails loudly (jznd) and its `.gitignore` dedup is gitignore-aware — variant coverage + negation hard-stop, `.envrc` stays literal (mqiq); Config Create-Mode non-interactively detects + fills `test_paths` from on-disk markers via the `{TEST_PATHS}` placeholder, with a visible note (5qf5)"
---
# Setup

Expand Down Expand Up @@ -30,6 +30,23 @@ description: "`/fab-setup` skill — structural bootstrap (sync-first order sinc
- Creates `.gitignore` entries
- Safe to re-run (idempotent — skips existing files)

### Config Create-Mode Detects & Fills `test_paths` (5qf5)

As of 260626-5qf5, `/fab-setup config` **create mode** auto-detects and fills `test_paths` from on-disk marker files — **non-interactively** (no prompt). After asking for project name/description/source_paths (step 2), it reads markers and derives an **anchored** test-path pattern from a marker→ecosystem table:

| Detected marker | Ecosystem | `test_paths` |
|---|---|---|
| `go.mod` | Go | `**/*_test.go` |
| `pytest.ini` / `pyproject.toml` / `setup.cfg` | Python (pytest) | `**/test_*.py`, `**/*_test.py` |
| `package.json` (jest/vitest), or `*.spec`/`*.test` `.ts`/`.js` present | JS/TS | `**/*.spec.ts`, `**/*.test.ts`, `**/*.spec.js`, `**/*.test.js` |
| `pom.xml` / `build.gradle` | Java/Kotlin | `**/src/test/**` |
| `*.csproj` (test SDK) | .NET | `**/*Tests.cs`, `**/*Test.cs` |
| `Cargo.toml` (Rust) / *(no marker)* | — | leave empty (Rust tests are inline `#[cfg(test)]`, not glob-addressable) |

The derived value is substituted as the new `{TEST_PATHS}` placeholder (step 4, alongside `{PROJECT_NAME}`/`{PROJECT_DESCRIPTION}`/`{SOURCE_PATHS}`), **preserving the scaffold's standing example comment block** and replacing only the active key line. Config Output surfaces a visible note: `Detected {ecosystem} — set test_paths to {patterns}. Edit fab/project/config.yaml if wrong.` when filled, or `No test convention detected — test_paths left empty (impact breakdown will show a single total). Set it later if desired.` for Rust/unrecognized stacks. Multi-marker repos take the union of pattern sets.

**Why anchored, not a substring**: `test_paths` drives the `/git-pr` impact breakdown's test/impl split (`impl = total − tests`). A bare substring (`**/*test*`) miscounts production code like `attestation.go`/`latest.go` — a confidently-wrong number is worse than the absent (collapsed-to-single-total) breakdown, so unrecognized stacks are left empty. The `2.7.1-to-2.8.0` migration backfills the same detection for existing repos (see [migrations.md](/distribution/migrations.md)).

### Subcommands

`/fab-setup` accepts three subcommands: `config [section]`, `constitution`, and `migrations [file]`. These provide ongoing management of initialization artifacts and version migrations without requiring separate commands. Validation is built into the `config` and `constitution` flows rather than exposed as a standalone subcommand.
Expand Down
Loading
Loading