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 .claude/agents/doc-engineer.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Documentation claims are code claims; verify them. Before reporting done you **m

The gates that bite:

- **Shipped-only.** Every behavior claim is cross-checked against `docs/progress.md`; planned features are labeled "coming in a future update."
- **Shipped-only.** Every behavior claim is cross-checked against the Status snapshot and shipped scoreboard in `work-consolidation.md` (the single source of truth since 2026-09-14); planned features are labeled "coming in a future update." The old `docs/progress.md` is archived and must not be cited as current.
- **Help Book ↔ `docs/user/` parity.** Regenerate `InterlinedList.helpindex` with `hiutil` after any HTML change (document the manual step if `hiutil` is unavailable — never fake the index).
- **No `<script>` tags** in Help Book HTML — grep to prove it. `plutil -lint` every `Info.plist` you touch.
- **Links resolve; coverage-matrix flips** correspond to wave consumers exercising the row end-to-end; recompute totals (never paste a number).
Expand Down
7 changes: 5 additions & 2 deletions .claude/skills/doc-engineer/assets/docs-quality-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@

## Project-specific gates

- **Shipped-only rule.** Every claim about app behavior is cross-checked against `docs/progress.md`. Planned features are labeled "coming in a future update."
- **Shipped-only rule.** Every claim about app behavior is cross-checked against the **Status snapshot** and shipped scoreboard in `work-consolidation.md` — the single source of truth since 2026-09-14. Planned features are labeled "coming in a future update." *(This rule pointed at `docs/progress.md` until 2026-09-14; that file is the M0–M7 build journal, was last updated 2026-06-25, and now lives in `docs/archive/`. Do not cite it as current.)*
- **Help Book ↔ `docs/user/` parity.** The Help Book HTML page mirrors the wording of the matching `docs/user/<page>.md`. Divergence is a maintenance bug.
- **`hiutil` rerun.** After any HTML page change, regenerate `InterlinedList.helpindex`. Document the run (or the manual-step requirement if `hiutil` is unavailable).
- **No `<script>` tags** in Help Book HTML. Grep before declaring done.
- **`plutil -lint`** on every `Info.plist` you touched.
- **Coverage matrix flips** correspond to wave consumers actually exercising the row end-to-end; recompute totals against the matrix, do not paste.
- **Same-date update-history entries are merged**, not stacked.
- **Read-only paths.** `PLAN.md`, `ORCHESTRATION.md`, `docs/decisions/**` are off-limits.
- **Read-only paths.** `docs/decisions/**` is off-limits — decision records are amended by superseding them, never edited in place. *(`PLAN.md` and `ORCHESTRATION.md` were also listed here until 2026-09-14; both were deleted from the repo in `f040954` and the rule no longer applies to them.)*
- **Same-PR doc sync — the anti-drift rule.** A PR that ships a `G`-item, closes a parity issue, or changes app behavior **must update `work-consolidation.md` in the same PR**: flip the scoreboard entry, and refresh the test baseline if it moved. Do not defer this to a later "docs pass."

