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
39 changes: 39 additions & 0 deletions .github/workflows/strip-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,45 @@ jobs:
if: steps.scope.outputs.run == 'true'
run: dart run tool/strip_sample_features.dart --apply ${{ matrix.flags }}

# `flutter analyze` and `flutter test` only prove the stripped tree still
# builds. They would stay green if the process-only removals silently
# stopped happening, which is the whole point of the strip for an
# adopter, so assert the absence directly. Keep this list in step with
# `_processOnlyPaths` in tool/strip_sample_features.dart.
- name: Assert process-only artifacts are gone
if: steps.scope.outputs.run == 'true'
shell: bash
run: |
set -euo pipefail
leftovers=0
for path in \
.claude \
.github/workflows/issue-refs.yml \
docs/issue-workflow.md \
docs/verification \
scripts/bootstrap-issue-labels.sh \
scripts/dev/check_issue_refs.sh \
test/tooling/epic_coverage_test.dart \
tool/check_epic_coverage.dart
do
if [ -e "$path" ]; then
echo "still present after strip: $path"
leftovers=$((leftovers + 1))
fi
done
# Whole-line match only: tool/README.md documents the marker syntax
# inline, and that sentence is meant to survive.
marker='^[[:space:]]*<!-- strip:process-only (start|end) -->[[:space:]]*$'
if grep -rlE "$marker" --include='*.md' . ; then
echo "a process-only marker survived the strip"
leftovers=$((leftovers + 1))
fi
if [ "$leftovers" -ne 0 ]; then
echo "$leftovers process-only artifact(s) survived the strip."
exit 1
fi
echo "All process-only artifacts were removed."

- name: Install dependencies (after strip)
if: steps.scope.outputs.run == 'true'
run: flutter pub get
Expand Down
20 changes: 20 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Code generation (Freezed, json_serializable, Riverpod) is committed. Regenerate
with `flutter pub run build_runner build --delete-conflicting-outputs` only when
you touch an annotated source.

<!-- strip:process-only start -->
## Workflow

GitHub issues are the single source of truth. Full spec:
Expand Down Expand Up @@ -97,9 +98,24 @@ diff". Every tracked path maps to exactly one epic, enforced by
[`tool/check_epic_coverage.dart`](tool/check_epic_coverage.dart) under
`flutter test`. If no epic fits a change, that is a taxonomy gap: file it,
do not force the nearest label - the parallelism rule below keys on that label.
<!-- strip:process-only end -->

## Acceptance verification

<!-- strip:process-only start -->
### Scope test: would an adopter notice?

This is a starter template, not an app that ships. A criterion proves the
**mechanism** is correct; it is not there to prove the *product* runs. So before
writing one, ask: **would an adopter notice if this were missing?** If answering
it needs a physical device, a custom CA, an Apple certificate, a reachable
backend or store credentials, that answer belongs to the adopter's app, not to
this repository - prove the mechanism at tier 1 or tier 2 here and hand the
residual over. Precedent: koniz-dev/flutter-starter#48, #59, #62 and #108 each
sat blocked for months of calendar time on exactly that (a real device, a custom
CA, an Apple cert, on-device storage inspection) after the mechanism had already
been proven, and all four closed with the residual assigned to the adopter.

Run `./scripts/test/run_acceptance.sh <issue-number>`. It runs the format check,
`flutter analyze`, `flutter test`, and the golden-tagged acceptance tests, tees
every log into `docs/verification/issue-<N>/`, and copies captured PNGs there so
Expand All @@ -118,6 +134,7 @@ Three tiers exist here:
runner opts in with `--run-skipped --tags golden`. Goldens are **evidence, not
a CI gate** - a golden regression will not fail CI, by design.
- **Tier 3 - not drivable here.** Route to `status:needs-uat`.
<!-- strip:process-only end -->

### What this tooling cannot verify

Expand Down Expand Up @@ -160,6 +177,8 @@ make the loop worthless.
reachable API exists here.
- **Coverage thresholds.** [`coverage.yml`](.github/workflows/coverage.yml) is
manual plus weekly, not per-PR.

<!-- strip:process-only start -->
### Which checks a PR gets

Four workflows run on PRs. Only one of them still filters at the workflow
Expand Down Expand Up @@ -344,6 +363,7 @@ reading them.
issue bodies.
- Only one session at a time may hold a `status:in-progress` claim on a given
issue. The claim-then-re-read step in step 7 above is what enforces this.
<!-- strip:process-only end -->

## Conventions

Expand Down
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,13 @@ Users prefer dark mode for better battery life and eye comfort, especially in lo

Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests.

