158 Commits

Author SHA1 Message Date
Ciprian Spiridon b3e5e33424 feat(nextjs): internalize project architecture contracts
Preserve installed versions and discovered auth, i18n, theme, and transport decisions.

Add trusted-request, agent-ready public-surface, async-state, and layered testing contracts.
2026-08-31 11:56:33 +04:00
Ciprian Spiridon a2806def27 docs: update Laravel and Next.js skills
Recommend Laravel 13 and stable Next.js 16.2, add dedicated upgrade guides, and refresh version-specific framework APIs and migration guidance.
2026-07-23 06:56:02 +04:00
Ciprian Spiridon 95da30a0a1 ship-playbook — drop the kache pre-warm (the store self-warms); keep it only as a cold-store trip-wire
kache is content-addressed and path/target-dir-independent, so its store warms itself across worktrees
and persists across runs — the first worktree to compile a crate populates it and every other worktree
and later run hardlinks it (measured ~97% cross-worktree hits, 51 GiB persistent store). A pre-warm on a
hot store is just a full workspace build that's all hits — dead weight. Remove the automatic kache
pre-warm from the warm step; document the one case it earns its keep (a genuinely COLD store — fresh
machine, kache purge, or Cargo.lock/toolchain bump — with a wide first build layer) as a trip-wire.
The no-kache path is unchanged: it still builds ROOT/target so worktrees CoW-seed it. Wording clarified
so a kache repo is never described as cold-building (kache still wraps via .cargo/config.toml).
2026-07-13 17:50:27 +04:00
Ciprian Spiridon b9572f671a ship-playbook — remove the 4 leftover sccache references (kache is the Rust cache)
Follow-up to v1.16.0: the kache onboarding missed four stale sccache mentions that still
described the warm step as using sccache — the warmWorktree default comment, the warm-provisioning
rationale ("a shared sccache compiler cache"), the seed-block verification note, and the resume
near-noop note. This repo uses kache (a path-independent rustc-wrapper wired in .cargo/config.toml,
~97% cross-worktree hits); sccache was removed and is not used. All four corrected to kache.
No behavior change — the kache priming + no-target/-clone path is unchanged.
2026-07-13 17:45:09 +04:00
Ciprian Spiridon 4b4a070a4b skills — rewrite every skill's description + when_to_use in the routing-first style
Restyle the description and when_to_use frontmatter of the whole skill catalog to the
skills-engineering-autonomous pattern, so Claude Code and Codex route to the right skill:

- description: capability + em-dash/colon differentiator (key invariant in CAPS) -> concrete sequenced
  mechanism -> explicit fail-closed/honesty clause -> a terse trailing "Use ..." (atomic skills) or a
  phase-chain/"Composes ..." closer (composites).
- when_to_use: "Use when <positives + examples>. Do NOT use <negatives> -> redirect to the sibling
  skill by name; <crisp principle>." + explicit-user-only/confirm caveat where the skill mutates or
  spawns agents.

