Skip to main content

jobcard-system

Use when working in the jobcard repository, dispatching agents, writing specs, creating cards, or understanding the card lifecycle. This is a multi-agent task orchestration system — NOT the transit data standard.

Jump to install

Source facts

Repository
ryanmaclean/skills
Last source activity
April 15, 2026 at 03:58
Detected SKILL.md language
English
Stars
1
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
jobcard-system
description
Use when working in the jobcard repository, dispatching agents, writing specs, creating cards, or understanding the card lifecycle. This is a multi-agent task orchestration system — NOT the transit data standard.
# Jobcard System (bop) ## Naming — COMPLETE (2026-03-01) | Role | Name | |------|------| | CLI binary | **`bop`** | | Quick Look bundle | `sh.bop.ql` | | Host app bundle | `sh.bop` | | Card UTI | `sh.bop.card` | | launchd labels | `sh.bop.dispatcher`, `sh.bop.merge-gate` | ```bash bop new implement feat-auth # deal a card into pending/ bop status # card counts by state bop dispatcher --once # process one pending card bop merge-gate --once # process one done card bop inspect <id> # show meta + spec + log tail bop approve <id> # clear decision_required gate bop kill <id> # terminate running agent bop logs <id> # colorized log tail (tailspin-style) bop poker open <id> # start estimation round bop poker submit <id> [--glyph 🂻] [--name alice] bop poker reveal <id> # reveal all estimates bop poker consensus <id> --glyph 🂻 # lock in final estimate bop factory install # generate + load launchd plists bop factory status # check if services are running bop factory start # start both services bop factory stop # stop both services bop factory uninstall # unload + remove plists bop icons # FSEvents watcher: auto-updates Finder icons on state change bop gantt # ANSI Gantt timeline in terminal (auto-fits pane) bop gantt -w 80 # force width (Zellij panes) bop gantt --html # write .cards/bop-gantt.html bop gantt -o # write HTML + open in browser bop events # OpenLineage event stream bop events --card <id> # filter events by card ``` `bop factory install` also sets up the icon watcher alongside dispatcher and merge-gate. ## MICROCLAW Principle **Fewer files. Sharper precision. Minimum viable factory.** - Every file has exactly one job - Agents can participate with just `mkdir` + `echo '{}' > meta.json` - The FORMAT is the product; the CLI is one thin reference impl - Like **Apache Iceberg** (table format, any engine reads/writes) ## Core Framing The filesystem IS the state machine. Playing cards ARE the identity system. The FORMAT is the product. ```sh # Minimum viable card — no CLI needed mkdir -p .cards/pending/my-task.jobcard echo '{"id":"my-task","stage":"implement","created":"2026-03-01T00:00:00Z"}' \ > .cards/pending/my-task.jobcard/meta.json echo "# My Task\nDo X" > .cards/pending/my-task.jobcard/spec.md ``` ## Architecture ``` .cards/ stages/ ← stage instruction files (spec.md, plan.md, implement.md, qa.md) templates/ ← factory recipes (implement, full, cheap, qa-only) system_context.md ← prepended to every agent prompt <team>/<state>/<id>.jobcard/ meta.json ← card identity, stage pipeline, glyph, labels, subtasks spec.md ← what to build prompt.md ← rendered from template, sent to agent logs/ ← stdout.log, stderr.log, pid, lease.json output/ ← result.md, cards.yaml (child card seeds) QuickLook/ ← Thumbnail.png for Finder preview ``` ## State Machine ``` pending/ → running/ → done/ → merged/ ↓ failed/ ``` Transitions are atomic `fs::rename`. Dispatcher owns `pending/→running/`. Merge-gate owns `done/→merged/` (runs acceptance_criteria first). ## Filename Glyph Lifecycle (Poker) Use filename prefix for poker visibility while keeping `meta.id` canonical. - Before consensus: `🂠-feat-auth.jobcard` - After consensus: `🂻-feat-auth.jobcard` - Keep `meta.id` stable as `feat-auth` (CLI queries stay stable) Safe rename flow (filesystem-first, same volume): 1. Only rename outside `running/` (prefer `pending/`; allow `done/`/`failed/` for cleanup). 2. Hold card lock / ownership gate; assert destination path does not exist. 3. Apply atomic rename (`fs::rename`). 4. If poker consensus finalized a glyph, write `meta.glyph` in the same critical section. 5. Refresh visual artifacts (`QuickLook/Thumbnail.png` + Finder icon). ## Stage Pipeline (Factory Engine) Templates define the stage pipeline via these `meta.json` fields: | Field | Type | Example | |-------|------|---------| | `stage_chain` | `Vec<String>` | `["implement", "qa"]` | | `stage_models` | `Map<String,String>` | `{"implement":"opus","qa":"sonnet"}` | | `stage_providers` | `Map<String,String>` | `{"implement":"claude","qa":"codex"}` | | `stage_budgets` | `Map<String,u64>` | `{"implement":32000,"qa":8000}` | When a stage finishes (exit 0), dispatcher reads `stage_chain`, creates next-stage child card in `pending/` inheriting spec + glyph + prior output. Final stage → done/. All four fields are on the Meta struct (landed 2026-03-01). `render_prompt` substitutes `{{stage_instructions}}`, `{{stage_index}}`, `{{stage_count}}`, `{{prior_stage_output}}`. Dispatcher auto-advances stages via `maybe_advance_stage()`. ## Stage Instruction Files `.cards/stages/` — one markdown file per stage, ~50 tokens each: | File | Agent's job | |------|------------| | `spec.md` | Write a spec under 500 words. No code. | | `plan.md` | Read spec, produce ordered steps under 800 words. | | `implement.md` | Write code, run tests, exit 0 when green. | | `qa.md` | Review as a different agent. Be skeptical. | Custom stages: create `.cards/stages/<name>.md`, add to template's `stage_chain`. ## Context Window Architecture Every token earns its slot. Dispatcher builds prompts by layering: ``` system_context.md ~150 tokens domain fix stages/<stage>.md ~50 tokens stage behavior card header ~20 tokens id + glyph + stage index spec.md variable the work prior_stage_output variable previous stage result acceptance_criteria ~10 tokens shell gates ``` Template variables in `prompt.md`: - `{{system_context}}` — `.cards/system_context.md` (WORKS) - `{{stage_instructions}}` — `.cards/stages/<stage>.md` (WORKS) - `{{stage_index}}` / `{{stage_count}}` — position in chain (WORKS) - `{{prior_stage_output}}` — previous stage's `output/result.md` (WORKS) - `{{spec}}`, `{{plan}}`, `{{acceptance_criteria}}`, `{{memory}}` — WORK ## Templates Live in `.cards/templates/`. Four shipping templates: | Template | Stages | Models | Cost | Use When | |----------|--------|--------|------|----------| | **implement** | implement → qa | opus → sonnet | $$ | Clear requirements | | **full** | spec → plan → implement → qa | sonnet → sonnet → opus → sonnet | $$$ | Complex/ambiguous | | **cheap** | implement | ollama-local | free | Small fix, local model | | **qa-only** | qa | sonnet | $ | Code review, audit | **Create your own:** `cp -c -R .cards/templates/implement.jobcard .cards/templates/mine.jobcard` then edit `meta.json` (stage_chain, stage_models, stage_providers, stage_budgets). See `plan.md` §8 for annotated meta.json reference. COW-clone: `cp -c` (macOS APFS) or `cp --reflink=auto` (Linux). ## APFS Copy, Dedupe, Compression (macOS) - Fast template clone: `cp -c -R` (clonefile/COW on APFS). - Metadata-safe bundle copy: `ditto --clone --extattr --acl --qtn --preserveHFSCompression <src> <dst>`. - Keep default atomic replacement behavior; avoid `ditto --nonAtomicCopies` for card bundles. - Cold-card storage option: `ditto --hfsCompression` (or preserve existing compression with default `--preserveHFSCompression`). - For archive export/import, use `ditto -c -k` / `ditto -x -k`; prefer staging + atomic move into `.cards/`. ## Filename Tooling Compatibility (macOS 26.3 validation) With `🂠-feat-auth.jobcard` on APFS, these worked in tests: - `rg`, `tail`, `eza`, `bat` - `bop inspect feat-auth` - `bop logs feat-auth` - `bop logs -f feat-auth` when the card is in `running/` `exa` is no longer a Homebrew formula; standardize on `eza`. ## Filesystem Hardening 1. **Dispatcher lock:** `.cards/.locks/dispatcher.lock/owner.json` - Acquire with atomic `mkdir`; reject if live owner PID exists - Reclaim stale lock (dead PID) and continue 2. **Run lease per card:** `logs/lease.json` - Fields: `run_id`, `pid`, `pid_start_time`, `started_at`, `heartbeat_at`, `host` - Dispatcher heartbeats every 5s; stale floor is 30s 3. **Orphan reaping:** reap when PID dead OR lease stale - Normalize stale stage metadata (`running → pending/failed`) 4. **Idempotent controls:** - `bop kill <id>` succeeds even with stale PID - `bop retry <id>` clears failure reason + normalizes stage ## Meta.json Fields | Field | Meaning | |-------|---------| | `glyph` | SMP playing card (suit=team, rank=priority) | | `token` | BMP symbol for terminals/filenames | | `stage` | Current stage: spec / plan / implement / qa | | `stage_chain` | Full pipeline: `["implement","qa"]` | | `stage_models` | Model per stage: `{"implement":"opus"}` | | `stage_providers` | Adapter per stage: `{"implement":"claude"}` | | `stage_budgets` | Token budget per stage: `{"implement":32000}` | | `stages.<s>.status` | pending / running / done / blocked / failed | | `zellij_session` | Zellij session name for running card | | `zellij_pane` | Zellij pane ID for running card | | `worktree_branch` | Git branch — never touch main | | `acceptance_criteria` | Shell commands merge-gate runs | | `decision_required` | true = merge-gate holds; `bop approve` clears | | `provider_chain` | Failover order: `["claude","codex","ollama-local"]` | | `timeout_seconds` | Kill agent after this many seconds | | `estimates` | Planning poker: `{"alice":"🂻","bob":"🂺"}` | | `poker_round` | "open" / "revealed" / absent | | `labels` | `[{"name":"High Impact","kind":"effort"}]` | | `subtasks` | `[{"id":"s1","title":"Do X","done":false}]` | | `progress` | 0–100 overall completion % | ## Adapter Contract ``` adapter.zsh <workdir> <prompt_file> <stdout_log> <stderr_log> [timeout] ``` | Exit | Meaning | Action | |------|---------|--------| | 0 | Success | → done/ | | 75 | Rate-limited | → pending/, rotate provider | | other | Failure | → failed/ | Available: `claude.zsh`, `codex.zsh`, `ollama-local.zsh`, `goose.zsh`, `aider.zsh`, `opencode.zsh`, `mock.zsh`. ## Planning Poker Suit → perspective: ♠=complexity ♥=effort ♦=risk ♣=value. Rank → magnitude: Ace=1, 2-10=face, Jack=13, Queen=21, King=40. Joker (🃟/🃏) → needs breakdown, blocks consensus. ## Scripts | Script | Purpose | |--------|---------| | `scripts/land_safe.zsh` | JJ/git safe-landing with gate checks | | `scripts/bop_bop.zsh` | Goal→card→Zellij session bootstrap | | `scripts/bop_focus.zsh` | Navigate Zellij panes by card id | | `scripts/macos_cards_maintenance.zsh` | Thumbnail refresh, cold card compression | | `scripts/render_card_thumbnail.swift` | Generate QuickLook/Thumbnail.png | | `scripts/set_card_icon.swift` | Stage-coloured Finder icons for .jobcard bundles | All zsh scripts use `ROOT=${0:A:h:h}`. `setopt NULL_GLOB` for `.jobcard` globs. Never use `done` as a variable (zsh reserved — use `n_done`).
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub