@lifeaitools/rdc-skills 0.35.23 → 0.35.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.github/workflows/self-test.yml +34 -34
- package/MANIFEST.md +224 -224
- package/RELEASE.md +53 -11
- package/deploy/install-systemd.sh +29 -6
- package/deploy/systemd/rdc-skills-mcp-update.service +15 -0
- package/deploy/systemd/rdc-skills-mcp-update.timer +9 -0
- package/deploy/update-from-tag.sh +382 -0
- package/guides/agents/backend.md +102 -102
- package/guides/agents/content.md +94 -94
- package/guides/agents/cs2.md +56 -56
- package/guides/agents/data.md +86 -86
- package/guides/agents/design.md +77 -77
- package/guides/agents/frontend.md +91 -91
- package/guides/agents/infrastructure.md +81 -81
- package/guides/agents/setup.md +272 -272
- package/guides/agents/verify.md +119 -119
- package/guides/agents/viz.md +106 -106
- package/guides/orchestration-epic.md +17 -17
- package/guides/output-contract.md +8 -0
- package/guides/work-contract.md +194 -0
- package/package.json +3 -2
- package/scripts/lib/guide-content-rules.mjs +49 -0
- package/scripts/self-test.mjs +1439 -1459
- package/scripts/test-guide-validator.mjs +25 -24
- package/skills/behavior-audit/agents/openai.yaml +4 -4
- package/skills/build/SKILL.md +81 -29
- package/skills/fixit/SKILL.md +16 -0
- package/skills/open/SKILL.md +35 -5
- package/skills/overnight/SKILL.md +3 -1
- package/skills/plan/SKILL.md +21 -23
- package/skills/tests/onramp.test.json +101 -101
- package/skills/tests/rdc-env.test.json +12 -12
- package/skills/tests/rdc-new-model.test.json +12 -12
- package/skills/tests/rdc-refactor.test.json +29 -29
- package/skills/tests/rdc-regen-media.test.json +29 -29
- package/tests/deploy-updater.test.mjs +608 -0
- package/.rdc/evidence/orchestrator-rework-strikes/a9fad8b4716ee35e5f5d0047.json +0 -1
- package/.rdc/last_seen.json +0 -8
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# Work Contract — truth at the start, Stop is the checklist
|
|
2
|
+
|
|
3
|
+
> The one home for how an `rdc:*` skill declares work, resolves its target, and
|
|
4
|
+
> proves it is finished. `rdc:open`, `rdc:fixit`, `rdc:build`, `rdc:plan`,
|
|
5
|
+
> `rdc:overnight` and `rdc:review` defer to this file rather than restating it.
|
|
6
|
+
> Runtime: `lifeai-env` ≥ 0.8.257 (`$LIFEAI_ENV/bin/rdc-work.mjs`), same command
|
|
7
|
+
> on Claude Code and Codex. When a gate prints an `rdc-work` line, run **that
|
|
8
|
+
> line**: it names the installed copy and carries `--session <id>`, which matters
|
|
9
|
+
> in a shell that holds both a Claude and a Codex session id.
|
|
10
|
+
|
|
11
|
+
## Why
|
|
12
|
+
|
|
13
|
+
Every gate this fleet had judged work at the end, by guessing — a regex over the
|
|
14
|
+
final message, a transcript scan for a todo list. A guess at the end cannot tell
|
|
15
|
+
half-built from finished. Operator, 2026-09-14/16:
|
|
16
|
+
|
|
17
|
+
- "the best truth is to start with a plan that has to be finished"
|
|
18
|
+
- "we should have a start gate is more important than the stop gate"
|
|
19
|
+
- "The agent can decide if the work is worth A To Do List or a work package"
|
|
20
|
+
- "hard undeniable proof of work"
|
|
21
|
+
- "move truth to the start so stop is a checklist"
|
|
22
|
+
|
|
23
|
+
## The contract
|
|
24
|
+
|
|
25
|
+
Before a session's first change — a file write in a git work tree, a `git commit`,
|
|
26
|
+
a `git push` — it declares:
|
|
27
|
+
|
|
28
|
+
| field | what it is |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `goal` | one sentence: what done means |
|
|
31
|
+
| `rows` | each a step **and the command that proves it**: `"<step> :: <command that exits 0 when the step is true>"` |
|
|
32
|
+
| `type` | the kind of work; it picks the tier |
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node "$LIFEAI_ENV/bin/rdc-work.mjs" start --type fixit \
|
|
36
|
+
--goal "checkout page renders prices from the API again" \
|
|
37
|
+
--row "unit tests pass :: pnpm --filter @lifeai/shop test" \
|
|
38
|
+
--row "page shows a real price :: curl -sf https://dev.shop.example/checkout | grep -q 'data-price'" \
|
|
39
|
+
--row "landed on develop :: git fetch -q origin && git merge-base --is-ancestor HEAD origin/develop"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
A row passes only when its command ran and exited 0. **Nothing ticks a row by
|
|
43
|
+
saying so** — there is no free-text evidence path.
|
|
44
|
+
|
|
45
|
+
Without a contract the start gate (`work-contract-required`) refuses the change
|
|
46
|
+
and prints the exact command, including this session's id. Plans, reports and
|
|
47
|
+
other documents under `.rdc/`, engine memory and plan files, and anything outside
|
|
48
|
+
a git work tree need no contract; code does, wherever its checkout sits.
|
|
49
|
+
|
|
50
|
+
### A proof observes, and it can fail
|
|
51
|
+
|
|
52
|
+
A proof runs through `rdc-work`'s own process, outside the hooks that guard a
|
|
53
|
+
tool call, so `rdc-work` applies both checks itself — at `start`/`add` and again at
|
|
54
|
+
`verify`:
|
|
55
|
+
|
|
56
|
+
- **The proof policy.** A proof may not change anything: no commit, push, merge,
|
|
57
|
+
rebase, reset, checkout, stash, tag or branch change; no publish, land, deploy,
|
|
58
|
+
migration, PM2/Docker/Kubernetes lifecycle; no `rm`/`mv`/`cp`/`touch`/`mkdir`,
|
|
59
|
+
`sed -i`, redirection into a file, or write request (`curl -X POST`, `-d`). The
|
|
60
|
+
command is read the way the shell runs it, so wrapping an action does not hide it —
|
|
61
|
+
`sh -c '…'`, `cmd /c …`, `npx …`, `node -e "…writeFileSync…"` are judged by what they
|
|
62
|
+
carry. And it must be able to fail: `true`, `exit 0`, a bare `echo`, `… || true`,
|
|
63
|
+
`test 1` are refused — and so is `x | tail`, because a pipeline exits with its LAST
|
|
64
|
+
command (prove with `x` itself, or `x | grep -q <evidence>`).
|
|
65
|
+
- **The shared guard rules** — the same ones a Bash call meets. A proof they refuse
|
|
66
|
+
is refused (`( cd dir && cmd )`, not `cd dir && cmd`).
|
|
67
|
+
|
|
68
|
+
A refused proof is recorded as exit 126 and **never runs**. Prove an action by
|
|
69
|
+
observing its result: a push with `git merge-base --is-ancestor HEAD origin/<branch>`,
|
|
70
|
+
a deploy with a read-only probe, a file with `test -f`.
|
|
71
|
+
|
|
72
|
+
**A proof is a POSIX shell command, on every engine.** `rdc-work` runs it with
|
|
73
|
+
`-c '<proof>'` in Git Bash on Windows and in `/bin/sh` everywhere else (dash on
|
|
74
|
+
Debian and Ubuntu) — whatever shell the agent itself uses. Write plain `sh`: a
|
|
75
|
+
bash-only form (`[[ ]]`, `$RANDOM`, arrays) passes on Windows and fails on Linux.
|
|
76
|
+
`$var`, `"…"` and backticks are expanded by that shell before any program sees
|
|
77
|
+
them. A PowerShell check goes inside single quotes, where POSIX
|
|
78
|
+
expands nothing: `pwsh -NoProfile -Command '(Get-Service x).Status -eq "Running"'`
|
|
79
|
+
— and since that prints `True` or `False` and exits 0 either way, end it with
|
|
80
|
+
`| grep -qx True`, or put the check in a script that exits non-zero, and prove with
|
|
81
|
+
`pwsh -NoProfile -File check.ps1`.
|
|
82
|
+
|
|
83
|
+
## Tier — the agent picks
|
|
84
|
+
|
|
85
|
+
| `--type` | tier | also |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `maintenance`, `hotfix`, `fixit`, `edit` | `todo` | rows only |
|
|
88
|
+
| `build`, `refactor`, `overnight` | `work-item` | `--work-item <uuid>` required |
|
|
89
|
+
|
|
90
|
+
Whatever the tier, a work item this session has **claimed** holds Stop until its
|
|
91
|
+
database Definition of Done closes — choosing `todo` does not drop a claimed item's DoD.
|
|
92
|
+
|
|
93
|
+
A todo contract that grows past ~5 changed files is reported at Stop ("usually
|
|
94
|
+
wants a work item") but never blocked on — the tier is the agent's call. Upgrade
|
|
95
|
+
with `rdc-work upgrade --work-item <uuid>`.
|
|
96
|
+
|
|
97
|
+
## Rows — proportional, not a quota
|
|
98
|
+
|
|
99
|
+
One row per **deliverable**, each with one proof. Decompose until every declared
|
|
100
|
+
surface (screen / api / db / tool) and every handoff has a row that can pass or fail
|
|
101
|
+
on its own. There is **no minimum row count**: a numeric floor produced 91 checks
|
|
102
|
+
before a runnable increment (Codex, building CDE Layer 0). Coverage is the rule;
|
|
103
|
+
count is not.
|
|
104
|
+
|
|
105
|
+
Coarse rows are still rejected, because they cannot fail: "works", "verified",
|
|
106
|
+
"integration complete", "tests pass" with no command.
|
|
107
|
+
|
|
108
|
+
## Proving, and staleness
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
node "$LIFEAI_ENV/bin/rdc-work.mjs" verify t2 --session <id> # one row
|
|
112
|
+
node "$LIFEAI_ENV/bin/rdc-work.mjs" verify --all --session <id> # every row, against the code as it stands now
|
|
113
|
+
node "$LIFEAI_ENV/bin/rdc-work.mjs" drop t3 --reason "no dev target exists for this package" --session <id>
|
|
114
|
+
node "$LIFEAI_ENV/bin/rdc-work.mjs" status --session <id> # the checklist Stop will judge
|
|
115
|
+
node "$LIFEAI_ENV/bin/rdc-work.mjs" check --session <id> # exit 0 when Stop would pass
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`--session` is optional when the shell carries exactly one engine's session id;
|
|
119
|
+
every verb prints the id it resolved and where it came from. `--no-db` skips the
|
|
120
|
+
work-item DoD lookup for an offline check — Stop never skips it.
|
|
121
|
+
|
|
122
|
+
A proof goes **stale** when the session edits after it, or when the content it ran
|
|
123
|
+
against changes by any route — a shell edit, a formatter, a rebase, a pull, a new
|
|
124
|
+
file.
|
|
125
|
+
Committing exactly the proved content does not make it stale. Finish every piece of
|
|
126
|
+
work with `verify --all`. A dropped row is resolved, not passed, and stays visible
|
|
127
|
+
with its reason. Every row prints its proof command beside it, so a weak proof is as
|
|
128
|
+
visible as its claim.
|
|
129
|
+
|
|
130
|
+
## Stop
|
|
131
|
+
|
|
132
|
+
For a session **holding a contract**, Stop is `rdc-work check`: every row proved
|
|
133
|
+
against the current content or dropped with a reason; the target's changes committed —
|
|
134
|
+
including new files this session wrote; the changes it wrote in **any other
|
|
135
|
+
repository** committed too (a second repo, a subagent's worktree); and the database DoD
|
|
136
|
+
closed for every work item it claimed or declared. Dropping every row after making
|
|
137
|
+
changes is not a pass — a drop explains, it does not prove. The block message is the
|
|
138
|
+
checklist, with runnable `--session` commands. A database outage is reported, not held
|
|
139
|
+
against the work.
|
|
140
|
+
|
|
141
|
+
A session with **no contract** — one that only read, planned or answered — still
|
|
142
|
+
gets the evidence checks: tracked changes it left uncommitted, and a claimed work
|
|
143
|
+
item's open DoD. How its final message is worded is never judged.
|
|
144
|
+
|
|
145
|
+
Enforcement is bounded: a Stop held identically three times, or six times in a row,
|
|
146
|
+
releases, and the unproved rows stay in the contract and in the compaction snapshot.
|
|
147
|
+
A defect in the gate itself — an unreadable contract, an error — reports and never holds.
|
|
148
|
+
|
|
149
|
+
## Target resolution — never assume regen-root
|
|
150
|
+
|
|
151
|
+
`start` resolves the target from `projects.json` (generated from Supabase
|
|
152
|
+
`repo_registry`) and prints it:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
target: C:/Dev/lifeai-env.wt/x · integration main · ship: node machines/land.mjs
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Skill text written for regen-root names `develop`, `.rdc/guides`, `scripts/land.mjs`
|
|
159
|
+
and the CodeFlow phase orchestrator. **Those are regen-root's facts, not universal
|
|
160
|
+
ones.** Wherever a skill names them:
|
|
161
|
+
|
|
162
|
+
| skill says | use instead |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `develop` / `origin/develop` | the contract's **integration** branch (`rdc-work status`). regen-root and rdc-harness: `develop`. lifeai-env, clauth, rdc-cde: `main`. rdc-skills: `master`. |
|
|
165
|
+
| `{PROJECT_ROOT}/.rdc/guides/<x>.md` | the contract's `guides_dir` if the target has one; otherwise the guides shipped with rdc-skills. **Never** a cwd-relative `.rdc/guides` from a different repository — that imports one repo's rules into another. |
|
|
166
|
+
| `node scripts/land.mjs` | the contract's **ship** route |
|
|
167
|
+
| `runOrchestrator()` with the phase manifest | only when the target contains `corpus/_shared/build/phase-manifest.json` (today: regen-root). Elsewhere the orchestrator does not apply: resolve waves from work-item dependencies and say so in one line. **An absent orchestrator is not a blocker.** |
|
|
168
|
+
| an undeclared target (`NOT in projects.json`) | work proceeds on rows; register the repository in `repo_registry` before relying on a ship route |
|
|
169
|
+
|
|
170
|
+
## Dispatching writers — engine-neutral
|
|
171
|
+
|
|
172
|
+
The skill's `Agent(…, isolation: "worktree", max_turns: 70)` is Claude Code's
|
|
173
|
+
interface. On an engine without it:
|
|
174
|
+
|
|
175
|
+
1. Create one worktree per writer from the **integration** branch:
|
|
176
|
+
`git fetch origin <integration> && git worktree add <pool>/<name> -b <branch> origin/<integration>`
|
|
177
|
+
(`<pool>` is the contract's `worktree_pool`).
|
|
178
|
+
2. Start the writer with that worktree as its working directory.
|
|
179
|
+
3. The writer is a subagent of this session only if the engine says so; a separately
|
|
180
|
+
launched session needs its own contract.
|
|
181
|
+
|
|
182
|
+
Claude subagents share the parent's session id, so they inherit the parent's
|
|
183
|
+
contract; a SubagentStop is never held to the parent's whole checklist.
|
|
184
|
+
|
|
185
|
+
## Rollout switch
|
|
186
|
+
|
|
187
|
+
`~/.rdc/work-contract-mode`: `enforce` (default) · `shadow` (log would-blocks only)
|
|
188
|
+
· `off` (previous behaviour). A file, not an environment variable, so an agent
|
|
189
|
+
cannot flip it for itself — and `work-contract-tamper` refuses any agent tool call
|
|
190
|
+
that writes the mode file, a contract, or Stop's breaker state. The operator
|
|
191
|
+
switches the mode from their own terminal.
|
|
192
|
+
|
|
193
|
+
A worker launched by the Codex Development Environment (CDE) is admitted by CDE's
|
|
194
|
+
own manager and validator; the start gate stands down for it.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifeaitools/rdc-skills",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.25",
|
|
4
4
|
"description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -55,7 +55,8 @@
|
|
|
55
55
|
"test:channel-formatter:remote": "node tests/channel-formatter.contract.test.mjs --remote",
|
|
56
56
|
"test:brochure": "node tests/rdc-brochure.test.mjs",
|
|
57
57
|
"mcp": "node bin/rdc-skills-mcp.mjs",
|
|
58
|
-
"prepack": "node scripts/prepack.mjs"
|
|
58
|
+
"prepack": "node scripts/prepack.mjs",
|
|
59
|
+
"test:deploy": "node tests/deploy-updater.test.mjs"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
|
61
62
|
"@lifeaitools/clauth-surface-sdk": "^0.1.0",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// guide-content-rules.mjs — the one home for the guide-content validator's rules.
|
|
2
|
+
//
|
|
3
|
+
// Imported by scripts/self-test.mjs (the validator) and scripts/test-guide-validator.mjs
|
|
4
|
+
// (its test). Both used to carry their own copy of these constants, because
|
|
5
|
+
// self-test.mjs runs on import and exports nothing. The copies drifted TOGETHER,
|
|
6
|
+
// so the test kept passing while the validator was wrong: the corrections-table
|
|
7
|
+
// exemption named `@regen/brand-studio`, the package scope was renamed to
|
|
8
|
+
// `@lifeai`, and `.claude/rules/naming-corrections.md` — the table whose whole
|
|
9
|
+
// purpose is to say that name is WRONG — failed every strict run as a "positive
|
|
10
|
+
// instruction" to use it (found 2026-09-16, failing on unmodified master too).
|
|
11
|
+
|
|
12
|
+
/** Terms that must NOT appear in guide/rule files as positive instructions. */
|
|
13
|
+
export const GUIDE_BANNED_TERMS = Object.freeze([
|
|
14
|
+
"@masonator/coolify-mcp",
|
|
15
|
+
"@masonator",
|
|
16
|
+
"coolify-mcp",
|
|
17
|
+
"@regen/brand-studio",
|
|
18
|
+
"brand-studio",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A line matching one of these is an explicit "don't use" statement, not an
|
|
23
|
+
* instruction, and a banned term on it is not flagged.
|
|
24
|
+
*/
|
|
25
|
+
export const GUIDE_NEGATION_PATTERNS = Object.freeze([
|
|
26
|
+
/\bdo not\b/i,
|
|
27
|
+
/\bnever\b/i,
|
|
28
|
+
/\bno such\b/i,
|
|
29
|
+
/\bdoes not exist\b/i,
|
|
30
|
+
/\bbanned\b/i,
|
|
31
|
+
/\bnot reference\b/i,
|
|
32
|
+
/\bnot use\b/i,
|
|
33
|
+
/\bavoid\b/i,
|
|
34
|
+
/\bremoved\b/i,
|
|
35
|
+
/\bdeprecated\b/i,
|
|
36
|
+
// The header row of a WRONG → CORRECT table.
|
|
37
|
+
/^\|[^|]*WRONG[^|]*\|/i,
|
|
38
|
+
// A data row of a corrections table: the banned term sits in the FIRST cell and
|
|
39
|
+
// the next cell is the bold correction. STRUCTURAL on purpose — any scope or
|
|
40
|
+
// prefix before the term (`@regen/`, `@lifeai/`, the next rename) still matches.
|
|
41
|
+
// The previous form listed exact spellings, which is how one scope rename turned
|
|
42
|
+
// a correct row into a strict-mode failure.
|
|
43
|
+
/^\|\s*[^|]*?(?:brand-studio|Brand Studio|@masonator|coolify-mcp)[^|]*\|\s*\*\*/,
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
/** True when a banned term on this line is a warning or a correction, not an instruction. */
|
|
47
|
+
export function isNegatedBannedLine(line) {
|
|
48
|
+
return GUIDE_NEGATION_PATTERNS.some((re) => re.test(line));
|
|
49
|
+
}
|