Frontmatter-only: skill bodies are unchanged. Grounded each rewrite in the skill's actual behavior.
(ship-playbook's restyle rode with its v1.16.0 commit.)
2026-07-13 14:15:30 +04:00
Ciprian Spiridon 1a6bc3bb58 ship-playbook v1.16.0 — git-ground-truth resume, reviewer native-fallback, kache-first Rust seeding
Resume/integration hardening (post-mortem of wf_faec74a9-170, which lost 27 of 74 tasks on resume):
- Derive integration state from git on resume: a task whose slice commit is on the working branch is
  integrated (and "already applied" re-merges count as integrated, never dev_done), so dependents no
  longer cascade-block and vanish.
- A dead/empty configured reviewer (codex/kiro) falls back to a real native review, never a false block;
  a startup health-probe downgrades a broken harness to native once, and the return surfaces the downgrade.
- Treat nextest "no tests to run" (exit 4 / zero-match filter) as a plan/filter defect, not a slice failure.
- Park unmerged wf/build/* branches under refs/ship/parked/ before cleanup so gc can't reap recovery commits.
- Re-target a drifted base on resume; recognize drift/duplicate merge hunks as no-ops.
- Resume carries full args via wf-status.mjs --resume (canonical), not resumeFromRunId (which drops args).

Rust worktree caching: kache-first (a path-independent, hardlink-based rustc-wrapper with proven
cross-worktree hits, wired via .cargo/config.toml) with target/ CoW-seed as the no-kache fallback;
sccache stays removed (0% cross-worktree hits). Both build briefs, the seed script, and the warm step
prime/detect kache; SKILL.md sccache mentions updated.

Also restyles ship-playbook's own description + when_to_use to the routing-first frontmatter pattern.
2026-07-13 14:15:22 +04:00
Ciprian Spiridon fe1abf8d3a framework skills — remove path-gating so they no longer auto-activate by file path
Strips the `paths:` frontmatter allow-list from all 7 path-gated framework
skills (laravel, laravel-filament, docker, nodejs, nestjs, nextjs, rust). They
were staying dormant until a matching file was touched and then auto-suggesting
— which misfired across stacks (e.g. the nodejs skill waking on package.json /
Dockerfile in a PHP repo). Without `paths:` they behave as ordinary on-demand
skills. Minor version bump on each; no other frontmatter or body changes.
2026-07-07 06:27:53 +04:00
Ciprian Spiridon 039ae3f8be ship-playbook v1.14.0 — remove sccache for Rust (measured 0.00% hit rate; net-negative overhead)
sccache --show-stats on a real run: 6 GB / 7603 files written, ZERO Rust
read-hits ever. Root cause is fundamental to the isolated-worktree design — each
worktree has a distinct target-dir path, and cargo bakes per-worktree absolute
paths into every rustc call (--extern/-L paths + path-dependent rlib contents),
so each crate is written under one cache key and looked up under another. Never a
hit; every rustc just detours through sccache (hash → miss → compile → write) for
zero payoff, adding overhead to a build that already cold-compiles everything.

Removes all Rust sccache machinery: the seed script's .cargo/config.toml wiring,
the warm-prime priming (size config file + daemon restart + throwaway build), and
the engineer-brief instructions. Rust worktrees now cold-build with plain cargo —
no seed, no prime, no config, no overhead. Node/PHP/Pods CoW seeding is untouched.

A target/ clone is also unsafe (cargo fingerprints embed abs paths → a moved
target rebuilds anyway). Any future Rust cache must first PROVE a non-zero hit
rate on a real run (candidate: --remap-path-prefix to stabilise paths) — not
shipped on faith. Verified: seed passes bash -n and writes no .cargo/config.toml.
2026-07-05 11:39:45 +04:00
Ciprian Spiridon fdc3a70f78 ship-playbook v1.13.1 — force CARGO_INCREMENTAL=0 so sccache caches workspace crates, not just deps
v1.13.0 already wrote `[build] incremental = false` (which per cargo docs
overrides all profiles), but the CARGO_INCREMENTAL env var outranks it — so a
`dev-fast.sh`/validate that exports CARGO_INCREMENTAL=1 for its local fast loop
silently re-enables incremental, and sccache skips incremental units → the ~30
first-party workspace crates cold-compile in every worktree (observed: sccache
hitting only unchanged third-party deps, ~56%).

Seed's .cargo/config.toml now also writes:
  [env]
  CARGO_INCREMENTAL = { value = "0", force = true }
force=true neutralizes an ambient CARGO_INCREMENTAL, so incremental is off
regardless of what the repo's build script exports → sccache caches the
workspace crates too (2nd worktree onward hits instead of recompiling).

Precedence (cargo docs): CARGO_INCREMENTAL env > build.incremental > profile.
Verified: rendered seed passes bash -n; emitted .cargo/config.toml parses as
valid TOML with both [build] incremental=false and the forced [env] entry.
2026-07-05 10:17:20 +04:00
Ciprian Spiridon b94f194138 ship-playbook v1.13.0 — wire sccache via .cargo/config.toml (env export was bypassing it entirely)
Live diagnosis on a real run: 7 of 8 rustc procs were UNWRAPPED — each worktree
engineer cold-compiled arrow/datafusion/sqlparser from scratch, and sccache
served only the warm prime's compiles. Root cause: the seed script's "Rust"
section was a comment that did nothing; it relied on the engineer brief's
`export RUSTC_WRAPPER=sccache`, but env does not survive across the agent's
separate shells / a fresh validate shell, so the real cargo/dev-fast.sh called
plain rustc. The v1.11–1.12 cache-size work was moot while the wrapper was bypassed.

Fix (env-independent, per the layer that actually reaches cargo):
- Seed script (runs in every worktree) now writes a worktree-local
  .cargo/config.toml = `[build] rustc-wrapper="sccache"\nincremental=false`,
  git-excluded via info/exclude so it never enters the engineer's commits,
  created only-if-absent so a tracked .cargo/config is never edited. cargo reads
  rustc-wrapper on EVERY invocation — dev-fast.sh, raw cargo, build.rs — no env.
- Engineer brief: stop telling engineers to `export` it (that was the bug);
  rely on the config, inline-prefix if forcing env, and verify sccache
  --show-stats climbs.

Verified: rendered seed script passes `bash -n`; run in a throwaway git repo it
produces valid TOML ([build] rustc-wrapper/incremental) and git-excludes the file.
2026-07-05 09:24:29 +04:00
Ciprian Spiridon d5b7367ee2 ship-playbook v1.12.0 — sccache 80G cap actually holds (config file, not env-only) across parallel worktrees
The prior 50G cap silently reverted to sccache's 10G default. sccache reads
SCCACHE_CACHE_SIZE only when the SERVER starts; a bare `export` is ignored by an
already-running (or auto-restarted) daemon, and the single shared daemon is
almost always already up at 10G (stale server, warmWorktree off, parallel
engineers racing the first `cargo`, or an idle-timeout restart). Only the prime
step restarted the server, so only it applied the cap — the engineer path just
exported it into the void, then LRU-evicted the big dep graph mid-build.

Fix (warm prime, workflow-template.js):
- Persist the size in sccache's CONFIG FILE ([cache.disk] size = 85899345920 =
  80 GiB), which is read on EVERY server start (manual, auto, post-idle-timeout)
  regardless of which shell triggers it. Written only if absent, so an existing
  sccache config is never clobbered. OS-aware path (Linux ~/.config, macOS
  ~/Library/Application Support/Mozilla.sccache).
- SCCACHE_IDLE_TIMEOUT=0 on the primed daemon so it survives the LLM-bound gaps.
- Raise cap 50G -> 80G in both the prime and the engineer build-shell export;
  the engineer export is now belt-and-suspenders since the config file is
  authoritative.

This is a run-time instruction to the build agent (writes the config on the
build machine), not a change to any user's global config.
2026-07-05 09:17:06 +04:00
Ciprian Spiridon 3301f32826 ship-playbook v1.11.0 — per-phase/per-task startedAt+updatedAt timestamps in the durable status file
The status file previously carried only file-level createdAt/updatedAt, so you
could see WHAT state each phase/task was in but not WHEN it got there. Adds
per-entry timestamps on every phase and task:
- workflow-template.js: the statusStep() jq merge now stamps startedAt (first
  write, preserved across later merges via //) and updatedAt (rewritten every
  write) onto only the phases/tasks named in each patch, alongside the existing
  file-level updatedAt. Time is computed at write time by jq `now` (the Workflow
  sandbox has no clock). Deep-merge + openRegister array-replace semantics are
  unchanged; still-pending entries stay timestamp-free until first change.
- wf-status.mjs: the --write journal backfill now reconstructs per-task
  startedAt/updatedAt from agent-transcript timestamps, matching the live shape.
- status-tracking.md: schema example + new Timestamps subsection.

Now phases.build.startedAt = when build began (updatedAt - startedAt = elapsed),
and a task's updatedAt = when it entered its current status (e.g. became blocked).
2026-07-05 07:01:46 +04:00
Ciprian Spiridon f5f262d7f6 ship-playbook v1.10.2 — document warmWorktree (worktree seeding + sccache) in SKILL.md + README
The v1.10.0/.1 feature shipped without user-facing docs. Adds:
- SKILL.md: warmWorktree in the Workflow args list + comment, and a Build-phase
  paragraph on fast worktree provisioning (CoW-seed node_modules/vendor/Pods,
  Rust sccache, frozen-install fallback, warmWorktree:false = plain install).
- README.md: the ship-playbook section now describes fast worktree provisioning.
2026-07-05 06:30:12 +04:00
Ciprian Spiridon b793d2c49c ship-playbook v1.10.1 — worktree-seed warm fixes: surgical gitignore, sccache 50G cap, throwaway prime target
Three corrections to the v1.10.0 warm/seed step:

- Gitignore is now surgical: .ulpi/.gitignore gets a `seed-worktree.sh` line
  (appended if the file exists, else created with just that line) instead of
  `*`, which would have hidden the plans/reviews/status files the workflow
  writes under .ulpi and that you may commit.
- Raise the sccache cap to 50G (and stop/start the server so it takes effect):
  the 10G default LRU-evicts a large dep graph (datafusion+arrow+candle) mid-run
  and silently kills the hit rate. The cap is also set in the engineer's Rust
  export so a cargo-autostarted server comes back at 50G, not 10G.
- Warm primes sccache into a THROWAWAY CARGO_TARGET_DIR (mktemp -d), not
  ${ROOT}/target — sccache's cache is target-dir-independent, so the shared
  cache is populated without clobbering the local incremental fast-loop cargo
  (e.g. dev-fast.sh) relies on. Also retires the torn-clone race.
2026-07-05 06:24:18 +04:00
Ciprian Spiridon 789396da99 ship-playbook v1.10.0 — CoW worktree seeding (Node/PHP/Pods) + Rust sccache, any-stack
Every build/fix engineer runs in an isolation:'worktree' checkout with empty
deps/artifacts, so each cold-installs or cold-compiles from scratch — per lane,
per layer, and again on resume. This seeds each worktree from the primary
checkout instead, per stack, and shares Rust compilation via sccache.

- One tested seed script (written to .ulpi/ by an early warm step, gitignored):
  CoW-clones node_modules / vendor / Pods from ROOT when the lockfile is unchanged
  (clonefile/reflink — instant same-volume), else a frozen --prefer-offline
  install. Never a slow copy: the macOS path gates on same device id (cp -c
  silently full-copies cross-volume), the Linux path uses --reflink=always
  (errors instead of a silent fallback).
- Rust is sccache-only — NO target/ clone (redundant with sccache, multi-GB×N
  disk, torn-clone risk). Engineers export RUSTC_WRAPPER=sccache
  CARGO_INCREMENTAL=0 in the build shell (raw cargo and wrapper scripts inherit
  it); the warm step primes sccache from ROOT before the fan-out.
- Warm starts right after preflight, overlapping the LLM-bound plan/plan-review
  phases (~0 added wall-clock on fresh runs; a harmless near-noop on resume).
- Default on; CFG.warmWorktree=false restores today's plain per-worktree install
  verbatim. Go left untouched (GOCACHE/GOMODCACHE already global).
2026-07-05 06:13:08 +04:00
Ciprian Spiridon 628c4295cd Merge pull request #2 from yogeshkathayat/fix/ship-playbook-plan-reload-after-review 2026-07-01 05:57:45 +04:00
yogeshkathayat 85fcb33215 ship-playbook v1.9.1 — reload plan after plan-review fixes (fix stale-plan build)
Plan review's fix rounds edit the plan FILES on disk (planFixBrief: .json
source of truth, re-render .md) but return only FIX_RESULT {applied,notes} —
the in-memory `plan` object is never updated. buildPlan() reads plan.tasks
directly and never re-reads the files, so when a fix round runs the build
walks the PRE-FIX plan: founder-review fixes to writeScope / dependsOn /
layers / agent / validate silently don't reach the build.

Fix: planReviewLoop now reports whether it applied a fix; after any review
that did, reload the plan from disk (validate; keep the pre-fix object if the
reload fails to parse) so the build walks the fixed DAG. No-op when the review
is clean (no fix → no reload).
2026-06-30 14:15:57 +04:00
Ciprian Spiridon 26d681801b launch-x + launch-linkedin v1.0.0 — social launch platforms
Extends the launch-* family to X (Twitter) and LinkedIn — own-audience social
launches — grounded in current sources and reviewed across multiple adversarial
rounds (9 findings fixed, 0 blockers/highs; facts independently re-confirmed clean).

New skills:
- launch-x — X launch orchestrator: writes .ulpi/launch/x/ (POST thread, PLAN
  golden-hour runbook, OUTREACH, CHECKLIST, analytics). The link goes in a REPLY,
  not the main tweet (link-in-body reach penalty); golden-hour replies are the top
  lever (X's open-source code: a reply the author replies back to = 75.0, the
  highest positive signal); X Premium is ~table-stakes for reach (Buffer's 18.8M-
  post study, third-party). Phoenix (xAI, Jan 2026) replaced the heavy-ranker, so
  2026 weights are labeled non-official.
- launch-linkedin — LinkedIn launch orchestrator: writes .ulpi/launch/linkedin/.
  Problem-first hook (survives the ~140-char mobile "see more" fold), link in the
  FIRST COMMENT (it's the preview card that hurts, and the penalty is contested/
  smaller in 2026 — don't over-engineer), dwell-time-first (an officially confirmed
  signal). Sanctioned team amplification ("Notify Employees") vs banned engagement
  pods + engagement-bait (both official violations).

Unlike Product Hunt / Hacker News, these are own-audience posts with NO vote-
manipulation rule — you MAY ask your audience and team to genuinely engage. The
compliance work shifts to platform-penalized anti-patterns: engagement-bait,
bought/coordinated engagement / pods, and the link-in-body reach penalty.

Shared: launch-copy gains x + linkedin asset profiles; launch-outreach gains
x + linkedin engagement-allowed compliance modes + the engagement-bait scan.
README adds rows + sections for both. Each composes launch-copy / launch-outreach
/ launch-analytics with graceful fallback.
2026-06-29 15:27:45 +04:00
Ciprian Spiridon 988b166594 plan-to-task-list-with-dag v2.0.1 — slice-scoped validateCommand guidance 2026-06-29 13:52:06 +04:00
Ciprian Spiridon 9fe1690989 ship-playbook v1.9.0 — non-destructive failure handling, base-vs-introduced attribution, worktree provisioning 2026-06-29 13:52:06 +04:00
Ciprian Spiridon fec00468bd launch-* v1.0.0 — Product Hunt + Hacker News launch family
Adds a launch-skill family (one skill per platform + a shared core), grounded in
verified current sources and reviewed across 4 adversarial rounds (~43 findings
fixed, 0 blockers/highs; compliance + facts independently re-confirmed clean).

New skills:
- launch-product-hunt — PH platform orchestrator: grounds the product, writes a
  paste-ready package to .ulpi/launch/product-hunt/ (LISTING, PLAN with an
  hour-by-hour Pacific runbook, OUTREACH, CHECKLIST gate). Verified PH specs
  (tagline 60, description 500, gallery 1270x760, topics <=3, four newsletters,
  Golden Kitty -> Orbit, Coming Soon discontinued, re-launch 6mo + significant
  update); official vs third-party labeled.
- launch-hacker-news — Show HN platform skill: writes POST/PLAN/CHECKLIST to
  .ulpi/launch/hacker-news/. Grounded verbatim in showhn.html / newsguidelines /
  newsfaq / dang; ranking formula labeled non-official. Forbids ALL vote
  mobilization (stricter than PH); ready-to-ship gate (no signup wall, survives
  the hug of death); technical/no-hype voice.
- launch-copy — shared copywriting engine; caller passes an asset profile
  (assets/limits/voice/compliance); drafts A/B/C/D angle versions grounded in the
  real product.
- launch-outreach — shared outreach; per-platform compliance mode (PH waves OK,
  HN no mobilization); paste-ready, scan-clean message library.
- launch-analytics — shared UTM + GA4 conversion tracking.

Architecture: platforms compose the three shared skills with graceful fallback
(install-hint + built-in fallback, never hard-fail); one shared product brief at
.ulpi/launch/positioning.md, written once and reused. Compliance-first throughout
— coaches only compliant promotion, a banned-phrase scan gates every message,
refuses vote manipulation.

README: adds table rows + full sections for all five skills.
2026-06-29 13:13:32 +04:00
Ciprian Spiridon a43b0c68c2 ship-playbook v1.8.0 — per-task pipeline, conflict resolution, durable resume
Replaces the per-LAYER batch build with a PER-TASK PIPELINE and fixes the
whole-suite-validate false-block that ground clean slices to death. Hardened
across ~16 adversarial verify→fix rounds (each round: find → independently
confirm; the final round confirmed 0).

Per-task pipeline (build-loop.md, workflow-template.js buildPlan/runTask):
- each task is its own unit: build → integrate → review → fix, run CONCURRENTLY
  within a DAG layer. A task's review fires the moment IT integrates (not batched
  after the whole layer), and fix loops run in parallel across tasks — only the
  git merge serializes, via a single-slot merge lock. Layers stay barriered (DAG).
- integrate is MERGE-ONLY: no per-task whole-workspace VALIDATE_ALL. The old
  per-task `pnpm -r test` turned an OTHER task's failure (half-migrated tree) into
  a per-task blocker, looping a CLEAN-reviewed slice to MAX_FIX then false-blocking
  it. Whole-tree validation now runs ONCE at the final validate gate.
- merge CONFLICTS are resolved (combine both sides, validate BEFORE commit, abort
  only if truly unresolvable), not bailed. Merge is idempotent under retry
  (clears stale MERGE_HEAD; merge-base ancestry short-circuit; branch-gone fails
  CLOSED → dev_done/rebuild, never falsely 'integrated').

Fail-closed gates: a died/absent/empty reviewer (native/codex/kiro gateNotRun), a
died go-live audit, a blocking VERDICT with no finding, or a RED final validate all
keep openRegister non-empty → never a false converged. reviewOnce surfaces verdict;
per-task/impl/audit each guard the blocking-verdict-with-empty-findings case.

Durable resume + modes:
- wf-status.mjs --resume <id> emits the exact Workflow() relaunch from the status
  file (planPath + checkpointResume, no resumeFromRunId, no args to hand-assemble);
  the skill stores launchArgs at launch. SKILL.md Step 0 makes new-run vs resume
  first-class.
- LAST STEP: a converged (clean) run archives the delivered plan to
  .ulpi/plans/done/ (planArchived; skipped on needs_fix / external plans; non-fatal).

build-loop.md / playbook-state.md / SKILL.md / README updated; helper + template
syntax-checked; pure helpers unit-tested.
2026-06-27 17:24:49 +04:00
Ciprian Spiridon 9cfad9d6f7 ship-playbook v1.7.0 — checkpoint resume + DAG dependency gate + fail-closed gates
Hardened the build loop across nine adversarial verification passes (12→12→7→1→
4→4→3→3→0 confirmed findings; the false-clean invariant was independently
confirmed closed before shipping).

Checkpoint resume (durable, not cache-based):
- buildPlan reads the status file (readCheckpoints, before the plan-done write so
  it isn't clobbered) and SKIPS every task already done — 'passed' (skip engineer
  + review) or on-branch (integrated/reviewing/fixing/blocked → skip engineer,
  re-review). Independent of the runtime agent cache, which any template edit busts.
- SKILL.md: on resume REUSE the prior status file; do not overwrite it.

DAG dependency gate (build a task only when its deps are really on the branch):
- per-task dependsOn in the PLAN schema; planBrief requires complete deps +
  topological layers + slice-scoped validate + merging inseparable tasks;
  validatePlan rejects mis-ordered/cyclic/duplicate/omitted-task/unknown-dep plans
  (and derives topological layers when none are given).
- runtime gate: a fresh task builds only once every dependsOn is integrated on
  WORKING_BRANCH; a missing dep ⇒ dep_blocked (root-cause attribution, cascades).
  Integrate matched by branch/id (id-agnostic), not a TASK-NNN regex.

Slice-scoped review (no false end-state blocks) + fail-closed gates:
- reviewer judges only the task's writeScope vs its acceptance; fix loop acts only
  on in-scope blockers; fileInScope handles globs/abs-paths/empty-scope.
- a configured gate that did NOT run is NEVER clean: died/absent/empty reviewer
  (native/codex/kiro gateNotRun), died go-live audit, and a RED FINAL workspace
  validate (resume-safe, checks out WORKING_BRANCH) each keep openRegister
  non-empty. Returns planReviewRan/implReviewRan/auditRan/workspaceValidatePassed/
  endStateUngated/blockedTaskCount so the skill reports honestly. No uncaught throw
  crashes the run (build/review/integrate/audit/plan all fail-soft).

Live status: status-writer agents per phase + DAG layer; durable .ulpi/workflows/
<id>.json; new statuses dep_blocked/dev_done. build-loop.md, status-tracking.md,
SKILL.md (rules 11-12 + Phase-2/3), README updated. Template syntax-checked; pure
helpers unit-tested.
2026-06-27 14:04:14 +04:00
Ciprian Spiridon fe0b68c991 ship-playbook v1.6.3 — wf-status.mjs: name the in-flight agent(s) per task
reconstruct() already attributes reviews/fixes to tasks via the agent transcript
and reports latest-verdict-per-task (v1.6.2). This adds the last piece: surface
WHICH task each running agent is on. A started-with-no-result agent → its prompt
names the role+task → header shows "1 running NOW → fix:TASK-035#1" (and review:/
build:/integrate:…), plus --json.runningNow. No more bare "1 running".
2026-06-27 10:42:28 +04:00
Ciprian Spiridon 83118891cf ship-playbook v1.6.2 — wf-status.mjs: TRUE per-task status (join agent prompts)
The journal's review/fix results carry no task id, so the result-shape pass
couldn't tell "integrated" from "integrated but review-blocked" or see
review-pending. But each agent's transcript (agent-<id>.jsonl) starts with its
prompt, which names the role + task ("READ-ONLY review of TASK-032", "Fix
TASK-032 …", "integrate … wf/build/TASK-007"); agentId joins it to the journal
result + whether it finished.

- reconstruct(): join prompt(role+task) × result × started → true per-task status
  pending/building/dev_done/integrated/reviewing/fixing/passed/blocked/dev_failed,
  incl. review-PENDING and fixing. Reads only each transcript's first line; ~0.3s
  over ~280 agents.
- render / --json / --write now use a DISJOINT status partition (sums to total)
  with an onBranch rollup; --write stamps the true per-task status into the file.
- Verified on the live 75-task run: 13 passed, 24 review-blocked, 1 reviewing,
  14 dev-failed, 23 not started (was reported flatly as "38 integrated").

status-tracking.md documents the prompt-join. Helper syntax-checked.
2026-06-27 10:38:44 +04:00
Ciprian Spiridon d20b71e61c ship-playbook v1.6.1 — wf-status.mjs: fix project scoping (slugify like Claude)
wf-status.mjs scoped runs to the current project by slugifying cwd with only
'/' → '-', but Claude's project dir slug replaces EVERY non-alphanumeric char
(so '_' and '.' too): /Users/x/work_cip/ulpi-v6 → -Users-x-work-cip-ulpi-v6.
Any path with an underscore/dot never matched its own project, so the default
(no --all) reported "no workflow runs found for this project". Slugify cwd with
/[^a-zA-Z0-9]/g → '-' to match. Verified against the real ulpi-v6 run dir.
2026-06-27 10:23:52 +04:00
Ciprian Spiridon 0bd913b11f ship-playbook: description covers DAG-ordering, slice-scoped review, live status (v1.6.0) 2026-06-27 09:31:20 +04:00
Ciprian Spiridon efb4c460cf ship-playbook v1.6.0 — follow the DAG: enforce dependency ordering in the plan
A build task can fail because its acceptance/validate need state owned by a
not-yet-integrated task (e.g. TASK-053 needs the TASK-015 catalog rows + the
TASK-054 registry test). The build integrates layer-by-layer with a barrier, so
the real cause is a PLAN defect: the task was placed at/before its dependencies.
Fix it by following the DAG, not by retrying around it at runtime.

- PLAN schema: add per-task `dependsOn` (ids whose output the task needs).
- planBrief: require complete `dependsOn`; `layers` MUST be a topological order
  (a task strictly after everything it depends on); each `validate` slice-scoped
  (not a whole-suite e2e); merge two pieces that can't validate independently.
- validatePlan: ABORT a plan whose layers violate `dependsOn` (a task at/before a
  dependency, or a dep not scheduled earlier / missing) — refuse to build on a
  base where required upstream isn't integrated. Unit-tested against the 053 case.
- founderBrief (plan review): BLOCK incomplete deps, non-topological layers,
  whole-suite validates, and mutually-blocking split tasks.
- loadPlanBrief (resume): preserve `dependsOn`.

SKILL.md guardrail + build-loop.md "Follow the DAG" section + README updated.
Template syntax-checked; topological mis-order detection unit-tested.
2026-06-27 09:30:39 +04:00
Ciprian Spiridon 39a6f227d2 ship-playbook v1.5.1 — wf-status.mjs --write backfills a full resume recipe
For a run launched before v1.5.0 (no status file, incl. an in-flight one),
`wf-status.mjs --write` now reconstructs a complete .ulpi/workflows/<run>.json
from the journal: plan name/path, working branch (from the preflight result),
the full task list with title/agent/branch + per-task status, layer count, live
counts + merge conflicts, inferred phases, and a planPath-based resume command.

The journal holds no launch args (gate config / hardRules / validate / prompt are
script inputs, not agent results), so `--args '<json>'` folds them in to complete
the resume recipe. Marked partial:true. Documented in references/status-tracking.md
(new "Backfill" section) + SKILL.md. Verified against a live 75-task run.
2026-06-27 09:15:08 +04:00
Ciprian Spiridon 5742a54afa ship-playbook v1.5.0 — slice-scoped per-task review + live status file
Two fixes to the delivery Workflow (forward-only; does not affect in-flight runs,
which execute from their own persisted script snapshot).

1. Slice-scoped per-task review (stops false BLOCK storms).
   The build lands one DAG slice at a time, so per-task reviews ran against a
   half-migrated tree and BLOCKed tasks for whole-codebase end-state gaps a LATER
   task owns (e.g. "legacy paste path still exists" vs a task with no scope to remove
   it) — burning all 3 fix rounds, then recording a false "blocked" (observed 72/81
   blocked, ~184 BLOCKs dominated by one end-state finding).
   - reviewerBrief now judges only the task's own writeScope + diff against ITS
     acceptance criteria, and is given the rest of the plan so an unmet end-state
     invariant a later task owns becomes an OBSERVATION attributed to that task,
     never a BLOCK on the current slice.
   - The fix loop acts only on in-scope blockers (fileInScope matcher); out-of-scope
     findings are counted (crossTaskDeferred) and deferred, not retried.
   - Impl review (step 12) is now the explicit end-state gate over the integrated tree.

2. Live status tracking.
   - Durable <root>/.ulpi/workflows/<id>.json: skill creates it pre-launch (the
     Workflow sandbox has no FS), stamps runId + resume command, and the Workflow
     updates it at every phase + DAG layer via cheap haiku status-writer agents
     (all writes sequential → race-free; non-fatal, never blocks the build).
   - helpers/wf-status.mjs: journal reader reconstructing per-task status from the
     run's journal.jsonl (zero template changes, works mid-flight); cwd-scoped,
     --list/--json/--write, reads the durable file for phase/verdict. Ported and
     generalized from a tool first built in the ulpi-v6 repo.
   - Three verbs (status/stop/resume) documented; new references/status-tracking.md.

build-loop.md, playbook-state.md, SKILL.md (guardrails + EXTREMELY-IMPORTANT rules)
and README updated. Template + helper syntax-checked; fileInScope unit-tested 8/8.
2026-06-27 09:07:21 +04:00
Ciprian Spiridon 4cb94a6f32 kiro-review: model list inline; ship-playbook v1.4.0: kiro runs use latest Opus
- kiro-review SKILL.md: list valid kiro model names inline (auto, claude-opus-4.8/4.7/4.6,
  claude-sonnet-4.6/4.5/4, claude-haiku-4.5) so it's self-sufficient; note opus/sonnet aliases invalid.
- ship-playbook: new KIRO_MODEL const (default claude-opus-4.8 = latest Opus, override via CFG.kiroModel)
  injected into all three kiro briefs (build via hand-over-to-kiro, per-task review + routed review via
  kiro-review) → '--model claude-opus-4.8'. Documented kiroModel in the args contract.
2026-06-24 16:37:03 +04:00
Ciprian Spiridon 6d40f2d31f hand-over-to-kiro v1.4.0 + kiro-review v2.4.0 — run specific kiro agents (--agent/--model) + model list
Helper gains --agent <name> (run kiro as a custom .kiro/agents/<name>.json agent) and
--model <name> (override the model). Documented the real kiro model names from
'kiro-cli chat --list-models' in references/kiro-cli.md → Models (auto, claude-opus-4.6/4.7/4.8,
claude-sonnet-4/4.5/4.6, claude-haiku-4.5, deepseek-3.2, minimax, glm-5, qwen3-coder-next).

Verified live (kiro-cli 2.6.0):
- A kiro-NATIVE agent (valid model + fs_read/fs_write/execute_bash tools) implements end-to-end.
- The ulpi .kiro/agents/*.json do NOT work as-is: model 'opus' is invalid (hard error) and the
  Claude-style tool names (Read/Write/Skill) leave the agent with no working tools (writes nothing).
- --model auto rescues an agent that pins an invalid model.

So running specific agents works once the agent JSON is kiro-native (valid model + native tools) —
that generation is the AGENTS/ulpi ecosystem's job, not this repo. --skill injection remains the
zero-agent path that already works. Helpers byte-identical; bash 3.2 + set -u safe.
2026-06-24 16:33:24 +04:00
Ciprian Spiridon 6beec53150 docs: README + descriptions note kiro skill injection (--skill)
- README hand-over-to-kiro: injects the task's stack skill (--skill nextjs → helper resolves+prepends .kiro/skills/nextjs/SKILL.md).
- README kiro-review: can inject stack-convention skills (--skill <name>).
- Both SKILL.md descriptions mention skill injection (kiro has no Skill tool of its own) + the bundled scoped-trust helper.
2026-06-24 15:51:15 +04:00
Ciprian Spiridon d8f6e18914 hand-over-to-kiro v1.3.0 + kiro-review v2.3.0 — helper resolves+injects skills (--skill)
Doing skill-referencing in the helper, not as a prompt instruction the agent must
remember (same lesson as moving the prompt mechanics into the helper).

run-kiro.sh: new repeatable --skill <name> flag. Resolves .kiro/skills/<name>/SKILL.md
(or ~/.kiro/skills/<name>/), prepends it to kiro's STDIN under a <skill> tag with a
'read references/ on demand' note, and warns+skips an uninstalled name. Kiro has no
Skill tool, so this deterministic inject is how kiro follows a skill in a one-shot
--no-interactive run. bash 3.2/set -u safe (no arrays).

SKILL.md (both): Step 2.5 now just names the skills → pass --skill; removed the manual
<skills> prompt blocks. ship-playbook kiro brief passes --skill for the task's stackSkill.

Tested live end-to-end (kiro-cli 2.6.0): implement mode + --skill made kiro create a
file whose first line obeyed the injected skill's mandatory rule — proving the skill
drives behavior, not just that bytes arrived.
2026-06-24 15:49:12 +04:00
Ciprian Spiridon f08dc7eefe hand-over-to-kiro v1.2.0 + kiro-review v2.2.0 — reference kiro's installed skills
Kiro has a native skills feature (default agent auto-discovers .kiro/skills/ and
~/.kiro/skills/) but NO Skill tool and no --trust-tools token for it; skill bodies
load on demand, so a one-shot --no-interactive run can't rely on auto-activation
(confirmed against kiro.dev + AWS Amazon Q docs). The handoff never told kiro to
use the relevant skill, so kiro built without the stack conventions.

Fix (deterministic, no new tool/trust): the prompt-builder INLINES the relevant
.kiro/skills/<name>/SKILL.md into kiro's prompt under a <skill> tag and tells kiro
to follow it + fs_read its references/ on demand.
- hand-over-to-kiro: new Step 2.5 (reference relevant skills) + <skills> block in
  both prompt templates + a Skills section in references/kiro-cli.md documenting
  kiro's mechanism (auto-discovery, resources file://skill://, no Skill tool).
- kiro-review: inline a stack/convention skill so kiro reviews against it.
- ship-playbook kiro build brief: tell the handoff to inline the task's stackSkill.

Documents the native alternative too (--agent with resources:[file://...] preload).
2026-06-24 15:42:17 +04:00
Ciprian Spiridon db5ea97c5f README: kiro-review + hand-over-to-kiro reflect helper-based stdin launch + scoped trust
- kiro-review: scoped read-only trust (fs_read,execute_bash), Write-tool prompt over stdin (was 'full tool access').
- hand-over-to-kiro: helper feeds prompt via stdin + empty-prompt guard + scoped trust by mode; --trust-all-tools is opt-in only.
2026-06-24 13:44:15 +04:00
Ciprian Spiridon a4842c5f04 hand-over-to-kiro v1.1.0 + kiro-review v2.1.0 — helper-based launch, stdin prompt, scoped trust
The kiro skills hand-rolled a fragile inline launch (BSD mktemp choking on the
.txt suffix, stale files, kiro running on an empty prompt) and used
--trust-all-tools / -a even for read-only reviews (which the auto-mode classifier
blocks on non-mutating tasks). Modeled the fix on the codex companion: encapsulate
the mechanics in a helper, feed the prompt over stdin (not argv/shell).

helpers/run-kiro.sh (new, in both skills): locates kiro-cli, REFUSES to launch on
an empty prompt, scopes trust by mode (review=fs_read,execute_bash;
implement=fs_read,fs_write,execute_bash; autonomous=--trust-all-tools opt-in),
captures a git baseline, and feeds the prompt via STDIN (verified kiro-cli 2.6.0
reads stdin) — no mktemp, no heredoc, no argv, no shell parsing of the prompt.

SKILL.md (both): agent writes the prompt with the Write tool, then calls the
helper; trust scoped by task; never default to --trust-all-tools. ship-playbook
kiro build brief switched to implement mode (scoped write trust), not all-tools.

Tested live (kiro-cli 2.6.0): both helpers run review mode end-to-end, empty-prompt
guard returns exit 65.
2026-06-24 13:41:13 +04:00
Ciprian Spiridon 802931c923 ship-playbook v1.3.0 — resume from an existing reviewed DAG plan
Accept a pre-built, pre-reviewed plan and start at the build phase, skipping
plan-writing and plan-review. The skill passes either the parsed plan object
(args.plan) or a path (args.planPath); the Workflow sandbox can't read files, so
a path is loaded + validated + normalized by a load-plan agent. New validatePlan()
guards the DAG shape (tasks need id/agent/writeScope/validate; layers must
reference real ids) for supplied AND freshly-written plans, aborting cleanly if
malformed. PROMPT is no longer required when resuming (the plan is the spec).
Returns planSupplied so Phase 3 reports that plan-review was skipped by design.

SKILL.md: RESUME intake drops gate Q1 (plan writer) + Q2 (plan reviewer), asks the
other five, validates .ulpi/plans/<name>.json, passes planPath. README: note the
resume path. Distinct from the runtime's resumeFromRunId (mid-run crash recovery).
2026-06-24 13:16:44 +04:00
Ciprian Spiridon 8bd883c9bd docs: README reflects ship-playbook v1.2.0 retry + frontend-design-ui-ux v3.1.0; frontend description updated
- README ship-playbook: note rate-limit retry with exponential backoff.
- README frontend-design-ui-ux: .ulpi/design artifacts, design-system routing, delegated build.
- frontend-design-ui-ux SKILL.md description: mention .ulpi/design, the design system, and the build handoff.
2026-06-24 11:47:11 +04:00
Ciprian Spiridon d415399655 ship-playbook v1.2.0 — retry rate-limited agents with exponential backoff
A rate-limit storm previously surfaced as a wall of false 'blocked: engineer
validate failed' tasks: agent() returns null when a subagent dies on a terminal
API error after the runtime's own retries (the 0-token door-rejections), or
throws on a transient fault (cut off mid-flight). Those are not real build/review
failures.

Added withRetry(fn) + sleep + isRateLimit + RETRY_DELAYS ([3s,10s,30s], up to 4
attempts). Retries on null return or a rate-limit-shaped throw (429/overloaded/
529/quota); genuine errors (e.g. agent-not-found) still surface immediately.
Wired into makeGate (covers the parallel engineers/reviewers/verify lenses) and
via a rAgent() wrapper on the 9 non-gated sequential calls (plan, preflight,
integrate/re-integrate, plan-fix, cleanup, routed reviews).

Sandbox-safe: no Date.now/Math.random; sleep is setTimeout-guarded and degrades
to immediate retry. Resume-safe: cached results return non-null on attempt 1.
Worst case unchanged (still null after 4 attempts). Concurrency caps and control
flow untouched.
2026-06-24 11:46:59 +04:00
Ciprian Spiridon 31f1b9ff52 frontend-design-ui-ux v3.1.0 — artifacts in .ulpi/design, design-system routing, explicit build-delegation handoff
- Write all artifacts under .ulpi/design/ (matching .ulpi/plans, .ulpi/issues):
  DESIGN.md (locked, project-wide) + <feature>.md (flows, components, handoff).
- New design-system-routing.md: brief->system map (Radix/shadcn, Material 3,
  Carbon, Fluent, Polaris, GOV.UK, HIG) + honesty rule; design_system field
  locked in DESIGN.md. A design decision delegated to the builder, not code.
- Step 7 is now an explicit build handoff: target agent + chosen system +
  acceptance criteria ('implement exactly this; do not redesign'). Reinforced
  the boundary: building is delegated to an engineering agent; we own the spec.
- Dropped the optional mock-image line to stay a design-spec skill, not a
  generator. Text/ASCII wireframes in the flow/component templates remain.
2026-06-23 11:16:15 +04:00
Ciprian Spiridon a1fab2f896 README: document 9 missing skills, rewrite ship-playbook (one-pass/7-gate) + frontend-design-ui-ux (v3.0.0), note skills+MCP in map skills
- Add sections + table rows for browse-qa, review-crate, bugfix-crate,
  create-tests-extract, normalize-agent-for-claude, normalize-skill-for-claude,
  nodejs, nestjs, docker (53 skills now documented, was 44).
- Rewrite ship-playbook to the current one-pass / seven-gate / no-autonomous-loop
  reality (was described as a looping 2-question workflow).
- Rewrite frontend-design-ui-ux to v3.0.0: locked design language, anti-slop,
  browse inspiration intake, scored pre-flight, a11y rigor, design-not-code.
- Note the new Available Skills & MCP feature in map-project and map-project-monorepo.
2026-06-23 10:51:07 +04:00
Ciprian Spiridon c2c71a4328 frontend-design-ui-ux v3.0.0 — locked design language + anti-slop + scored pre-flight + browse inspiration intake
Rewrote the skill from a generic spec template into a taste + consistency
engine, after analyzing 7 high-install frontend-design skills (anthropic 578K,
leonxlnx taste family, impeccable, vercel). Stays a design-SPEC skill (no code).

New references: design-language-lock.md (per-project DESIGN.md the skill writes
and locks; register split; design-system routing; tunable dials), anti-slop.md
(named bans incl. em-dash + pattern vocabulary + slop test), design-preflight.md
(gated checklist + cognitive-load caps + scored self-critique with revise-and-
justify), inspiration-intake.md (visit reference links via the browse skill,
extract DNA, synthesize-not-clone).

design-tokens-template.md: replaced the hardcoded sky-blue/Inter default (which
produced generic output) with a per-brief derivation method (OKLCH, tinted
neutrals, 60-30-10, contrast-axis type pairing) + neutral structural scales.

SKILL.md: 8-step flow leading with Design Read -> locked identity -> flows/states
-> components -> pre-flight gate -> handoff. Added Skill to allowed-tools (browse).
Kept the a11y/state/flow rigor that no competitor matches. v2.0.0 -> v3.0.0.
2026-06-23 10:50:04 +04:00
Ciprian Spiridon 7d500b6d22 ship-playbook: cap concurrent agents with two gates to avoid Claude rate limits
The build and verify phases fanned out (engineers per DAG layer, reviewers per
layer, and dedupVerify's one-verifier-per-finding x up to 2 lenses) bounded only
by the runtime's min(16, cpu-2) cap, enough agents in flight to trip Claude API
rate limits (429s). Added two independent concurrency gates: buildGate
(MAX_BUILD_PARALLEL=4) for the heavy isolation worktree engineers, agentGate
(MAX_PARALLEL=6) for the light read-only reviewers/verifiers. Gated at the leaf
spawns (buildSpawn, taskReviewSpawn, verifyFinding lenses) so the cap holds no
matter how parallel nests; serial fix loop and single agents untouched. Total
agent count unchanged, only concurrency is bounded. Constants tunable (not 1-2).
ship-playbook 1.1.0.
2026-06-23 09:12:22 +04:00
Ciprian Spiridon 8d92dc0592 go-live-audit: cap concurrent agents with a global gate to avoid Claude rate limits
The audit fanned out finders, then one verifier per finding x up to 2 lenses,
plus a critic round, bounded only by the runtime's min(16, cpu-2) cap — enough
agents in flight at once to trip Claude API rate limits (429s). Added a global
concurrency gate (MAX_PARALLEL, default 6) and a gAgent() wrapper; routed every
spawn point (gates, finders, dedup, verify lenses, critic, follow-up finders)
through it. Control flow and parallel() barriers unchanged; total agent count
unchanged (~40-80) — only how many run at once is bounded, so they proceed in
waves. MAX_PARALLEL documented as a tunable (not 1-2). go-live-audit 1.1.0.
2026-06-23 09:04:12 +04:00
Ciprian Spiridon d0a435bd5c map-project, map-project-monorepo: record available skills + MCP servers in CLAUDE.md so agents prefer them
Both map skills now discover project-committed skills (.claude/skills/) and
enabled MCP servers (.mcp.json / .claude/settings*.json) and write an inline
'Available Skills & MCP — prefer these' section into CLAUDE.md (root CLAUDE.md
for the monorepo), plus a one-line pointer at the top of the file. Kept inline,
not in a lazy reference, because only always-loaded text changes behavior, so a
fresh agent stops forgetting the repo's own capabilities. New skills-and-mcp.md
reference carries discovery sources, redaction rules (never copy MCP secrets),
and the output format; SKILL.md steps, when-to-load, output-contract sections,
and verification gates updated. map-project 2.1.0, map-project-monorepo 3.1.0.
2026-06-21 06:53:50 +04:00
Ciprian Spiridon 27c46adc4a ship-playbook: read-only reviewers must not re-run validate (vitest EPERM in sandbox caused false CONCERN churn)
reviewerBrief told the read-only reviewer to confirm the per-task validate
'actually passes', so it re-ran the test command (vitest) in a read-only
sandbox; the runner's temp-dir mkdir EPERMs, surfacing a false 'tests not
green' CONCERN that re-triggered the fix loop even though integrate already
ran and passed that validate in a writable worktree. Now the reviewer reviews
statically and treats any check it cannot run in the sandbox as an OBSERVATION
(never BLOCK/CONCERN), so the loop converges once the real BLOCK is fixed.
Same guard added to implBrief and auditBrief.
2026-06-19 12:29:41 +04:00
Ciprian Spiridon 82c879e009 map-project, map-project-monorepo, kiro-review: drop disable-model-invocation so workflows can compose them
Root cause of "ship-playbook can't run these": all three set disable-model-invocation: true, which blocks
the Skill tool entirely — so neither the ship-playbook orchestrator (Phase 3 map refresh) nor its
workflow subagents (kiro review role) could invoke them, even though they were installed and loaded as
user slash commands. A restart never fixed it; the flag is intentional, not a load-timing issue.

The flag was too blunt: the real intent (per the bodies) is "don't run PROACTIVELY" because they mutate
durable memory (map-project*) or run an external CLI (kiro-review) — but they SHOULD be composable by an
explicit user-invoked workflow like /ship-playbook. Fix: remove disable-model-invocation (keep
user-invocable: true so the slash commands still work), and reword the EXTREMELY-IMPORTANT rule +
Guardrail from "explicit-user-only" to "no proactive invocation, but composable by an explicit
user-invoked workflow". Not changed: claude-review / codex-review stay user-only — ship-playbook does
not compose them (native review is an inline agent, codex review is the codex:codex-rescue plugin).
2026-06-19 10:33:37 +04:00
Ciprian Spiridon fd6fb05990 ship-playbook: correct specialist reviewer naming in the dependency check
A live run showed reviewer agents as "nextjs-reviewer"/"go-reviewer" — wrong. The reviewer is the FULL
engineer name + "-reviewer": nextjs-senior-engineer + nextjs-senior-engineer-reviewer, go-senior-engineer
+ go-senior-engineer-reviewer, etc. (matches the registry and the workflow's `reviewer = agent + '-reviewer'`).

The Step 1 examples were ambiguous ("nextjs-senior-engineer(+-reviewer)"), so the instance abbreviated
wrong. Now the skill spells out the full pair names and the install commands
(@nextjs-senior-engineer + @nextjs-senior-engineer-reviewer), and explicitly says never to shorten to
@nextjs-reviewer.
2026-06-19 10:24:17 +04:00
Ciprian Spiridon e30f547ae4 ship-playbook: 3-state dependency detection (ready / installed-needs-restart / missing)
Follow-up to the loaded-list fix: a skill installed to .claude/skills/ is only loaded into the
available-skills list at Claude STARTUP, so "installed on disk" != "usable this session". The previous
"use the loaded list, not disk" rule was right about usability but mislabeled an installed-but-not-yet-
restarted skill as plain "missing" — confusing when the skill IS available on disk.

Now three states:
- ready: in the loaded available-skills list / subagent_type options → usable now, not listed.
- installed, needs restart: not loaded, but present on disk via a SYMLINK-AWARE check
  (test -e / ls -laL .claude/skills/<name>, NOT find -type d) → shown with "Restart Claude to load",
  no install command.
- missing: not loaded and not on disk → shown with the full install command.

The two tables now list not-ready items with their state+action; the "present/ready" section is
explicitly forbidden (only show what needs action). kiro-cli binary detection is separate (name +
~/.local/bin PATH fallback).
2026-06-19 10:07:20 +04:00