@ai-dev-methodologies/rlp-desk 0.11.1 → 0.12.0

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.
Files changed (44) hide show
  1. package/docs/rlp-desk/artifact-schema.md +99 -0
  2. package/docs/rlp-desk/ci-setup.md +100 -0
  3. package/docs/rlp-desk/e2e-scenarios.md +102 -0
  4. package/docs/rlp-desk/plans/rlp-desk-tmux-flywheel-routing.md +730 -0
  5. package/install.sh +93 -20
  6. package/package.json +8 -2
  7. package/scripts/build-node-manifest.js +52 -0
  8. package/scripts/postinstall.js +162 -8
  9. package/src/commands/rlp-desk.md +48 -25
  10. package/src/governance.md +55 -6
  11. package/src/node/MANIFEST.txt +15 -0
  12. package/src/node/cli/command-builder.mjs +25 -5
  13. package/src/node/constants.mjs +19 -0
  14. package/src/node/polling/signal-poller.mjs +119 -3
  15. package/src/node/runner/campaign-main-loop.mjs +470 -41
  16. package/src/node/runner/leader-registry.mjs +100 -0
  17. package/src/node/runner/prompt-dismisser.mjs +200 -0
  18. package/src/node/shared/fs.mjs +38 -0
  19. package/src/node/util/debug-log.mjs +56 -0
  20. package/src/node/util/shell-quote.mjs +12 -0
  21. package/docs/superpowers/plans/2026-04-24-gpt-5-5-default.md +0 -517
  22. package/docs/superpowers/specs/2026-04-24-gpt-5-5-default.md +0 -107
  23. /package/docs/{TODO-verification-next.md → rlp-desk/TODO-verification-next.md} +0 -0
  24. /package/docs/{architecture.md → rlp-desk/architecture.md} +0 -0
  25. /package/docs/{blueprints → rlp-desk/blueprints}/blueprint-flywheel-enhancement.md +0 -0
  26. /package/docs/{blueprints → rlp-desk/blueprints}/blueprint-pivot-step.md +0 -0
  27. /package/docs/{blueprints → rlp-desk/blueprints}/plan-flywheel-enhancement.md +0 -0
  28. /package/docs/{blueprints → rlp-desk/blueprints}/sv-architecture-rethink.md +0 -0
  29. /package/docs/{getting-started.md → rlp-desk/getting-started.md} +0 -0
  30. /package/docs/{internal → rlp-desk/internal}/verification-policy-gap-analysis.md +0 -0
  31. /package/docs/{internal → rlp-desk/internal}/verification-strategy-research.md +0 -0
  32. /package/docs/{multi-mission-orchestration.md → rlp-desk/multi-mission-orchestration.md} +0 -0
  33. /package/docs/{plans → rlp-desk/plans}/cozy-gliding-trinket.md +0 -0
  34. /package/docs/{plans → rlp-desk/plans}/frolicking-churning-honey.md +0 -0
  35. /package/docs/{plans → rlp-desk/plans}/keen-sauteeing-snowflake.md +0 -0
  36. /package/docs/{plans → rlp-desk/plans}/mutable-booping-corbato.md +0 -0
  37. /package/docs/{plans → rlp-desk/plans}/rlp-desk-0.11-handoff-7fixes.md +0 -0
  38. /package/docs/{plans → rlp-desk/plans}/rlp-desk-0.11.1-tmux-pane-disappearance.md +0 -0
  39. /package/docs/{plans → rlp-desk/plans}/rlp-desk-elegant-papert-agent-a8cd695ffca2a3ad8.md +0 -0
  40. /package/docs/{plans → rlp-desk/plans}/rlp-desk-elegant-papert.md +0 -0
  41. /package/docs/{plans → rlp-desk/plans}/toasty-whistling-diffie-agent-a6814625642e956da.md +0 -0
  42. /package/docs/{plans → rlp-desk/plans}/toasty-whistling-diffie.md +0 -0
  43. /package/docs/{plans → rlp-desk/plans}/validated-snacking-crayon.md +0 -0
  44. /package/docs/{protocol-reference.md → rlp-desk/protocol-reference.md} +0 -0
