本文へ移動
cccskills
無料GitHub で公開

prototype-loop

Leveraged-prototype dev loop (`pulp loop`) — focus marker plus normal watch/rebuild loop, with AOT analyzer guidance and deferred ar-swap/PR-monitor playbook. Use when porting an existing UI/bundle to Pulp, doing visual/behavioral parity work, or batching upstream framework gap fixes.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md13.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Prototype Loop Skill

Codifies the leveraged-prototype dev loop for closing framework gaps during high-feedback UI parity work.

When to use this skill

Trigger this skill when the user is doing any of:

  • Porting a UI to Pulp and wants tight visual-feedback iteration (Spectr's WebView editor → native via @pulp/react is the canonical example).
  • Gap-finding — they suspect there are framework gaps and want to enumerate them via an AOT analyzer.
  • Multi-PR upstream coordination — they're filing a batch of framework PRs and want a tight loop while upstream merges land.
  • Hitting slow cross-platform configure cost (Skia/Dawn/threejs FetchContent) on changes that only need single-platform validation during iteration.

Do not trigger for: bugfixes, cross-platform refactors, or final-landing flows. Those want the cross-platform default.

When NOT to use this skill

  • Pre-merge / landing the consumer's PR — always exit focus mode (or run shipyard pr / pulp pr) before landing. The ship path validates cross-platform regardless, but exiting focus mode keeps subsequent local iteration honest.
  • Bugfixes that touch platform-specific code — a cross-platform build is the cheapest correctness check for those.
  • Refactors that span subsystems — single-platform configure can mask a build break on a sibling platform.

The loop in one breath

analyze → file → prototype (ar-swap) → monitor → bump → ship

Each step has tooling. The CLI loop is available now; deeper archive-splice, issue-monitoring, and analyzer-lift work should land separately.

Current surface

SurfaceStatus
pulp loop CLI + skill + slash command + docsavailable
pulp-ar-swap.sh ABI-checked archive splicedeferred
pulp loop --watch-issues PR-monitordeferred
Lift @pulp/css-adapt, pulp-css-analyze, extract-html-bundledeferred

Step 0 — Start a new worktree warm, not cold

A fresh worktree's first build is a full configure plus every compile and link, even when the worktree you branched from built the same tree minutes ago. On macOS/APFS, pulp build --seed-build (or PULP_SEED_BUILD=1 in the environment so every first build does it) runs tools/scripts/seed_build_dir.py before the first configure. It clonefiles the warm Ninja build dir of the sibling worktree closest to HEAD (shared blocks, no data copied) and retargets it: text files that name the donor path are rewritten, .ninja_deps is re-emitted, .ninja_log command hashes are recomputed, binaries that embed the donor path are dropped, and unchanged clean sources get the donor's mtimes. The first build is then only what differs from the donor. Receipt: build/.pulp-seed-receipt.json (edges left to build, path-tainted binaries dropped, timings).

What to know before trusting it:

  • It only ever removes gratuitous work. Anything Ninja cannot prove up to date is rebuilt, and it reads the donor without writing it (the suite audits the donor's inodes and mtimes).
  • Eligible donors are Ninja, built, same CMAKE_BUILD_TYPE and PULP_BUILD_EXAMPLES, same APFS volume, and not mid-build. Anything else is refused with exit 3 and nothing left behind, and pulp build configures from scratch as usual. Cross-volume never silently copies.
  • A Release donor built through ccache with base_dir gains almost everything; a Debug donor (-g) embeds the path in every object and gains only the configure. Targets whose -D defines carry the source dir recompile regardless.
  • dirty_edges in the receipt is Ninja's planned total from a dry run of a copy of build.ninja. A plain ninja -n stops at CMake's always-dirty glob check and reports 2, and counting its status lines undercounts, because a dry run skips the status line of edges that finish together. When cmake_rerun_pending is non-empty (a CMakeLists.txt differs from the donor's, e.g. a VERSION bump) CMake re-runs first and the count is a lower bound.
  • pulp build in a fresh worktree has an empty diff, so its focused selector widens to all; on a seeded dir that is exactly the leftover edges, not a full build.

Never start the worktree under /tmp or $TMPDIR. Configure and governed-build.sh refuse it (exit 3), because a temporary tree misses the shared ccache and starts every build cold; create it under $PULP_WORKTREES_ROOT or beside the primary checkout. A second pulp build into a tree that is still building exits 75 and names the running build: attach to that one instead of relaunching. pulp loop takes the same lock for each rebuild, so a loop and a manual pulp build in one tree cannot race; a rebuild that finds another build holding the tree reports 75 and the loop keeps watching.

Step 1 — AOT analyze the consumer's bundle

Run pulp-css-analyze over the consumer's pre-built React bundle. The output is a coverage report listing unmapped CSS props with occurrence counts.

Reference output shape:

Unmapped CSS props (8 total):
  fontFamily            14×   examples: src/Label.tsx:23, src/Header.tsx:8, ...
  textAlign             6×    examples: src/Caption.tsx:12, ...
  ...

The occurrence counts are how you prioritize — file the 14× issue first.

Step 2 — File framework issues with the right shape

Each gap deserves its own issue. Use this shape:

  • One-line title — e.g. "Label.font_family_ accessor missing from public surface".
  • Occurrence count — "Used in 14 places across the Spectr bundle (see analyzer report URL)".
  • Acceptance criteria — concrete, testable. "label.set_font_family("Inter") followed by label.font_family() == "Inter" returns true".
  • Bridge-fn signature suggestion — "label.set_font_family(string) mirroring set_font()".
  • Cross-link to the analyzer report that surfaced it.

Filing 6 well-shaped issues with concrete signatures cuts upstream ramp-up dramatically. If you're going to file an umbrella + sub-issues, link the sub-issues from the umbrella's body so the dashboard view is coherent.

Step 3 — Enter focus mode (pulp loop)

pulp loop                       # auto-detect host platform
pulp loop --platform=macos      # explicit override
pulp loop --status              # report current state
pulp loop --off                 # restore cross-platform mode

The CLI persists [loop] focus_platform = "..." in ~/.pulp/config.toml. Subsequent invocations stay pinned until explicitly cleared.

The watch loop is also focused on the working diff by default: before every rebuild it re-runs the affected-target selector (pulp affected, script tools/scripts/affected_targets.py) and passes cmake --build --target only the targets that own the diff plus their companion test programs (test_<stem>*.cpp), following add_dependencies and CTest fixture edges. With --test it runs only those tests via ctest --tests-from-file. A one-line .cpp edit in core/view rebuilds pulp-view-core + pulp-test-widgets in seconds instead of relinking ~1,400 programs. The banner it prints is the contract:

FOCUSED: building 3/1708 targets affected by your diff - run 'pulp build --all' before opening a PR
  • pulp loop --all (and pulp dev --all, pulp build --all) restores the full build; --target and --test-filter always win; PULP_BUILD_FOCUS=0 disables focus for a shell.
  • The selector falls back to all and says why for an empty diff, a build-system change, an unmapped C/C++ file, or a selection above ~40% of the target graph. Header edits focus only when a dependency database exists (ninja -t deps or Makefile .o.d files).
  • The first focused run in an existing build dir configures once (~80 s) to record the CMake file-API codemodel it selects from.
  • Focused green is not landing green. Pre-push and Shipyard still build all; run pulp build --all && pulp test --all before shipyard pr.

A fresh source-checkout configure leaves the example projects off (-DPULP_BUILD_EXAMPLES=OFF) and pins Ninja + Release, like pulp build. When the prototype lives under examples/, pass pulp loop --examples so the first configure (or a reconfigure of a tree that has examples off) includes it. An existing tree an older CLI left on Makefiles, Debug, or examples ON is migrated on the first pulp loop: its cache moves to build/.pulp-pre-migration/, one Reconfiguring … (was: …) line prints, and the tree configures fresh (a one-time full rebuild). A prototype under examples/ must therefore pass --examples on every run, or the migration turns examples back off; PULP_KEEP_BUILD_CONFIG=1 keeps a tree as it is.

--no-watch flips state and exits without entering the watch loop — this is what tests use, and it's also useful when you want the marker but plan to drive builds yourself.

Step 4 — Local prototype via ar-swap

Pick the simplest gap from your filed issues. Build the framework patch in another worktree:

git worktree add ../pulp-fix-issue-X feat/fix-issue-X
cd ../pulp-fix-issue-X
cmake --build build --target pulp-view

The planned pulp loop --ar-swap-from ../pulp-fix-issue-X helper will splice the changed .o files into the pinned SDK's static archive after validating header/library ABI. The validator refuses on vtable mismatch — the failure mode where a consumer compiles against stale layout assumptions such as Label::font_family_.

Until that helper lands, do the ar-swap by hand:

  1. Build the patched object file in the other worktree.
  2. nm -gU the object — make sure exported symbols match what your consumer's compile expects.
  3. ar -r <pinned-sdk>/lib/libpulp-view.a <patched.o> — splice.
  4. Visually validate via pulp-screenshot or another explicit capture path.
  5. DELETE the local archive after validation. Otherwise you'll forget it's spliced and ship a binary that doesn't match the upstream pin.

Step 5 — Monitor upstream PR state flips

When automatic upstream monitoring is available:

pulp loop --watch-issues 924,927,931,932

will poll gh pr list for state flips on PRs referencing the named issues. It fires a notification when each PR transitions to MERGED.

Until then, run this in a side terminal:

watch -n 60 'gh pr list --state merged --search "924 OR 927 OR 931 OR 932" --json number,title,mergedAt'

Step 6 — Bump SDK pin and validate cross-platform

After the upstream batch merges and auto-releases:

  1. Bump the consumer's SDK pin in one shot (e.g. 0.52.0 → 0.56.0 if v0.53/v0.54/v0.55/v0.56 each came from one of the merged PRs). Update pulp.toml / find_package(Pulp …).
  2. Run pulp loop --off — restore cross-platform mode.
  3. Run shipyard pr (or pulp pr) — full cross-platform validation gates the merge. This is the contract: focus mode for iterating, cross-platform for landing.

Filing follow-up issues

When you discover a new framework gap while in focus mode, file it the same way as Step 2. Don't fix it locally and forget — the loop's discipline is upstream-first.

If you fixed something locally to keep iteration moving and the upstream issue isn't merged yet, leave a // TODO(issue-NNN) marker and a planning doc note in the consumer. The skill is "file framework issues immediately", not "fix and forget".

Switching modes

  • Enter: pulp loop --platform=macos → persists the focus marker and runs the normal project watch/rebuild loop.
  • Exit: pulp loop --off → restores cross-platform mode.
  • Land: shipyard pr (or pulp pr) → still runs full cross-platform validation before merge regardless of focus state.

The mode is advisory at the build layer today. The marker is read by tooling that wants to know "is the developer iterating or landing?", but it does not silently hide cross-platform breakage. Keep the marker semantically clean: "I am iterating, please don't surprise me with cross-platform configure cost."

Common pitfalls

  • Forgetting to exit focus mode before landing — pulp loop --off is one extra keystroke, but it's how you preserve the "single-platform for iterating, cross-platform for landing" separation. The ship path validates regardless, but the marker should match reality.
  • Locally hacking around a framework gap instead of filing it — easy to fall into, especially when you're in flow. The skill prompts upstream issue-filing as the preferred path; resist the local-fix temptation.
  • Drifting past merged upstream PRs — the planned --watch-issues monitor is the structural answer. Until then, set a 5-minute timer or pin the gh pr list watch in a side terminal.
  • ar-swap leaving SDK in inconsistent state — header vs .a vtable mismatch is the trap. The planned helper refuses on mismatch; until then, nm -gU the patched object before splicing and delete the local archive after validation.
  • Multiple worktrees on different focus platforms — the marker is per-PULP_HOME, so two worktrees pointing at the same ~/.pulp/config.toml share the marker. If you're working on macOS in one worktree and want a Linux focus check in another, use PULP_HOME=/tmp/pulp-linux pulp loop --platform=linux.

Slash command

The Claude Code slash command lives at .claude/commands/prototype-loop.md. It asks the user to confirm the focus platform, then orchestrates the loop.

Reference

  • Planning issue: leveraged-prototype dev loop.
  • Validation example: Spectr native React editor coverage using focused Pulp framework-gap issues.
  • Coverage report: spectr feature/native-react-editor branch, planning/spectr-style-coverage-report.md
  • Companion docs: docs/guides/focus-mode.md

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

aax

無料

Optional AAX support for Pulp, including developer-supplied Avid SDK setup, CMake enablement, DigiShell/AAX Validator workflows, and local AAX builds on macOS or Windows.

日本語の概要は準備中です。原文の説明を表示しています。

Generous-Corp/pulp222026年10月10日 更新

Configure, implement, and test Pulp's optional desktop Ableton Link tempo-sync adapter while preserving the developer-supplied SDK, licensing, realtime, latency-compensation, and no-install boundaries.

日本語の概要は準備中です。原文の説明を表示しています。

Generous-Corp/pulp222026年10月10日 更新

Maintain Pulp's installed design-time agent capability manifest and public-surface ledger. Use when adding, removing, renaming, or materially changing public audio, MIDI, signal, timebase, or sequence APIs; registering a new algorithm for generators; changing capability support or deprecation state; or repairing agent-capabilities freshness, schema, fingerprint, tombstone, or installed-SDK tests.

日本語の概要は準備中です。原文の説明を表示しています。

Generous-Corp/pulp222026年10月10日 更新

android

無料

Android platform development for Pulp — NDK cross-compilation, Oboe audio, Dawn/Skia GPU rendering, JNI bridge, touch interaction, emulator workflows, and end-to-end smoke validation. Covers build, deploy, debug, and the gotchas discovered during bringup.

日本語の概要は準備中です。原文の説明を表示しています。

Generous-Corp/pulp222026年10月10日 更新

ara

無料

Optional ARA support for Pulp, including developer-supplied ARA SDK setup, CMake enablement, adapter companion APIs, validation, and ARA-aware plugin implementation guidance.

日本語の概要は準備中です。原文の説明を表示しています。

Generous-Corp/pulp222026年10月10日 更新

The measurement surface for ALL Pulp DSP and audio-pipeline work — read it BEFORE writing or gating DSP, not only when something already sounds wrong. Covers the C++ harness (signal generators, metrics, assertions, RenderScenario, contracts), the offline Audio Doctor (magnitude/frequency response, THD/THD+N, phase/group delay), and their Python sibling the Audio Quality Lab (tools/audio/quality-lab — null residual + alignment, LTAS log-spectral distance, spectral flux/centroid, HNR, Theil-Sen drift slope, Kaiser-sinc resampling, license-guarded corpus, regression-net ratchet). TRIGGER on AUTHORING work — "build/design an oscillator/filter/synth/effect", "add a DSP module", "what should the acceptance gate be", "how do I measure aliasing / anti-aliasing / alias floor", "null against a reference", "is this DSP correct", "choose a tolerance", "golden/regression corpus for audio", "measure drift or jitter", "A/B two renders" — AND on DEBUGGING work — "is there sound / no audio / I hear nothing", "does this filter/compressor/synth/delay produce the right signal", "prove the DSP / prove the contract", "measure the frequency response", "what's the THD / is it distorting", "what's the group delay / phase response / measured latency", "magnitude response curve", "render a test tone and assert", "audio regression", "64-frame works but 128 is silent", "sample-rate change pitch-shifted it", "describe what's in this buffer", "audio doctor", "compare before/after a DSP refactor". Reach for this BEFORE hand-rolling any FFT, null test, alias measurement, pitch tracker, or golden-render script — most of it already exists in one of the two lanes. Test/tool layer over HeadlessHost — deterministic, no audio device, no speakers. Off the realtime thread entirely.

日本語の概要は準備中です。原文の説明を表示しています。

Generous-Corp/pulp222026年10月10日 更新

Generous-Corp のスキルをすべて見る

このスキルの問題を報告する