@launchsecure/launch-kit 0.0.33 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/chart-serve.js +167 -2
- package/dist/server/cli.js +249 -41
- package/dist/server/council-entry.js +0 -0
- package/dist/server/course-entry.js +1 -1
- package/dist/server/fb-wizard.js +0 -0
- package/dist/server/graph-mcp-entry.js +180 -4
- package/dist/server/init-entry.js +438 -43
- package/dist/server/launch-radar-entry.js +45 -0
- package/dist/server/parse-worker-entry.js +167 -2
- package/dist/server/radar-docker-init-entry.js +444 -39
- package/dist/server/radar-entrypoint-entry.js +0 -0
- package/dist/server/radar-teardown-entry.js +23 -22
- package/dist/server/rover-entry.js +20122 -0
- package/package.json +28 -25
- package/scaffolds/ls-marketplace/plugins/kit/commands/standup.md +6 -6
- package/scaffolds/ls-marketplace/plugins/kit/skills/analyse/SKILL.md +6 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/brief/SKILL.md +40 -48
- package/scaffolds/ls-marketplace/plugins/kit/skills/debug/SKILL.md +45 -20
- package/scaffolds/ls-marketplace/plugins/kit/skills/deploy-check/SKILL.md +76 -67
- package/scaffolds/ls-marketplace/plugins/kit/skills/handoff/SKILL.md +132 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/ship/SKILL.md +149 -133
- package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
- package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
|
@@ -1,144 +1,151 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Production-readiness check for the current branch — typecheck, lint, build,
|
|
2
|
+
description: Production-readiness check for the current branch — branch freshness, typecheck, lint, build, schema/migration drift, migration safety, env coverage, and recent LS comms. Stack-agnostic: detects the project's toolchain (Node/Python/Go/Rust/Ruby/JVM/.NET/PHP) and migrations tooling at runtime, runs the detected command per check, and skips with a reason where a stack has no equivalent. Read-only; reports a go/no-go punch list. Does NOT deploy.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# /kit:deploy-check
|
|
6
6
|
|
|
7
|
-
Audit the current branch for production readiness. Bundles every signal a human would manually check before clicking "deploy" or merging to a deploy-tracked branch (
|
|
7
|
+
Audit the current branch for production readiness. Bundles every signal a human would manually check before clicking "deploy" or merging to a deploy-tracked branch (default: `master`/`main`). Reports a punch list with ✓ / ⚠ / ✗ per check and a single go/no-go verdict.
|
|
8
|
+
|
|
9
|
+
This skill ships with `launch-kit init` into **any** project, so it makes **no stack assumptions**. Preflight step 5 detects the toolchain and the migrations tooling once; every check below runs the *detected* command, and any check with no equivalent on this stack is **skipped with a visible reason** rather than failing or running a tool the repo doesn't have.
|
|
8
10
|
|
|
9
11
|
Parse `$ARGUMENTS`:
|
|
10
|
-
- (empty) — full check on the current branch vs
|
|
12
|
+
- (empty) — full check on the current branch vs the default branch.
|
|
11
13
|
- **--target=<branch>** — compare against a different deploy-tracked branch.
|
|
12
14
|
- **--skip=<check,…>** — comma-separated checks to skip (e.g. `--skip=lint,build`). Use sparingly; surface skipped checks in the report.
|
|
13
|
-
- **--quick** — skip the build (the slowest check). Still runs
|
|
15
|
+
- **--quick** — skip the build (the slowest check). Still runs the rest.
|
|
14
16
|
- **--json** — emit a machine-readable report (per check: ok, detail, durationMs).
|
|
15
17
|
|
|
16
18
|
Examples:
|
|
17
19
|
- `/kit:deploy-check`
|
|
18
20
|
- `/kit:deploy-check --quick`
|
|
19
21
|
- `/kit:deploy-check --skip=lint`
|
|
20
|
-
- `/kit:deploy-check --target=staging
|
|
22
|
+
- `/kit:deploy-check --target=staging --json`
|
|
21
23
|
|
|
22
24
|
## Preflight
|
|
23
25
|
|
|
24
26
|
1. Confirm cwd is a git repo (`git rev-parse --is-inside-work-tree`).
|
|
25
|
-
2. Resolve the target branch — `--target=` if given, else default branch (`git symbolic-ref refs/remotes/origin/HEAD --short` → strip `origin/`; fall back to `master`).
|
|
26
|
-
3. Print the scope upfront: `"deploy-check: <current-branch> → <target-branch>"`.
|
|
27
|
-
4. Stash check — if `git status --porcelain` shows uncommitted changes, surface
|
|
27
|
+
2. Resolve the target branch — `--target=` if given, else default branch (`git symbolic-ref refs/remotes/origin/HEAD --short` → strip `origin/`; fall back to `master`/`main`).
|
|
28
|
+
3. Print the scope upfront: `"deploy-check: <current-branch> → <target-branch>"`.
|
|
29
|
+
4. Stash check — if `git status --porcelain` shows uncommitted changes, surface a `⚠ uncommitted changes in working tree` row at the top. Don't refuse; some workflows want uncommitted work included.
|
|
30
|
+
5. **Detect the project stack** (this is what makes the skill portable — resolve once, reuse below). Identify the project family from its manifest, then resolve the per-check command. **Always prefer an explicit script/target the repo defines** (a `package.json` script, a `Makefile` target like `build`/`lint`/`test`, a `justfile` recipe) over the language default — a defined script encodes the project's real intent.
|
|
31
|
+
|
|
32
|
+
| Family | Marker | typecheck | lint | build | env-ref grep |
|
|
33
|
+
|---|---|---|---|---|---|
|
|
34
|
+
| Node | `package.json` (PM from lockfile: pnpm/yarn/bun/npm; `RUN=<pm> run`) | `<RUN> typecheck` else `npx tsc --noEmit` **only if `tsconfig.json`**; else skip | `<RUN> lint` if defined | `<RUN> build` if defined | `process\.env\.[A-Z_]+` in `*.ts,*.tsx,*.js,*.mjs,*.cjs` |
|
|
35
|
+
| Python | `pyproject.toml`/`requirements.txt`/`setup.py` | `mypy`/`pyright` if configured, else skip | `ruff check`/`flake8` if configured | build script if defined (often none) | `os\.environ\[`, `os\.getenv\(`, `getenv\(` in `*.py` |
|
|
36
|
+
| Go | `go.mod` | `go vet ./...` | `golangci-lint run` if present | `go build ./...` | `os\.Getenv\(` in `*.go` |
|
|
37
|
+
| Rust | `Cargo.toml` | `cargo check` | `cargo clippy` | `cargo build --release` | `env::var\(`, `std::env::var` in `*.rs` |
|
|
38
|
+
| Ruby | `Gemfile` | `srb tc` if sorbet, else skip | `rubocop` if present | build script if defined | `ENV\[` in `*.rb` |
|
|
39
|
+
| JVM | `pom.xml`/`build.gradle(.kts)` | (compile = build) | checkstyle/ktlint if configured | `mvn -q package` / `gradle build` | `System\.getenv\(` in `*.java,*.kt` |
|
|
40
|
+
| .NET | `*.csproj`/`*.sln` | (compile = build) | `dotnet format --verify-no-changes` if present | `dotnet build -c Release` | `Environment\.GetEnvironmentVariable\(` in `*.cs` |
|
|
41
|
+
| PHP | `composer.json` | `phpstan`/`psalm` if present | `php-cs-fixer`/`phpcs` if present | build script if defined | `getenv\(`, `\$_ENV\[` in `*.php` |
|
|
42
|
+
| unknown | — | skip | skip | skip (look for a `Makefile`/`justfile` `build` target first) | skip env_coverage |
|
|
43
|
+
|
|
44
|
+
Also resolve, reusing the same detection `/kit:ship` uses:
|
|
45
|
+
- **`MIGRATIONS_DIR`** — `prisma/migrations/` · `supabase/migrations/` · `drizzle/` (or a dir with `drizzle/meta/`) · `db/migrate/` (Rails) · `alembic/versions/` · a Django app's `*/migrations/` · `src/main/resources/db/migration/` (Flyway) · a knex/TypeORM/Sequelize dir, or **`none`**. A config-declared `migrationsPath` wins.
|
|
46
|
+
- **`MIGRATION_TOOL`** — prisma / supabase / drizzle / rails / alembic / django / flyway / knex / typeorm / sequelize / `none`. Drives whether a *drift* command exists (check 5).
|
|
47
|
+
- **`ENV_EXAMPLE`** — `.env.testing` if it exists, else `.env.example`, else `none`.
|
|
48
|
+
|
|
49
|
+
Record the resolved command set and print a one-line `stack: <family> · pm=<pm> · migrations=<tool|none>` so the user can see what was detected.
|
|
28
50
|
|
|
29
51
|
## Checks
|
|
30
52
|
|
|
31
|
-
Run
|
|
53
|
+
Run independent checks (typecheck/lint/build) in PARALLEL. Each returns `{ name, status: "ok"|"warn"|"fail"|"skip", detail: <one-line>, artifact?: <path|url> }`. **A check with no detected command is `skip` with a reason — never `fail`.**
|
|
32
54
|
|
|
33
55
|
### 1. branch_freshness
|
|
34
56
|
|
|
35
|
-
How far behind the target branch is the current branch?
|
|
36
|
-
|
|
37
57
|
```
|
|
38
58
|
git fetch --quiet origin
|
|
39
59
|
git rev-list --left-right --count <target>...HEAD
|
|
40
60
|
```
|
|
41
|
-
|
|
42
61
|
- ✓ `0 commits behind target` → fresh
|
|
43
62
|
- ⚠ `1–10 behind`
|
|
44
63
|
- ✗ `>10 behind` → suggest `git merge origin/<target>` or rebase
|
|
45
64
|
|
|
46
65
|
### 2. typecheck
|
|
47
66
|
|
|
48
|
-
`
|
|
49
|
-
|
|
67
|
+
Run `TYPECHECK_CMD` from Preflight. If none for this stack, `⚠ typecheck skipped — no typecheck configured for <family>`.
|
|
50
68
|
- ✓ `0 errors`
|
|
51
|
-
- ✗ `<N> errors` (sample first 3 file:line:message)
|
|
69
|
+
- ✗ `<N> errors` (sample first 3 `file:line:message`)
|
|
52
70
|
|
|
53
71
|
### 3. lint
|
|
54
72
|
|
|
55
|
-
`
|
|
56
|
-
|
|
57
|
-
- ✓ `0 errors`
|
|
58
|
-
- ⚠ `<N> warnings`
|
|
59
|
-
- ✗ `<N> errors`
|
|
73
|
+
Run `LINT_CMD`. If none defined, `⚠ lint skipped — no lint script/linter detected`.
|
|
74
|
+
- ✓ `0 errors` · ⚠ `<N> warnings` · ✗ `<N> errors`
|
|
60
75
|
|
|
61
76
|
### 4. build
|
|
62
77
|
|
|
63
|
-
|
|
78
|
+
Run `BUILD_CMD` (the project's real build, so the check matches CI). Skip if `--quick` or `--skip=build`. If no build command exists for this stack (common for libraries / scripting projects), `⚠ build skipped — no build step detected`.
|
|
79
|
+
- ✓ `built in <durationMs>ms` · ✗ `build failed` (last 20 lines of stderr as artifact)
|
|
64
80
|
|
|
65
|
-
-
|
|
66
|
-
- ✗ `build failed` (last 20 lines of stderr as artifact)
|
|
81
|
+
**DB-safety guard (only when the build touches a DB).** If the detected `BUILD_CMD` runs migrations as part of the build (e.g. a Node build script that chains `prisma migrate deploy`, or any build that applies `MIGRATION_TOOL` migrations — detect by scanning the build script / target), then a prod DB connection string must NOT be used. If the relevant connection env (`DATABASE_URL`, `DB_URL`, etc.) looks production-y (matches `neon.tech`, `rds.amazonaws.com`, `supabase.co`, a `vercel.app` proxy host, etc.), refuse the build step: `⚠ build skipped — build applies migrations and DATABASE_URL looks production-y (<host>); re-run with a dev DB or pass --skip=build`. If the build does NOT touch a DB (most stacks), skip this guard.
|
|
67
82
|
|
|
68
|
-
|
|
83
|
+
### 5. schema_drift (only when MIGRATION_TOOL supports it)
|
|
69
84
|
|
|
70
|
-
|
|
85
|
+
Schema-vs-migrations consistency, using the tool's own drift command:
|
|
86
|
+
- **prisma** — `npx prisma migrate diff --from-schema-datasource prisma/schema.prisma --to-migrations prisma/migrations --shadow-database-url <DEV_SHADOW_URL>`. The diff should be EMPTY (this project hand-authors migrations — see CLAUDE.md). Non-empty = a model change without a migration.
|
|
87
|
+
- **drizzle** — `npx drizzle-kit check` (reports schema/migration mismatch).
|
|
88
|
+
- **rails** — `bin/rails db:abort_if_pending_migrations` against a dev DB (pending = drift).
|
|
89
|
+
- **alembic/django** — `alembic check` / `python manage.py makemigrations --check --dry-run` (a would-be-generated migration = drift).
|
|
90
|
+
- **other / none** — `⚠ schema_drift skipped — no drift command for <tool>` (or skip silently when `MIGRATION_TOOL=none`).
|
|
71
91
|
|
|
72
|
-
|
|
92
|
+
- ✓ `schema matches migrations` · ✗ `<N> drift detected` (surface the diff as an artifact; suggest authoring a migration).
|
|
93
|
+
- If a drift command needs a shadow/dev DB and none is available: `⚠ schema_drift skipped — no shadow/dev DB URL`.
|
|
73
94
|
|
|
74
|
-
|
|
75
|
-
npx prisma migrate diff --from-schema-datasource prisma/schema.prisma --to-migrations prisma/migrations --shadow-database-url <DEV_SHADOW_URL>
|
|
76
|
-
```
|
|
95
|
+
### 6. migration_safety (only when MIGRATIONS_DIR ≠ none)
|
|
77
96
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
- ✓ `schema matches migrations`
|
|
81
|
-
- ✗ `<N> drift detected` — surface the diff body as an artifact; suggest authoring a migration per the project's hand-written SQL convention.
|
|
82
|
-
|
|
83
|
-
If no `DEV_SHADOW_URL` is available, skip this check with `⚠ prisma_drift skipped — no shadow DB URL` and recommend setting one in `.env.local`.
|
|
84
|
-
|
|
85
|
-
### 6. migration_safety
|
|
86
|
-
|
|
87
|
-
Recent migrations on the branch — look at every migration file added since divergence from target:
|
|
97
|
+
If `MIGRATIONS_DIR=none`, skip entirely. Otherwise scan every migration added since divergence:
|
|
88
98
|
|
|
89
99
|
```
|
|
90
|
-
git diff --name-only <target>...HEAD --
|
|
100
|
+
git diff --name-only <target>...HEAD -- <MIGRATIONS_DIR>
|
|
91
101
|
```
|
|
92
102
|
|
|
93
|
-
For
|
|
103
|
+
For **SQL-based** migrations (prisma/supabase/flyway/rails-SQL/alembic-SQL), scan the SQL for risk patterns (per the project's migration-safety discipline):
|
|
104
|
+
- ✓ no destructive ops (`DROP COLUMN`, `DROP TABLE`, `ALTER COLUMN ... DROP`, `DELETE FROM` without a backup-matching `WHERE`).
|
|
105
|
+
- ⚠ destructive ops present BUT a sidecar `CREATE TABLE _backup_*` AND an orphan-check (`RAISE EXCEPTION ... orphans remain`) are present in the same file.
|
|
106
|
+
- ✗ destructive ops without backup OR without orphan-check OR expand+contract mixed in one migration.
|
|
94
107
|
|
|
95
|
-
-
|
|
96
|
-
- ⚠ destructive ops present BUT a sidecar `CREATE TABLE _backup_*` exists in the same file AND an orphan-check (`RAISE EXCEPTION ... orphans remain`) is present.
|
|
97
|
-
- ✗ destructive ops without backup OR without orphan-check OR mixing expand+contract in a single migration.
|
|
108
|
+
For **non-SQL** migration DSLs (Rails Ruby DSL, Django/Alembic Python ops, Drizzle TS), best-effort scan for the tool's destructive ops (`remove_column`, `drop_table`, `op.drop_column`, `.dropColumn`, etc.) and note `partial coverage — non-SQL migration, pattern scan only`.
|
|
98
109
|
|
|
99
110
|
Each failure cites the exact migration filename + line numbers.
|
|
100
111
|
|
|
101
|
-
### 7. env_coverage
|
|
112
|
+
### 7. env_coverage (only when ENV_EXAMPLE ≠ none and an env-ref pattern exists)
|
|
102
113
|
|
|
103
|
-
Compare
|
|
114
|
+
Compare documented keys in `ENV_EXAMPLE` against env references in new code since divergence, using the stack's `env-ref grep`:
|
|
104
115
|
|
|
105
116
|
```
|
|
106
|
-
git diff <target>...HEAD --
|
|
117
|
+
git diff <target>...HEAD -- <stack source globs> | grep -oE '<ENV_REF_PATTERN>'
|
|
107
118
|
```
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
- ✗ N/A (always a warn, never a hard fail — env docs are advisory)
|
|
119
|
+
- ✓ every referenced env var is documented in `ENV_EXAMPLE`
|
|
120
|
+
- ⚠ `<N> new env vars used but missing from <ENV_EXAMPLE>` (list them)
|
|
121
|
+
- env docs are advisory — this is never a hard ✗. If `ENV_EXAMPLE=none`, `⚠ env_coverage skipped — no env example file`.
|
|
112
122
|
|
|
113
123
|
### 8. recent_comms (LS Comm Hub)
|
|
114
124
|
|
|
115
|
-
Pull the last 10 comments tagged `release` or `daily_update` via `mcp__launch-secure__communication_read
|
|
116
|
-
|
|
117
|
-
Skip with a `⚠ launch-secure MCP not wired` row if the MCP isn't available; don't fail the whole check.
|
|
125
|
+
Pull the last 10 comments tagged `release` or `daily_update` via `mcp__launch-secure__communication_read`; surface `"<N> release/standup comments in last 7 days — latest: <title> (<author>, <age>)"`. Informational. Skip with `⚠ launch-secure MCP not wired` if unavailable.
|
|
118
126
|
|
|
119
127
|
### 9. recall_health
|
|
120
128
|
|
|
121
|
-
`mcp__launch-recall__recall_status` —
|
|
122
|
-
|
|
123
|
-
- ✓ `recall alive — last snap <X ago>`
|
|
124
|
-
- ⚠ `recall dead — restart before deploy (\`/kit:recall doctor\` for detail)`
|
|
129
|
+
`mcp__launch-recall__recall_status` — confirms the shadow-git backup is alive so a rollback path exists. Informational.
|
|
130
|
+
- ✓ `recall alive — last snap <X ago>` · ⚠ `recall dead — restart before deploy`. Skip if the MCP isn't wired.
|
|
125
131
|
|
|
126
132
|
## Report
|
|
127
133
|
|
|
128
|
-
Render a punch list (plain text, monospace; not markdown table):
|
|
134
|
+
Render a punch list (plain text, monospace; not a markdown table):
|
|
129
135
|
|
|
130
136
|
```
|
|
131
137
|
deploy-check: implementation → master
|
|
138
|
+
stack: node · pm=npm · migrations=prisma
|
|
132
139
|
|
|
133
140
|
✓ branch_freshness 0 commits behind master
|
|
134
141
|
✓ typecheck 0 errors (3.2s)
|
|
135
142
|
⚠ lint 12 warnings (no errors)
|
|
136
143
|
✓ build built in 47s
|
|
137
|
-
✓
|
|
144
|
+
✓ schema_drift schema matches migrations
|
|
138
145
|
✗ migration_safety 1 destructive op without backup
|
|
139
|
-
→ prisma/migrations/
|
|
146
|
+
→ prisma/migrations/2026_05_25_drop_legacy/migration.sql:14 (DROP COLUMN, no _backup_* sidecar)
|
|
140
147
|
⚠ env_coverage 2 new env vars missing from .env.example: FEED_BACKEND_URL, FEED_TIMEOUT_MS
|
|
141
|
-
✓ recent_comms 1 release comment in last 7 days — "
|
|
148
|
+
✓ recent_comms 1 release comment in last 7 days — "channels rollout" (prajyot, 2d ago)
|
|
142
149
|
✓ recall_health alive — last snap 4m ago
|
|
143
150
|
|
|
144
151
|
verdict: NO-GO — 1 hard fail (migration_safety).
|
|
@@ -147,14 +154,16 @@ next: author a backup table + orphan check in the listed migration, then re-run
|
|
|
147
154
|
|
|
148
155
|
Verdict rules:
|
|
149
156
|
- Any ✗ → NO-GO with the failing check(s) listed.
|
|
150
|
-
- All ✓ +
|
|
157
|
+
- All ✓ + ⚠/skip only → GO WITH CAVEATS, list the warnings + skips.
|
|
151
158
|
- All ✓ → GO.
|
|
159
|
+
- **Skips never fail the gate** — but if every code-quality check (typecheck+lint+build) skipped, add a `⚠ note: no typecheck/lint/build ran for this stack — gate is weak` so a green verdict isn't mistaken for thorough.
|
|
152
160
|
|
|
153
161
|
## Constraints
|
|
154
162
|
|
|
155
163
|
- **Read-only.** Never deploy, never push, never auto-fix.
|
|
156
|
-
- **
|
|
164
|
+
- **No stack assumptions.** Every tool-specific command is resolved by detection in Preflight step 5. If detection comes up empty for a check, skip it with a reason — never run a tool the repo doesn't have, never hard-fail for its absence.
|
|
165
|
+
- **Parallel checks.** Run independent checks concurrently — sequential bloats the wait past usefulness.
|
|
157
166
|
- **No silent skips.** Every skipped check appears in the report with a reason.
|
|
158
|
-
- **DB-safe.**
|
|
159
|
-
- **Honest about scope.** This check is what a human would do manually; it is NOT a guarantee. Surface
|
|
160
|
-
- **
|
|
167
|
+
- **DB-safe.** The build DB-safety guard only triggers when the detected build actually applies migrations; when it does, refuse a production-looking connection string.
|
|
168
|
+
- **Honest about scope.** This check is what a human would do manually; it is NOT a guarantee. Surface: `"This check doesn't run e2e tests, doesn't validate runtime config, doesn't sniff for secrets in commits — those are separate skills."`
|
|
169
|
+
- **launch-chart is optional context only** (e.g. blast radius of a migration), never part of the gate. The gate is git + the detected toolchain + the migrations tool + MCP-LS.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Refresh the HANDOFF Brief (doc/handoff/HANDOFF.md) from current session state and regenerate the next-session kickoff prompt. Current-state only — per-ship history lives in doc/shipping-logs/ (written by /kit:ship). Does NOT commit or push; run /kit:handoff first, then /kit:ship so the HANDOFF edit rides the ship payload.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:handoff
|
|
6
|
+
|
|
7
|
+
Wrap a session: keep `doc/handoff/HANDOFF.md` an accurate **current-state snapshot**, and produce a kickoff prompt the next session can paste in cold.
|
|
8
|
+
|
|
9
|
+
`doc/handoff/HANDOFF.md` is a **current-state Brief** — it does NOT accumulate per-session "what shipped" writeups. That history lives in `doc/shipping-logs/` (written by `/kit:ship`). Keep HANDOFF lean — if it grows past ~150 lines, the wrong thing is going into it (a cumulative feature list belongs in a roadmap doc; per-ship detail belongs in `doc/shipping-logs/`).
|
|
10
|
+
|
|
11
|
+
This skill does **NOT commit and does NOT push**. `/kit:ship` does that. The intended order is `/kit:handoff` → `/kit:ship`, so the HANDOFF edit lands inside the slice's ship payload and publishes with it. For a session that won't run `/kit:ship`, see **Edge cases**.
|
|
12
|
+
|
|
13
|
+
Parse `$ARGUMENTS`:
|
|
14
|
+
|
|
15
|
+
- (empty) — refresh `doc/handoff/HANDOFF.md` against the current session and regenerate the kickoff prompt.
|
|
16
|
+
- **--dry-run** — build the refreshed HANDOFF + kickoff in a fenced preview block, but do NOT write the file. Useful for "what would the handoff look like right now?".
|
|
17
|
+
- **--next=<text>** — name what's next explicitly (e.g. `--next="F12 webhook retries"`) instead of inferring it from the session. Drives the kickoff prompt's title + context.
|
|
18
|
+
|
|
19
|
+
## Preflight
|
|
20
|
+
|
|
21
|
+
1. `git rev-parse --is-inside-work-tree` — abort if not a git repo.
|
|
22
|
+
2. Resolve the **base branch** to diff the session against:
|
|
23
|
+
- `git symbolic-ref refs/remotes/origin/HEAD --short` (strip `origin/`) → the repo's default branch. Fall back to `origin/main` / `origin/master` if unset.
|
|
24
|
+
- Use `git log <base>..HEAD` as "what this session/branch added."
|
|
25
|
+
3. Confirm `doc/handoff/` exists. If not, this is the first handoff — create `doc/handoff/HANDOFF.md` from the skeleton in **Step 2** rather than editing.
|
|
26
|
+
|
|
27
|
+
## Step 1 — Inventory what happened
|
|
28
|
+
|
|
29
|
+
Survey the session — gather, don't show yet:
|
|
30
|
+
|
|
31
|
+
- `git log <base>..HEAD --oneline` — what's committed locally this branch.
|
|
32
|
+
- `git status --porcelain` + `git diff --stat` — uncommitted work.
|
|
33
|
+
- Recent `TaskList` (if present) — completed vs deferred.
|
|
34
|
+
- From the conversation: decisions made, scope cuts, schema/migration changes, new env vars, external-service touchpoints, anything paused mid-flight.
|
|
35
|
+
|
|
36
|
+
Produce a short internal summary (slice/title · what changed · schema/env deltas · deferred items · open threads). This feeds Steps 2–3; do not print it.
|
|
37
|
+
|
|
38
|
+
## Step 2 — Refresh `doc/handoff/HANDOFF.md`
|
|
39
|
+
|
|
40
|
+
Update **only** these sections — nothing else belongs in this file:
|
|
41
|
+
|
|
42
|
+
1. **Intro line** — keep the "refreshed at each `/kit:handoff`" note + the `docs/archive/` pointer (see Archiving).
|
|
43
|
+
2. **Where we are** — the one-block current-state status: what's now feature-complete, what's paused, any new external dependency. Tight.
|
|
44
|
+
3. **What's next** — the next 1–3 things in priority order. If priorities shifted this session, reflect it.
|
|
45
|
+
4. **Open threads** — the short list of genuinely-open items needing attention soon. **Prune anything resolved this session.** Long-horizon "maybe someday" items belong in a deferrals doc, not here.
|
|
46
|
+
5. **Kickoff prompt** — Step 3.
|
|
47
|
+
|
|
48
|
+
Do NOT add: a "What shipped this session" section (→ `doc/shipping-logs/`), a past-sessions log, or a cumulative feature list (→ a roadmap doc).
|
|
49
|
+
|
|
50
|
+
First-handoff skeleton (when the file doesn't exist yet):
|
|
51
|
+
|
|
52
|
+
```markdown
|
|
53
|
+
---
|
|
54
|
+
title: Handoff — Current State
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
# <Project> — Handoff
|
|
58
|
+
|
|
59
|
+
_Current-state snapshot, refreshed at each session's `/kit:handoff`. Per-ship "what shipped" history lives in `doc/shipping-logs/`. Older handoff content is archived at `docs/archive/`._
|
|
60
|
+
|
|
61
|
+
## Where we are
|
|
62
|
+
|
|
63
|
+
<one-block current state>
|
|
64
|
+
|
|
65
|
+
## What's next
|
|
66
|
+
|
|
67
|
+
1. <next thing>
|
|
68
|
+
2. <…>
|
|
69
|
+
|
|
70
|
+
## Open threads
|
|
71
|
+
|
|
72
|
+
- <genuinely-open item>
|
|
73
|
+
|
|
74
|
+
## Kickoff prompt for the next session
|
|
75
|
+
|
|
76
|
+
> <generated in Step 3>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Step 3 — Regenerate the kickoff prompt
|
|
80
|
+
|
|
81
|
+
Replace the "Kickoff prompt for the next session" section at the bottom of `HANDOFF.md`. It must be **specific to whatever's next** (use `--next=` if given), not generic:
|
|
82
|
+
|
|
83
|
+
```markdown
|
|
84
|
+
## Kickoff prompt for the next session
|
|
85
|
+
|
|
86
|
+
> Starting **<work item / FNN — Title>**. Read `CLAUDE.md`, then `doc/handoff/HANDOFF.md` and the relevant Briefs under `doc/`. {One-paragraph context: what this work is, why now, what infra is already in place.}
|
|
87
|
+
>
|
|
88
|
+
> Before any code, confirm the design shape:
|
|
89
|
+
>
|
|
90
|
+
> 1. **Surface.** {Where does this live? Closest precedent in the codebase?}
|
|
91
|
+
> 2. **Fields / inputs.** {What does the user/agent provide?}
|
|
92
|
+
> 3. **Eligibility.** {When is the action available? State guards?}
|
|
93
|
+
> 4. **Data path.** {What writes happen, in what order? What events/logs are emitted?}
|
|
94
|
+
> 5. **{Feature-specific question.}**
|
|
95
|
+
> 6. **Out of scope / deferrals.** {What are we explicitly NOT building? Trigger to revisit?}
|
|
96
|
+
>
|
|
97
|
+
> Scope the slice, confirm deferrals, then branch off the default branch. Run `/kit:handoff` then `/kit:ship` at session end.
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If `What's next` lists multiple candidates, write the kickoff for the most-likely-next and add a one-line note about the alternative.
|
|
101
|
+
|
|
102
|
+
## Step 4 — Tell the user
|
|
103
|
+
|
|
104
|
+
Single short message:
|
|
105
|
+
|
|
106
|
+
1. **Confirm `HANDOFF.md` is updated** — brief recap of the new current-state + what's-next.
|
|
107
|
+
2. **Show the kickoff prompt** — copy-paste ready, in a fenced block.
|
|
108
|
+
3. **Remind:** start a **new** session for the next slice (one session per feature/branch) and paste the kickoff as the first message.
|
|
109
|
+
4. **Suggest `/kit:ship` next** if there's uncommitted work — there will be, at minimum the HANDOFF edit — so the refresh publishes with the slice.
|
|
110
|
+
|
|
111
|
+
Do NOT commit. Do NOT push. `/kit:ship` does that.
|
|
112
|
+
|
|
113
|
+
## Archiving (keep HANDOFF lean)
|
|
114
|
+
|
|
115
|
+
If `HANDOFF.md` exceeds ~150 lines or the "Where we are" block has accumulated many fully-shipped-and-stable bullets:
|
|
116
|
+
|
|
117
|
+
- Move the stale, no-longer-active content to `docs/archive/HANDOFF-thru-<YYYY-MM>.md` (append to it if it exists).
|
|
118
|
+
- Leave a one-line pointer in the intro line.
|
|
119
|
+
- The live HANDOFF should read in under a minute. History is recoverable from the archive + `doc/shipping-logs/`; it does not need to live in the active snapshot.
|
|
120
|
+
|
|
121
|
+
## Edge cases
|
|
122
|
+
|
|
123
|
+
- **Session shipped code** — `/kit:ship` runs after this and commits the HANDOFF edit along with the slice. The normal path.
|
|
124
|
+
- **Design / planning / process session, no `/kit:ship`** — still refresh HANDOFF (decisions made, deferrals identified, new open threads) and the kickoff. Since no ship will run, either make a small `docs:` commit of the HANDOFF change yourself, or tell the user it's uncommitted and unpublished. Do not silently leave it dangling.
|
|
125
|
+
- **No changes since base** (pure conversation, no code, no decisions) — don't fabricate updates. Refresh only the kickoff prompt and say "no current-state changes; here's the prompt for next session."
|
|
126
|
+
- **Session spanned multiple slices** (rare — violates one-session-per-feature) — each slice already has its own `doc/shipping-logs/` entry from `/kit:ship`; just ensure HANDOFF's current-state reflects all of them.
|
|
127
|
+
|
|
128
|
+
## Notes for the assistant
|
|
129
|
+
|
|
130
|
+
- HANDOFF is **current-state only**. The single most common failure is letting it grow into a session journal — that's what `doc/shipping-logs/` is for. When in doubt, cut.
|
|
131
|
+
- This skill never pushes; it respects the same unauthorized-push rules as `/kit:ship`. The HANDOFF edit becomes team-visible only when `/kit:ship` pushes it.
|
|
132
|
+
- If the repo registers a `handoff` doc category in its file-content-sync config (mapping `doc/handoff/**` to the discussion handler, the same mechanism `/kit:ship` uses for `doc/shipping-logs/**`), the HANDOFF Brief materializes as a Comm Hub comment on push. If not, HANDOFF still works as a local cold-start doc — it just isn't mirrored to the Comm Hub. That category registration is a one-time repo/server config, not this skill's job.
|