@@ -0,0 +1,99 @@
1
+ # rlp-desk Artifact Schema (v5.7 §4.25)
2
+
3
+ > Worker/Verifier write JSON artifacts that the Leader reads. The schema validator at the READ boundary enforces these contracts. **Violation → BLOCKED `contract_violation/malformed_artifact`** (recoverable).
4
+
5
+ ## Validated artifacts
6
+
7
+ | File | Written by | Read by | `signal_type` |
8
+ |------|-----------|---------|---------------|
9
+ | `<slug>-iter-signal.json` | Worker | Leader (worker poll) | `signal` |
10
+ | `<slug>-verify-verdict.json` (per-US) | Verifier | Leader (verifier poll) | `verdict` |
11
+ | `<slug>-verify-verdict.json` (final ALL) | Verifier | Leader (final-verifier poll) | `verdict` |
12
+ | `<slug>-flywheel-signal.json` | Flywheel | Leader (flywheel poll) | `flywheel_signal` |
13
+ | `<slug>-flywheel-guard-verdict.json` | Guard | Leader (guard poll) | `flywheel_guard_verdict` |
14
+ | `<slug>-done-claim.json` | Worker | Leader (analytics, A4 fallback) | `done_claim` |
15
+
16
+ ## Required structural fields (validated by `validateArtifact`)
17
+
18
+ | Field | Type | Constraint | Notes |
19
+ |-------|------|------------|-------|
20
+ | `slug` | string | === campaign slug | OPTIONAL for backward compat. If present, must match. |
21
+ | `iteration` | integer | ≥ `iteration_floor` (current state.iteration) | OPTIONAL for backward compat. Worker may advance, never regress. |
22
+ | `signal_type` | string | === expected per read context | OPTIONAL for backward compat. Discriminates artifacts at read time. |
23
+ | `us_id` | string | ∈ `usList ∪ {'ALL'}` | OPTIONAL for backward compat. Closed-set check. |
24
+
25
+ The validator is structural-minimum + semantic-anchor. It does NOT validate downstream business fields (e.g. `verdict.verdict`, `signal.status`); those are checked by their respective consumers.
26
+
27
+ ## Examples
28
+
29
+ ### Valid worker signal
30
+ ```json
31
+ {
32
+ "slug": "sum-fn",
33
+ "iteration": 1,
34
+ "signal_type": "signal",
35
+ "us_id": "US-001",
36
+ "status": "verify",
37
+ "summary": "implementation done; tests pass"
38
+ }
39
+ ```
40
+
41
+ ### Valid verifier verdict
42
+ ```json
43
+ {
44
+ "slug": "sum-fn",
45
+ "iteration": 1,
46
+ "signal_type": "verdict",
47
+ "us_id": "US-001",
48
+ "verdict": "pass",
49
+ "criteria_results": [...]
50
+ }
51
+ ```
52
+
53
+ ### Violation: wrong slug
54
+ ```json
55
+ {
56
+ "slug": "wrong-campaign", // ← BLOCKED contract_violation
57
+ "iteration": 1,
58
+ ...
59
+ }
60
+ ```
61
+ → `Malformed artifact at slug: expected sum-fn, got wrong-campaign`
62
+
63
+ ### Violation: us_id outside allowed set
64
+ ```json
65
+ {
66
+ "us_id": "US-999" // ← BLOCKED contract_violation (US-999 ∉ [US-001, ALL])
67
+ }
68
+ ```
69
+ → `Malformed artifact at us_id: expected one of [US-001, ALL], got US-999`
70
+
71
+ ### Violation: iteration regress
72
+ ```json
73
+ {
74
+ "iteration": 0 // ← floor is 1; regress not allowed
75
+ }
76
+ ```
77
+ → `Malformed artifact at iteration: expected >= 1, got 0`
78
+
79
+ ## Backward compatibility
80
+
81
+ Existing artifacts written before v5.7 §4.25 do not carry `slug`/`signal_type`/`iteration` fields. The validator skips any field not present (`undefined` is allowed). Workers/Verifiers SHOULD start emitting these fields for stronger contract enforcement, but legacy artifacts continue to work.
82
+
83
+ ## Feedback loop closure
84
+
85
+ When `MalformedArtifactError` fires:
86
+ 1. `_handlePollFailure` writes BLOCKED with `reason_category: contract_violation`, `failure_category: malformed_artifact`, `recoverable: true`.
87
+ 2. `reason_detail` includes the structured error: `Malformed artifact at <field>: expected <expected>, got <got>`.
88
+ 3. Operators reviewing `<slug>-blocked.json` see the precise contract violation and can update the Worker prompt template (`prompts/<slug>.worker.prompt.md`) to require the missing/correct field.
89
+ 4. On re-run after fix, the Worker writes a compliant artifact and the campaign proceeds.
90
+
91
+ ## Authoring guidance
92
+
93
+ - Worker prompt templates SHOULD instruct the LLM to include `slug`, `iteration`, `signal_type`, and `us_id` in every JSON artifact.
94
+ - The fix-contract (`buildFixContract` in `campaign-main-loop.mjs`) already feeds verifier failures back to the next Worker; future enhancement: feed `MalformedArtifactError` details directly into the next Worker prompt without requiring user re-run.
95
+
96
+ ## Audit
97
+
98
+ - Schema unit tests: `tests/node/test-artifact-schema.mjs` (7 violation scenarios)
99
+ - E2E: Schema violations are exercised in `tests/sv-gate-full.sh` (REAL campaign E2E asserts `complete.md` or `blocked.md` exists — schema violations route to the latter)
@@ -0,0 +1,100 @@
1
+ # rlp-desk CI Setup (v5.7 §4.25)
2
+
3
+ > SV gate is a mechanical contract: every PR touching `src/node/**`, `src/scripts/**`, `src/commands/rlp-desk.md`, or `src/governance.md` MUST pass `tests/sv-gate-full.sh` before merge.
4
+
5
+ ## Local development
6
+
7
+ ### Fast gate (~30s)
8
+
9
+ Run before every commit:
10
+
11
+ ```sh
12
+ zsh tests/sv-gate-fast.sh
13
+ # or
14
+ npm run sv-gate:fast
15
+ ```
16
+
17
+ Checks:
18
+ - 35+ code-pattern greps (each tracked v5.7 fix has the expected code)
19
+ - All Node unit tests (~50)
20
+ - 5 critical zsh unit tests
21
+
22
+ ### Full gate (~5 min)
23
+
24
+ Run before merge / release:
25
+
26
+ ```sh
27
+ zsh tests/sv-gate-full.sh
28
+ # or
29
+ npm run sv-gate:full
30
+ ```
31
+
32
+ Adds:
33
+ - REAL tmux E2E (mocked tmux capture, 9 scenarios)
34
+ - REAL campaign E2E (haiku worker/verifier, max-iter 3, iter-timeout 300s)
35
+ - Asserts `<slug>-complete.md` OR `<slug>-blocked.md` exists post-run (file-guarantee invariant)
36
+
37
+ **Pre-conditions for full gate**:
38
+ - Inside a tmux session (`echo $TMUX` not empty)
39
+ - `claude` CLI in PATH
40
+ - `node` >= 16 in PATH
41
+ - `~/.claude/ralph-desk/` synced from latest `src/` (run `bash install.sh` or manual sync)
42
+
43
+ ## GitHub Actions
44
+
45
+ The fast gate runs on every PR via `.github/workflows/sv-gate.yml`:
46
+
47
+ ```yaml
48
+ name: SV Gate
49
+ on: [push, pull_request]
50
+ jobs:
51
+ sv-gate-fast:
52
+ runs-on: macos-latest # zsh + tmux available
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - uses: actions/setup-node@v4
56
+ with: { node-version: '22' }
57
+ - run: bash install.sh # syncs to ~/.claude/ralph-desk
58
+ env: { REPO_URL: file://${{ github.workspace }} }
59
+ - run: zsh tests/sv-gate-fast.sh
60
+ ```
61
+
62
+ The full gate (with REAL campaign E2E) is NOT run in CI — it requires:
63
+ - Anthropic API key (haiku worker/verifier)
64
+ - Live tmux session (CI runners are non-interactive)
65
+ - ~3-5 min wallclock per run
66
+
67
+ Operators MUST run `tests/sv-gate-full.sh` locally before merging to `main`.
68
+
69
+ ## Branch protection (manual)
70
+
71
+ Required for the SV gate to be enforceable:
72
+
73
+ 1. Go to `https://github.com/<owner>/rlp-desk/settings/branches`
74
+ 2. Add rule for `main`:
75
+ - ✅ Require a pull request before merging
76
+ - ✅ Require status checks to pass before merging
77
+ - ✅ Search and select: `sv-gate-fast`
78
+ - ✅ Require branches to be up to date before merging
79
+ 3. Document the manual step here. Branch protection cannot be enforced via committed YAML alone — it is a repo-admin setting.
80
+
81
+ ## Forks / non-GitHub repos
82
+
83
+ `tests/sv-gate-fast.sh` and `tests/sv-gate-full.sh` are pure zsh + Node — no GitHub-specific dependencies. Forks should:
84
+
85
+ 1. Run `npm run sv-gate:fast` in their CI (Travis, GitLab CI, etc.) using the same OS-level prereqs (macOS or Linux + zsh + tmux + node + claude CLI).
86
+ 2. Optionally run `npm run sv-gate:full` in a scheduled job (nightly) since it requires live API key.
87
+
88
+ ## Gate failure interpretation
89
+
90
+ | Failure mode | Meaning | Action |
91
+ |--------------|---------|--------|
92
+ | Code-pattern grep failed | Tracked fix's expected code is missing | Restore the fix or update `tests/sv-gate-fast.sh` if the pattern legitimately changed |
93
+ | Node unit test failed | Behavioral regression | Fix the code; do NOT relax the test |
94
+ | zsh unit test failed | Behavioral regression in shell helpers | Fix the helper |
95
+ | REAL tmux E2E failed | Real tmux capture/send-keys broke | Investigate tmux version or pane state |
96
+ | REAL campaign E2E failed (no sentinel) | **FILE-GUARANTEE VIOLATED** — Worker/Verifier exited without artifact AND backstop did NOT catch | Critical bug; investigate `_ensureTerminalSentinel` and `_handlePollFailure` paths |
97
+
98
+ ## Memo: SV gate is the contract
99
+
100
+ The SV gate exists because AI assistants (including the Leader itself) miss steps. Mechanical .sh verification is the only enforceable contract — code review, "I tested it locally", and unit-test-only verification are not sufficient. Plan v5.7 explicitly forbids commits that have not passed `tests/sv-gate-full.sh`.
@@ -0,0 +1,102 @@
1
+ # rlp-desk E2E Test Scenarios (v5.7 §4.25)
2
+
3
+ > Two-tier coverage: **Tier A** (deterministic injection, ~ms) runs in `sv-gate-fast`; **Tier B** (real-subprocess + real-tmux + real-claude, seconds–minutes) runs in `sv-gate-full`. Every fix path is covered by at least one tier.
4
+
5
+ ## Tier A — Deterministic injection (sv-gate-fast)
6
+
7
+ Uses `pollForSignal` injection seam (no subprocess spawn) — deterministic, fast, CI-stable.
8
+
9
+ | Scenario | Test file | Asserts |
10
+ |----------|-----------|---------|
11
+ | writeSentinelExclusive O_EXCL race | `tests/node/test-sentinel-exclusive.mjs` | First-writer-wins, parent dir create, EEXIST returns no-op, parallel race |
12
+ | Backstop: missing scaffold | `tests/node/test-leader-exit-invariant.mjs` | `_ensureTerminalSentinel` writes `blocked.md` even on `ensureScaffold` throw |
13
+ | Backstop: pollForSignal throws | `tests/node/test-leader-exit-invariant.mjs` | `_handlePollFailure` writes BLOCKED + run() returns blocked status |
14
+ | Backstop: idempotent first-writer-wins | `tests/node/test-leader-exit-invariant.mjs` | Pre-existing BLOCKED is NOT overwritten by backstop |
15
+ | Lying worker (signal missing) | `tests/node/test-lying-worker.mjs` | BLOCKED `infra_failure/worker_exited_without_artifacts` |
16
+ | Lying verifier (per-US verdict missing) | `tests/node/test-lying-worker.mjs` + `tests/node/sv-e2e/test-lying-verifier.mjs` | BLOCKED `verifier_exited_without_artifacts` |
17
+ | Lying final verifier (US-ALL) | `tests/node/sv-e2e/test-lying-verifier.mjs` | BLOCKED `final_verifier_exited_without_artifacts` |
18
+ | Prompt-blocked (default-No worker) | `tests/node/sv-e2e/test-prompt-blocked.mjs` | BLOCKED `prompt_blocked` |
19
+ | Prompt-blocked (default-No verifier) | `tests/node/sv-e2e/test-prompt-blocked.mjs` | BLOCKED `prompt_blocked` (verifier role) |
20
+ | Schema: empty object | `tests/node/test-artifact-schema.mjs` | No crash |
21
+ | Schema: wrong slug | `tests/node/test-artifact-schema.mjs` | BLOCKED `contract_violation/malformed_artifact` |
22
+ | Schema: us_id outside set | `tests/node/test-artifact-schema.mjs` | BLOCKED `malformed_artifact` |
23
+ | Schema: iteration regress | `tests/node/test-artifact-schema.mjs` | BLOCKED `malformed_artifact` |
24
+ | Schema: iteration not integer | `tests/node/test-artifact-schema.mjs` | BLOCKED `malformed_artifact` |
25
+ | Schema: signal_type mismatch | `tests/node/test-artifact-schema.mjs` | BLOCKED `malformed_artifact` |
26
+ | Schema: valid signal (back-compat) | `tests/node/test-artifact-schema.mjs` | No false positive |
27
+ | Auto-dismiss prompt patterns (24+) | `tests/node/test-prompt-dismisser.mjs` | Each `(y/n)`/`[Y/n]`/`[y/N]` variant + scrollback + unknown-fast-fail + claude v2.x trust |
28
+ | Shell quote (Bug 1) | `tests/node/test-shell-quote.mjs` | POSIX single-quote escape for `[1m]` etc. |
29
+ | Opus 1M context | `tests/node/test-opus-1m-context.mjs` | `ANTHROPIC_BETA` prefix, isOpusModel detection |
30
+
31
+ **Tier A total**: 50+ tests across 11 files. Runtime: ~0.7s. Always runs in CI.
32
+
33
+ ## Tier B — Real-subprocess (sv-gate-full)
34
+
35
+ Uses real tmux session + real `tmux send-keys` / `capture-pane` / real claude haiku CLI. Slow (~5min) but exercises actual production paths.
36
+
37
+ | Scenario | Test | Asserts |
38
+ |----------|------|---------|
39
+ | Real tmux: `[Y/n]` auto-dismiss | `tests/sv-gate-real-e2e.sh` | Real `tmux send-keys Enter` after `auto_dismiss_prompts` |
40
+ | Real tmux: `[y/N]` BLOCK | `tests/sv-gate-real-e2e.sh` | `infra_failure` sentinel written, NO Enter sent |
41
+ | Real tmux: 10s no-progress timeout | `tests/sv-gate-real-e2e.sh` | BLOCKED on freeze regardless of prompt |
42
+ | Real tmux: unknown text + no bracket | `tests/sv-gate-real-e2e.sh` | No false BLOCK, no false Enter |
43
+ | Real tmux: unknown phrasing + `[y/N]` | `tests/sv-gate-real-e2e.sh` | Fast-fail BLOCK (10min wait avoided) |
44
+ | Real tmux: unknown phrasing + `(y/n)` | `tests/sv-gate-real-e2e.sh` | Fast-fail BLOCK |
45
+ | Real tmux: codex `[Y/n]` | `tests/sv-gate-real-e2e.sh` | Auto-dismiss (codex CLI variant) |
46
+ | Real tmux: codex `[y/N]` | `tests/sv-gate-real-e2e.sh` | BLOCK |
47
+ | Real tmux: scrollback contamination | `tests/sv-gate-real-e2e.sh` | Old `[Y/n]` + active `[y/N]` → BLOCK (scan-all) |
48
+ | Real haiku campaign (happy path) | `tests/sv-gate-full.sh` (inline) | `complete.md` written; trust prompt auto-dismissed; tests pass; commit recorded |
49
+
50
+ **Tier B total**: 10+ scenarios. Runtime: ~5 min (1 min for tmux scenarios + ~4 min for haiku campaign). Run before merge / release.
51
+
52
+ ## Coverage matrix (per fix)
53
+
54
+ | Fix | Tier A | Tier B | Bug ID |
55
+ |-----|--------|--------|--------|
56
+ | zsh `[1m]` glob | shell-quote | (haiku campaign launches Opus models when promoted) | Bug 1 |
57
+ | tmux silent SV/flywheel | us012 | (haiku campaign exercises tmux mode) | Bug 2/3 |
58
+ | auto_dismiss prompts | prompt-dismisser | real-e2e #1-9 | Bug 4 |
59
+ | A4 fallback prompt guard | a4_fallback | (haiku campaign) | Bug 5 |
60
+ | scrollback contamination | prompt-dismisser | real-e2e #9 | §4.17.b |
61
+ | unknown-prompt fast-fail | prompt-dismisser | real-e2e #5-6 | §4.18 |
62
+ | Node iterTimeout fwd | (verified by haiku campaign actually completing in ≤300s) | full | §4.19 |
63
+ | claude v2.x trust prompt | prompt-dismisser | full (haiku triggers it) | §4.20 |
64
+ | capture window -50 + whitespace norm | prompt-dismisser | full (haiku narrow-pane wrap) | §4.21 |
65
+ | WorkerExitedError | lying-worker | (full campaign covers happy path; injection covers exit) | §4.22 |
66
+ | tail-15 normalized matching | prompt-dismisser | real-e2e | §4.23 |
67
+ | writeSentinelExclusive O_EXCL | sentinel-exclusive | (full campaign uses it for complete.md) | §4.24 |
68
+ | run() try/finally backstop | leader-exit-invariant | (full campaign verifies success path) | §4.24 §1g |
69
+ | _handlePollFailure | lying-worker, lying-verifier, prompt-blocked | (full campaign success path) | §4.25 |
70
+ | validateArtifact schema | artifact-schema | full (haiku artifacts schema-compliant) | §4.25 P1 |
71
+
72
+ Every fix has at least one Tier A test. Tier B exercises the production-realistic paths (real tmux, real subprocess, real claude haiku).
73
+
74
+ ## Running the gates
75
+
76
+ ```sh
77
+ # Fast gate (~0.7s, every commit)
78
+ zsh tests/sv-gate-fast.sh
79
+ # or
80
+ npm run sv-gate:fast
81
+
82
+ # Full gate (~5 min, before merge/release)
83
+ zsh tests/sv-gate-full.sh
84
+ # or
85
+ npm run sv-gate:full
86
+ ```
87
+
88
+ `sv-gate-full` requires:
89
+ - Inside a tmux session (`echo $TMUX` non-empty)
90
+ - `claude` CLI in PATH with valid auth
91
+ - `node >= 16` in PATH
92
+ - `~/.claude/ralph-desk/` synced from latest `src/` (run `bash install.sh`)
93
+
94
+ ## Adding a new scenario
95
+
96
+ 1. **Determine tier**:
97
+ - Deterministic, no subprocess → Tier A
98
+ - Requires real tmux/claude/network → Tier B
99
+ 2. **Tier A**: add `tests/node/sv-e2e/test-<name>.mjs` (or extend existing file). Use `pollForSignal` injection seam. Update `NODE_TESTS` array in `tests/sv-gate-fast.sh`.
100
+ 3. **Tier B**: add scenario to `tests/sv-gate-real-e2e.sh` with `reset_pane_state` between scenarios. The script auto-runs in `sv-gate-full.sh`.
101
+ 4. **Document**: add row to the Coverage matrix in this file.
102
+ 5. **Verify**: run `npm run sv-gate:fast` (Tier A) or `npm run sv-gate:full` (both tiers); both must exit 0.