> **Why this rule exists.** Between 2026-09-07 and 2026-09-13, seven PRs (#67–#73) shipped without the master doc moving once. The doc drifted ~330 tests and two API re-measures behind the code, and six issues it described as open had already shipped. A doc updated only in dedicated docs passes will always drift; one updated by the PR that invalidates it cannot.
11 changes: 9 additions & 2 deletions .claude/skills/swift-engineer/assets/e2e-gate-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,16 @@ Every changed behavior ships with at least four BDD-named cases:
5. `swift test --package-path Packages/InterlinedPersistence`
→ report count; confirm no regression.

6. `grep -rn "import InterlinedKit" App/Features App/Navigation App/MenuCommands 2>/dev/null`
6. `grep -rnE "^[[:space:]]*(@[A-Za-z]+ )?import InterlinedKit" App/Features App/Navigation App/MenuCommands 2>/dev/null`
→ must produce zero hits (Decision 0003). Report the result line explicitly even when empty.

> **Anchor the pattern.** The unanchored `grep -rn "import InterlinedKit" …` this
> checklist used until 2026-09-14 matched **prose comments** as well as code — four
> files (`ProfileRootView`, `ProfileHeaderView`, `ProfileViewModel`, `OnboardingView`)
> carry comments saying a file *does not* import Kit, so the check reported four hits
> while the rule genuinely passed. A check that cries wolf gets ignored; keep the
> `^[[:space:]]*` anchor so only real import statements match.

7. **Contract tests** (env-gated): if `INTERLINEDLIST_EMAIL` / `INTERLINEDLIST_PASSWORD` are set, the kit's `ContractTests` exercise the live API. State whether they ran or were skipped; never invent credentials.

## View-layer rule
Expand All @@ -49,5 +56,5 @@ Do not write tests that render SwiftUI views. Test view models against `*Servici

- Build failure → fix the build before reporting.
- Test regression in a package you did not touch → investigate; do not paper over.
- New `import InterlinedKit` hit in `App/Features/**` → add the missing domain model in `InterlinedDomain` and re-route the feature through it (Decision 0003).
- New `import InterlinedKit` hit in `App/Features/**` → add the missing domain model in `InterlinedDomain` and re-route the feature through it (Decision 0003). Confirm the hit is a real `import` line and not a comment before chasing it.
- pbxproj had to be edited → warn the user that Xcode's SourceKit indexer may need **File → Packages → Reset Package Caches**; xcodebuild is unaffected.
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
## Docs

- [ ] `docs/api-coverage.md` updated if endpoint coverage changed
- [ ] `docs/progress.md` updated if a wave gate moved
- [ ] `work-consolidation.md` updated **in this PR** if it ships a `G`-item, closes a parity issue, or moves the test baseline (same-PR doc-sync rule)
- [ ] New decision recorded under `docs/decisions/` if architecture changed
15 changes: 13 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@ Native macOS **SwiftUI** client for InterlinedList: Xcode project `InterlinedLis
- `Packages/InterlinedPersistence` — SwiftData stores + on-disk cache
- `SyncAgent/` — background menu-bar doc-sync utility

Master planning doc: `work-consolidation.md`. Detailed checklists live in `.claude/skills/*/assets/` (the single source of truth).
**Master planning doc: `work-consolidation.md` — THE single source of truth.** It owns the plan:
ordering, architecture, probe evidence, API shapes, the re-measure log, the release path, and a work
index (§1f) mapping every item to its GitHub issue. **GitHub issues own execution** — live status,
and what PRs link to. Epic #66 is a pointer to the doc, not a second backlog. When the doc and an
issue disagree, the issue wins and the doc gets corrected.

⚠️ **Same-PR doc-sync rule.** A PR that ships a `G`-item, closes a parity issue, or moves the test
baseline **must update `work-consolidation.md` in the same PR**. Seven PRs (#67–#73) once shipped
without it moving; it drifted ~330 tests and two API re-measures behind the code.

Detailed checklists live in `.claude/skills/*/assets/`. `docs/progress.md` is **archived** (M0–M7 build
journal, last updated 2026-06-25) — do not cite it as current.

## Non-negotiable rules

Expand All @@ -24,7 +35,7 @@ No change is "done" until the gate in `.claude/skills/swift-engineer/assets/e2e-
- `xcodebuild -scheme InterlinedList -destination 'platform=macOS' build` → `** BUILD SUCCEEDED **`
- `xcodebuild -scheme InterlinedList -destination 'platform=macOS' test` (App target)
- `swift test --package-path Packages/{InterlinedKit,InterlinedDomain,InterlinedPersistence}`
- `grep -rn "import InterlinedKit" App/Features App/Navigation App/MenuCommands` → zero hits
- `grep -rnE "^[[:space:]]*(@[A-Za-z]+ )?import InterlinedKit" App/Features App/Navigation App/MenuCommands` → zero hits *(anchored: the unanchored form matches prose comments and reports four false positives)*

Ship the BDD unit-test quartet (happy / invalid / upstream-failure / boundary) with every behavior change. Docs work has its own gate: `.claude/skills/doc-engineer/assets/docs-quality-checklist.md`.

Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

InterlinedList for macOS mirrors every capability of the [InterlinedList web app](https://interlinedlist.com), organized as native macOS features: a timeline, a composer window, structured lists with a schema DSL, an offline-capable Markdown document store, social and organization features, notifications, and Settings &mdash; all backed by the documented [InterlinedList API](https://interlinedlist.com/help/api).

The project is greenfield. Scope, architecture, milestones, and branding are pinned in [PLAN.md](PLAN.md); orchestration rules live in [ORCHESTRATION.md](ORCHESTRATION.md). Progress is recorded in [docs/progress.md](docs/progress.md) and endpoint coverage in [docs/api-coverage.md](docs/api-coverage.md).
Scope, architecture, milestones, remaining work and shipped status are consolidated in [work-consolidation.md](work-consolidation.md) &mdash; **the single source of truth** &mdash; with per-endpoint coverage in [docs/api-coverage.md](docs/api-coverage.md) and architectural rationale in [docs/decisions/](docs/decisions/). The historical M0&ndash;M7 build log is archived at [docs/archive/progress.md](docs/archive/progress.md). *(`PLAN.md` and `ORCHESTRATION.md` were removed in `f040954`; links to them are retired.)*

## Status

Expand Down Expand Up @@ -66,7 +66,7 @@ AppTests/ # App-target XCTest (BDD-named)
docs/ # progress, api-coverage, decisions, spikes, user guides
```

See [PLAN.md §3](PLAN.md) for the rules at each boundary &mdash; in particular the kit-import policy from [Decision 0003](docs/decisions/0003-kit-import-policy.md): the App target imports `InterlinedKit` only from the composition root.
The rules at each boundary are recorded in [docs/decisions/](docs/decisions/) &mdash; in particular the kit-import policy from [Decision 0003](docs/decisions/0003-kit-import-policy.md): the App target imports `InterlinedKit` only from the composition root.

## Building

Expand Down Expand Up @@ -106,14 +106,14 @@ The CI workflow does **not** run contract tests. Credentials must never be commi

## Documentation

- [PLAN.md](PLAN.md) &mdash; product scope, architecture, milestones, branding (authoritative).
- [ORCHESTRATION.md](ORCHESTRATION.md) &mdash; how work is sequenced and how agents own paths.
- [docs/progress.md](docs/progress.md) &mdash; running log of waves, gates, deviations.
- [docs/decisions/](docs/decisions/) &mdash; architectural decision records (authoritative on boundaries and exceptions).
- [work-consolidation.md](work-consolidation.md) &mdash; **the single source of truth**: what ships, what remains, in execution order.
- [docs/archive/progress.md](docs/archive/progress.md) &mdash; archived M0&ndash;M7 wave log (historical; last updated 2026-06-25).
- [docs/api-coverage.md](docs/api-coverage.md) &mdash; endpoint matrix.
- [docs/decisions/](docs/decisions/) &mdash; recorded architecture decisions.
- [docs/spikes/](docs/spikes/) &mdash; investigations and probes against the live API.
- [docs/user/](docs/user/) &mdash; end-user guides.

## Branding

All visual identity follows the [official InterlinedList branding standards](https://interlinedlist.com/help/branding). The product name is **InterlinedList** &mdash; capital I, capital L, no spaces or hyphens. See [PLAN.md §9](PLAN.md) for the palette, typography, and asset rules used throughout the app.
All visual identity follows the [official InterlinedList branding standards](https://interlinedlist.com/help/branding). The product name is **InterlinedList** &mdash; capital I, capital L, no spaces or hyphens. The palette, typography and asset rules are applied in `App/Resources` and the theme tokens under `App/Theme`.
Loading