@launchsecure/launch-kit 0.0.33 → 0.0.35
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 +286 -50
- package/dist/server/course-entry.js +1 -1
- package/dist/server/graph-mcp-entry.js +180 -4
- package/dist/server/init-entry.js +563 -60
- package/dist/server/launch-bot-entry.js +4078 -0
- package/dist/server/launch-radar-entry.js +45 -0
- package/dist/server/orbit-entry.js +123 -26
- package/dist/server/parse-worker-entry.js +167 -2
- package/dist/server/radar-docker-init-entry.js +496 -39
- package/dist/server/radar-teardown-entry.js +23 -22
- package/dist/server/rover-entry.js +20555 -0
- package/package.json +8 -5
- 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 +72 -49
- package/scaffolds/ls-marketplace/plugins/kit/skills/brief/briefs.mjs +152 -0
- 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/kickoff/SKILL.md +151 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/orbit/SKILL.md +14 -2
- package/scaffolds/ls-marketplace/plugins/kit/skills/ship/SKILL.md +149 -133
|
@@ -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.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Cold-start a session — read the last HANDOFF snapshot, the newest shipping log, the git summary, and (if LS is connected) your open work items, reconcile them, then categorize all pending work (resume in-flight · review/PR feedback · bugs · high-priority · low-hanging fruit · stale/dead · tech-debt/deferred, plus a non-pickable blocked list) and let you choose a list to work from before drilling into a specific item. Read-only; the complement to /kit:handoff. Does NOT branch, commit, or write files unless you confirm a next step.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# /kit:kickoff
|
|
6
|
+
|
|
7
|
+
Start a session the way `/kit:handoff` ends one. Handoff **writes** the current-state snapshot and a single kickoff prompt at the end of a session; kickoff **reads** that snapshot back at the start of the next one, cross-checks it against git and your work items, and turns "what was I doing / what's next" into a concrete pick.
|
|
8
|
+
|
|
9
|
+
The loop is: `/kit:handoff` → (new session) → `/kit:kickoff` → choose a slice → work → `/kit:handoff` → `/kit:ship`. One session per feature; kickoff is the first thing you run in the fresh session.
|
|
10
|
+
|
|
11
|
+
This skill is **read-only by default**. It does not branch, commit, push, or write files. Its output is: a lay-of-the-land board, the pending work **sorted into categorized lists** (resume in-flight · low-hanging fruit · high-priority · stale/dead · tech-debt/deferred), a two-stage choice (pick a *list*, then a *specific item*), and — once you've chosen — a ready-to-use kickoff prompt for that item plus an offer to set up the branch/orbit as a *separate, confirmed* next step.
|
|
12
|
+
|
|
13
|
+
Parse `$ARGUMENTS`:
|
|
14
|
+
|
|
15
|
+
- (empty) — full orient: gather all sources, show the board + categorized lists, ask which list to work from, then drill into a specific item.
|
|
16
|
+
- **--brief** — show the lay-of-the-land board + the category headline counts only (e.g. "🍒 Low-hanging: 4 · 🔥 High-priority: 3 · 🪦 Stale: 6"). Skip the interactive choice. For "just remind me where I was."
|
|
17
|
+
- **--list=<name>** — skip the first-stage menu; go straight to the named list (`resume` / `review` / `bugs` / `priority` / `fruit` / `stale` / `debt`) and present its filtered items to pick from.
|
|
18
|
+
- **--pick=<text>** — skip both menus; treat `<text>` as the chosen item and go straight to producing its kickoff prompt + setup offer.
|
|
19
|
+
- **--all** — when assembling work-item candidates, include items not assigned to you (whole-board backlog), not just your own. Default is assigned-to-me.
|
|
20
|
+
|
|
21
|
+
## Preflight
|
|
22
|
+
|
|
23
|
+
1. `git rev-parse --is-inside-work-tree` — abort if not a git repo.
|
|
24
|
+
2. Resolve the **base branch** (same logic as `/kit:handoff` and `/kit:ship`):
|
|
25
|
+
- `git symbolic-ref refs/remotes/origin/HEAD --short` (strip `origin/`). Fall back to `origin/main` / `origin/master` if unset.
|
|
26
|
+
3. Record current branch (`git rev-parse --abbrev-ref HEAD`) and git email (`git config user.email`) — the email is the work-item handle.
|
|
27
|
+
4. Detect LS connectivity: check for `.launch-secure.cred.config` at the repo root. If absent, kickoff still runs — it just **skips the work-items source** and notes "LS not connected; candidates from HANDOFF + git only." Do NOT abort (unlike `/kit:standup`, kickoff is useful offline).
|
|
28
|
+
|
|
29
|
+
## Step 1 — Gather the sources (don't show yet)
|
|
30
|
+
|
|
31
|
+
Pull from four layers in parallel. Each is independently optional; a missing one is noted, not fatal.
|
|
32
|
+
|
|
33
|
+
**1a. The HANDOFF snapshot** — read `doc/handoff/HANDOFF.md` if it exists. Extract its four live sections: **Where we are**, **What's next** (the priority-ordered 1–3), **Open threads**, and the embedded **Kickoff prompt**. This is the human-curated "what's next," highest signal. If the file doesn't exist, note "no HANDOFF yet — first kickoff" and lean on git + work items.
|
|
34
|
+
|
|
35
|
+
**1b. The last ship** — read the newest file under `doc/shipping-logs/` (date-prefixed `YYYY-MM-DD-…`, so the lexically-last name is newest). This is the authoritative "what was *actually* last updated/shipped" — HANDOFF is current-state only and does not carry per-ship detail. Capture its title + the slice it shipped. If the dir is empty, skip.
|
|
36
|
+
|
|
37
|
+
**1c. Git summary** — the real on-disk state, to reconcile against what HANDOFF claims:
|
|
38
|
+
- `git log <base>..HEAD --oneline` — commits on this branch not yet in base.
|
|
39
|
+
- `git log -n 8 --oneline <base>` — recent baseline history (what landed lately).
|
|
40
|
+
- `git status --porcelain` — uncommitted work. Filter out generated noise (`.launchsecure/graphs/*.json`, `node_modules`, `dist`, `.next`). What remains is genuine in-flight work — a **"resume this"** candidate.
|
|
41
|
+
- Current branch + whether it's ahead/behind base.
|
|
42
|
+
|
|
43
|
+
**1d. Work items (only if LS connected)** — build the backlog candidates:
|
|
44
|
+
- `mcp__launch-secure__work_items_list({ assignee_email: "<git email>", status: "IN_PROGRESS" })` — things you already started; strongest "resume" candidates.
|
|
45
|
+
- `mcp__launch-secure__work_items_list({ assignee_email: "<git email>", status: "TODO" })` — your queued backlog.
|
|
46
|
+
- With `--all`, also fetch the same statuses without `assignee_email` to include unassigned/team items.
|
|
47
|
+
- Capture id + title + status for each. Cap at ~8 total; if more, keep the top 8 and note "(N more in LS)".
|
|
48
|
+
|
|
49
|
+
> Use the hosted `launch-secure` MCP by default. Only use `local-launch-secure` if the active course points there (see `/kit:course`). Don't ask for org/project slugs — the `.mcp.json` headers default to the current project.
|
|
50
|
+
|
|
51
|
+
## Step 2 — Reconcile + flag drift
|
|
52
|
+
|
|
53
|
+
Before showing anything, cross-check the sources against each other. This is the honesty pass — the inverse of what `/kit:standup` does for shipped work.
|
|
54
|
+
|
|
55
|
+
- **Stale "What's next":** if a HANDOFF "What's next" item appears already done in git (matching commits in `<base>..HEAD`, or named in the newest shipping log), flag it: _"HANDOFF lists ‹X› as next, but it appears shipped (commit ‹sha›) — likely stale."_ Don't silently drop it; surface the contradiction.
|
|
56
|
+
- **Dedup across sources:** a HANDOFF "What's next" item and an LS work item often refer to the same slice (match on id like `LS-…`/`#…`, or on title similarity). Collapse them into one candidate that carries both handles.
|
|
57
|
+
- **Resolved open threads:** if an "Open thread" looks addressed by a recent commit, note it as "possibly resolved — confirm."
|
|
58
|
+
- **Branch sanity:** if the current branch already has commits ahead of base AND there's an in-progress work item, the most likely intent is "continue the current branch," not "start something new" — rank accordingly.
|
|
59
|
+
|
|
60
|
+
## Step 3 — Categorize the pending work into lists
|
|
61
|
+
|
|
62
|
+
Pool every candidate from the reconciled sources (HANDOFF "What's next" + "Open threads", LS work items, uncommitted git work, follow-up flags grepped from recent commit bodies — same patterns `/kit:standup` uses: `TODO`, `follow-up`, `deferred`, `not patched`, `revert`, `next pass`, plus `broken`/`bug`/`failing`/`blocked`/`waiting on`). Dedup (Step 2).
|
|
63
|
+
|
|
64
|
+
**First, pull out the blocked items** — anything tagged `blocked`/`waiting`, marked depending on an unfinished item, or whose commit/thread says "waiting on ‹X›". These go to the non-pickable **🚧 Blocked** list (Step 4) so you see *why* they aren't moving; they are removed from all buckets below.
|
|
65
|
+
|
|
66
|
+
Then sort each remaining item into **one** bucket — most-specific bucket wins, in this precedence:
|
|
67
|
+
|
|
68
|
+
1. **🔧 Resume in-flight** — uncommitted local work + `IN_PROGRESS` work items. The strongest "continue what you started" signal; always wins if present.
|
|
69
|
+
2. **👀 Review / PR feedback** — work waiting on *your* action on something already in motion: open PRs you authored or are assigned to review, unresolved review comments, `needs-review`/`changes-requested` tags. Time-sensitive (someone's blocked on you), so it outranks fresh work.
|
|
70
|
+
3. **🐛 Bugs / broken** — defects: work items of type `bug` or tagged `bug`/`defect`/`regression`, and `broken`/`failing`/`revert`/`not patched` follow-up flags from commit bodies. Distinct from feature backlog regardless of priority.
|
|
71
|
+
4. **🔥 High-priority** — items the project marks urgent: a work-item priority/severity field at its top value, tags like `p0`/`p1`/`urgent`, **and** everything in HANDOFF "What's next" (human-curated = high priority by definition), minus anything Step 2 flagged stale.
|
|
72
|
+
5. **🍒 Low-hanging fruit** — quick wins: work items with a small estimate/size field or `quick`/`chore`/`good-first`/`small` tags, single-file follow-up flags from commit bodies, and one-line open threads. When no size signal exists, infer from scope words in the title ("rename", "typo", "bump", "add flag", "copy") — but say it's inferred.
|
|
73
|
+
6. **🪦 Stale / dead** — pending too long: `TODO`/`IN_PROGRESS` work items whose `updatedAt` is older than ~30 days (tune to the project's pace), and open threads that have survived multiple handoffs. These are the "why is this still here" items.
|
|
74
|
+
7. **🧹 Tech-debt / deferred** — items tagged `tech-debt`/`debt`/`deferred`/`backlog`, explicit deferrals recorded in HANDOFF, and `deferred`/`rolled back` follow-up flags from commit bodies.
|
|
75
|
+
|
|
76
|
+
Each item lands in exactly one bucket. Within a bucket, sort by the most relevant key (priority desc, then age; for stale, oldest first; for fruit, smallest first). An empty bucket is simply omitted everywhere downstream.
|
|
77
|
+
|
|
78
|
+
## Step 4 — Show the lay of the land
|
|
79
|
+
|
|
80
|
+
One compact block: orientation header, then each **non-empty** bucket with up to **5** items and a `+N more` tail. No preamble.
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
📍 Where we are
|
|
84
|
+
<HANDOFF "Where we are", trimmed to 2–4 lines. If no HANDOFF: a 1-line synthesis from git.>
|
|
85
|
+
🚢 Last shipped: <newest shipping-log title + date> — <one line>
|
|
86
|
+
⚠️ Drift: <Step 2 flags, one line each. Omit if none.>
|
|
87
|
+
|
|
88
|
+
🔧 Resume in-flight (N)
|
|
89
|
+
- <item — handle/branch/file · short why>
|
|
90
|
+
…up to 5… (+N more)
|
|
91
|
+
|
|
92
|
+
👀 Review / PR feedback (N)
|
|
93
|
+
- <item — PR#/LS-id · what's waiting on you>
|
|
94
|
+
…up to 5… (+N more)
|
|
95
|
+
|
|
96
|
+
🐛 Bugs / broken (N)
|
|
97
|
+
- <item — LS-id · short why>
|
|
98
|
+
…up to 5… (+N more)
|
|
99
|
+
|
|
100
|
+
🔥 High-priority (N)
|
|
101
|
+
- <item — LS-id · short why>
|
|
102
|
+
…up to 5… (+N more)
|
|
103
|
+
|
|
104
|
+
🍒 Low-hanging fruit (N)
|
|
105
|
+
- <item — handle · est/size or "inferred quick">
|
|
106
|
+
…up to 5… (+N more)
|
|
107
|
+
|
|
108
|
+
🪦 Stale / dead (N)
|
|
109
|
+
- <item — LS-id · "untouched 47d">
|
|
110
|
+
…up to 5… (+N more)
|
|
111
|
+
|
|
112
|
+
🧹 Tech-debt / deferred (N)
|
|
113
|
+
- <item — handle · source>
|
|
114
|
+
…up to 5… (+N more)
|
|
115
|
+
|
|
116
|
+
🚧 Blocked (N) — not pickable, shown for awareness
|
|
117
|
+
- <item — handle · waiting on ‹what›>
|
|
118
|
+
…up to 5… (+N more)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Readable in under a minute. The 🚧 Blocked list is informational only — never offered as a pick. If `--brief`, stop after the headline counts line (don't expand the bucket items).
|
|
122
|
+
|
|
123
|
+
## Step 5 — Two-stage choice: pick a list, then an item
|
|
124
|
+
|
|
125
|
+
**Stage A — which list.** Call **AskUserQuestion** ("Which list do you want to work from?"). Options are the **non-empty pickable buckets** (🚧 Blocked is never an option), capped at 4 (the tool's max) — there are up to 7 pickable buckets, so choose the 4 most useful for this session by precedence + item count + freshness, and surface the rest in option descriptions ("…also N stale, N tech-debt — say the word to see them"). Thin slow-moving buckets may be folded into one option ("Stale & deferred"). Each option's description carries the bucket's count + a one-line flavor of what's inside. "Other" (auto-added) lets the user name any list (including a folded/overflow one) or item directly. Skip Stage A if `--list=` was passed.
|
|
126
|
+
|
|
127
|
+
**Stage B — which item.** Once a list is chosen, show that bucket's **full** filtered list (not just the top 5 — now we're focused on one category, so depth is fine), numbered, each with its handle + the one-line why. Ask the user to pick one (a second `AskUserQuestion` with up to 4 of the top items, or just let them reply with a number/name if the list is long). Skip Stage B if `--pick=` was passed.
|
|
128
|
+
|
|
129
|
+
## Step 6 — Set up the chosen item
|
|
130
|
+
|
|
131
|
+
Once a specific item is chosen:
|
|
132
|
+
|
|
133
|
+
1. **Produce its kickoff prompt.** If the chosen slice matches the one HANDOFF already wrote a "Kickoff prompt for the next session" for, **reuse that verbatim** in a fenced block. Otherwise synthesize one in the **same shape** handoff uses (Starting **‹item — Title›** · read CLAUDE.md + HANDOFF + relevant Briefs · then the 1–6 design-shape questions: Surface, Fields/inputs, Eligibility, Data path, feature-specific, Out-of-scope). Make it specific to the chosen slice, not generic.
|
|
134
|
+
2. **Offer the setup as a confirmed next step — do not do it unprompted.** In one line, offer to: branch off the base (`git checkout <base> && git pull && git checkout -b <slice-branch>`) **or** create an isolated orbit (`/kit:orbit`) if the slice wants a forked DB. Wait for an explicit "yes" / branch name before running any git or orbit command — this is a state mutation and falls under the per-action confirmation rule.
|
|
135
|
+
3. If the chosen slice is a `TODO` work item and the user confirms starting it, offer (don't auto-run) to move it to `IN_PROGRESS` via `mcp__launch-secure__work_item_move` / `work_item_update`.
|
|
136
|
+
|
|
137
|
+
## Edge cases
|
|
138
|
+
|
|
139
|
+
- **No HANDOFF.md yet** (first kickoff in a repo) — don't fabricate a "Where we are." Synthesize the board from git + last shipping log + work items, and tell the user "no HANDOFF snapshot yet — run `/kit:handoff` at the end of this session to create one." Kickoff degrades to a git+LS orientation.
|
|
140
|
+
- **LS not connected** — skip Step 1d entirely; candidates come from HANDOFF + git. Note it once on the board.
|
|
141
|
+
- **Clean tree, nothing in flight, empty backlog** — say so plainly ("nothing in flight; HANDOFF's next is ‹X›") and just present HANDOFF's "What's next" as the candidates. Don't invent work.
|
|
142
|
+
- **HANDOFF wildly out of sync with git** (many stale "next" items already shipped) — lead with the drift block and suggest the previous session likely forgot `/kit:handoff`; offer to reconstruct current-state from git, but don't write HANDOFF here (that's `/kit:handoff`'s job).
|
|
143
|
+
- **Mid-branch resume** (current branch already ahead of base) — surface "continue this branch" at the top of the 🔧 Resume in-flight list, and skip the branch-creation offer in Step 6 unless the user picks a different item.
|
|
144
|
+
- **Everything lands in one bucket** (e.g. all candidates are stale) — that's fine; show the single list and skip Stage A (no choice to make), going straight to picking an item.
|
|
145
|
+
|
|
146
|
+
## Notes for the assistant
|
|
147
|
+
|
|
148
|
+
- Kickoff is **read + orient + choose**. It is the mirror of `/kit:handoff` (write) — keep the boundary clean: kickoff does not write `HANDOFF.md`, does not commit, does not push. The only mutations it ever performs are the explicitly-confirmed branch/orbit/work-item-move in Step 6.
|
|
149
|
+
- The single most useful thing kickoff adds over just re-reading HANDOFF is **reconciliation** (Step 2): HANDOFF is hand-maintained and goes stale. Always cross-check it against git before presenting its "What's next" as gospel.
|
|
150
|
+
- Prefer commit scopes, work-item ids, and shipping-log titles as candidate handles — they're stable and clickable. Don't pull the full chart/graph for this; kickoff is a fast orientation, not an analysis (`/kit:analyse` is for structure).
|
|
151
|
+
- Respect the course: read/write LS through whichever server the active course points at, never cross prod/local.
|
|
@@ -10,7 +10,8 @@ Parse `$ARGUMENTS` — first token is the subcommand:
|
|
|
10
10
|
|
|
11
11
|
- **create <branch>** — `[--base=<ref>] [--profile=<name>]` — fork resources per `orbit.json`, return path + envFile.
|
|
12
12
|
- **list** — list every orbit registered on this machine.
|
|
13
|
-
- **switch <branch>** —
|
|
13
|
+
- **switch <branch>** — activate an orbit: atomically repoint the `current` anchor at its worktree, then operate under that anchor.
|
|
14
|
+
- **deactivate** — clear the `current` anchor so work targets the main checkout again.
|
|
14
15
|
- **doctor** — surface registry inconsistencies.
|
|
15
16
|
- **check <branch> --target=<target-branch>** — run pre-merge gates WITHOUT merging.
|
|
16
17
|
- **merge <branch> --target=<target-branch>** — `[--cleanup=full|none] [--skip-gate=<id>,…]` — run gates + merge.
|
|
@@ -43,7 +44,18 @@ Examples:
|
|
|
43
44
|
|
|
44
45
|
### switch
|
|
45
46
|
|
|
46
|
-
`mcp__launch-orbit__orbit_switch(branch)`
|
|
47
|
+
`mcp__launch-orbit__orbit_switch(branch)` **activates** the orbit — it atomically repoints `<project>/.launchsecure/orbit/current` at the orbit's worktree and writes `active.json`, then returns `anchor` + `nextAction`. This is a real, deterministic switch: one stable path now resolves into the active orbit.
|
|
48
|
+
|
|
49
|
+
After switching, target the anchor for everything (this is the whole point — one path, not the raw worktree path):
|
|
50
|
+
- **files**: Read / Edit / Write under `.launchsecure/orbit/current/<path>`.
|
|
51
|
+
- **chart**: pass `project_root: ".launchsecure/orbit/current"`.
|
|
52
|
+
- **commands**: run the returned `nextAction` (`cd ".launchsecure/orbit/current"`) once, then all Bash runs in the orbit.
|
|
53
|
+
|
|
54
|
+
Switching to a *different* orbit just repoints the anchor — re-run `nextAction` afterward, because a shell that already `cd`'d resolved the old target at cd-time (files and chart follow the symlink live; only the shell needs the re-cd).
|
|
55
|
+
|
|
56
|
+
### deactivate
|
|
57
|
+
|
|
58
|
+
`mcp__launch-orbit__orbit_deactivate()` removes the `current` anchor + `active.json` for this project. Use when done in the orbit so subsequent work targets the main checkout. No-op if nothing is active. (Dropping the active orbit clears the anchor automatically.)
|
|
47
59
|
|
|
48
60
|
### doctor
|
|
49
61
|
|