<!-- strip:process-only start -->
> Issues are the single source of truth for what gets worked on, in what order,
> and when it counts as done. Before picking something up, read
> [docs/issue-workflow.md](docs/issue-workflow.md) — it defines the label state
> machine, the acceptance-criteria requirement, and why commits link to issues
> rather than closing them.
<!-- strip:process-only end -->


1. Fork the repository
Expand Down Expand Up @@ -399,6 +401,7 @@ test(auth): add login use case tests
- Keep subject line under 50 characters
- Capitalize first letter of subject
- No period at end of subject
<!-- strip:process-only start -->
- Reference issues in the footer as `Refs koniz-dev/flutter-starter#123`

> **Do not use `Closes`, `Fixes`, or `Resolves`.** GitHub auto-closes an issue
Expand All @@ -407,6 +410,7 @@ test(auth): add login use case tests
> removes the verification gate the workflow exists to enforce. Use the fully
> qualified `owner/repo#N` form so the reference survives being quoted elsewhere.
> See [docs/issue-workflow.md](docs/issue-workflow.md).
<!-- strip:process-only end -->

### Git hooks

Expand Down
10 changes: 10 additions & 0 deletions docs/guides/onboarding/fork-and-customize.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ Naming both samples is the same request as naming neither, so

All three variants are exercised by [`strip-smoke.yml`](../../../.github/workflows/strip-smoke.yml), which applies each one and then runs `flutter analyze` and `flutter test` over the result.

Every variant also removes the machinery that serves the upstream repository's
own issue loop rather than your app: the acceptance-evidence archive under
`docs/verification/`, `docs/issue-workflow.md`, `.claude/agents/`,
`scripts/bootstrap-issue-labels.sh`, the epic-coverage guard and its test, and
the commit-reference check with its workflow (it requires `Refs` pointing at the
upstream tracker, so it would reject your commits). The guards that protect your
app - env-asset, docs, signature and symbol checks, the CI workflows and the git
hooks - all stay. See [`tool/README.md`](../../../tool/README.md) for the full
list and the reasoning.

Then delete or adjust any remaining docs under `docs/features/` that referenced removed modules.

## 5. Remove auth sample (advanced)
Expand Down
25 changes: 25 additions & 0 deletions tool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ code it described changed.
so a stripped tree does not fail `test/docs/doc_symbols_test.dart` over a
feature that is no longer there.

<!-- strip:process-only start -->
## `check_epic_coverage.dart`

Taxonomy guard: every tracked surface maps to **exactly one** `epic:*` label.
Expand All @@ -100,6 +101,7 @@ in the same `epic:*`" rule keys on that label.
It reads paths from version control rather than from the filesystem, so
`strip_sample_features.dart` deleting the sample slices does not make the
sample epics look stale under **Strip smoke**.
<!-- strip:process-only end -->

## `strip_sample_features.dart`

Expand All @@ -114,6 +116,29 @@ flutter analyze
flutter test
```

### Process-only artifacts

Every variant also removes what serves **this repository's issue loop** rather
than the app a fork ships: `docs/verification/` (the acceptance-evidence
archive, by far the largest thing in `docs/`), `docs/issue-workflow.md`,
`.claude/agents/`, `scripts/bootstrap-issue-labels.sh`,
`tool/check_epic_coverage.dart` with `test/tooling/epic_coverage_test.dart`,
and `scripts/dev/check_issue_refs.sh` with `.github/workflows/issue-refs.yml`.
The last two pairs would actively break a fork: the epic guard shells out to a
labels script that no longer exists, and the refs check rejects any commit that
does not name *this* tracker.

Sections of files a fork keeps are marked in place with
`<!-- strip:process-only start -->` / `<!-- strip:process-only end -->` (see
`CLAUDE.md`, `CONTRIBUTING.md` and this file) rather than listed in the script,
so the two cannot drift. Unbalanced markers are a hard error, reported before
anything is deleted.

Kept deliberately, because they protect the adopter's app rather than this
repository's workflow: `check_env_assets.dart`, `check_docs.dart`,
`doc_signatures.dart`, `doc_symbols.dart`, `ci.yml`, `strip-smoke.yml`, the git
hooks, and `scripts/test/run_acceptance.sh`.

### Golden tree

Edit **`tool/golden/stripped/`** when the stripped baseline should change (e.g. new `AppRoutes`, `main` bootstrap). Mirrored paths include `lib/`, `test/core/routing/` (`app_router_test.dart`, `app_routes_test.dart`), and `integration_test/`. The tree is **excluded from** `flutter analyze` via `analysis_options.yaml` so it does not conflict with the real `lib/`.
Expand Down
Loading
Loading