@zalom/plastic 2.0.0-alpha.11 → 2.0.0-alpha.12
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/agents/plastic-enforcer.md +3 -1
- package/agents/plastic-executor.md +9 -3
- package/hooks/statusline +4 -27
- package/package.json +1 -1
- package/scripts/doctor.rb +46 -3
- package/scripts/verify-intent +2 -1
- package/skills/auto/SKILL.md +2 -2
- package/skills/intent-executing/SKILL.md +9 -5
- package/skills/intent-executing/implementer-prompt.md +6 -1
|
@@ -31,7 +31,9 @@ deliberately; the auto pipeline never dispatches them.
|
|
|
31
31
|
`plastic-intent-executing`'s `plan-reviewer-prompt.md`; fold every finding into the spec, the
|
|
32
32
|
matrix, and the tests.
|
|
33
33
|
4. **Dispatch one executor, tests first** - the executor commits the matrix's tests red, then
|
|
34
|
-
builds, then drives the full suite green; you verify
|
|
34
|
+
builds, then drives the full suite green; you verify tick-versus-diff at the
|
|
35
|
+
post-execution review and again before the merge. A mismatch is a review finding, not a
|
|
36
|
+
cleanup you perform silently.
|
|
35
37
|
5. **Review by risk** - dispatch the post-execution reviewer only when the auto skill's risk
|
|
36
38
|
rule fires; otherwise the green suite is the review.
|
|
37
39
|
6. **Close** - `outcome.md`, then `plastic-intent-ending`, which releases the worktree, clears
|
|
@@ -20,7 +20,11 @@ valid lifecycle artifacts. Honor it as your live state; do not re-derive or cont
|
|
|
20
20
|
any other change.
|
|
21
21
|
2. **Implement the actions** - make the code changes for each action in order, inside the
|
|
22
22
|
worktree the preamble names.
|
|
23
|
-
3. **
|
|
23
|
+
3. **Tick with the commit** - commit after each logical unit of work, and in the same step
|
|
24
|
+
tick the checklist item that unit lands: mark its box `[x]` and move the line to
|
|
25
|
+
`## Completed`, then append the savepoint `Commit` line
|
|
26
|
+
(`scripts/savepoint-note <intent_dir> --kind Commit --text "<sha> <what it proves>"`). A
|
|
27
|
+
commit without its tick is incomplete.
|
|
24
28
|
4. **Record insights** - capture durable discoveries and report them in the `insights:` field;
|
|
25
29
|
persist each to `## Insights` via the `insight-append` helper
|
|
26
30
|
(`scripts/insight-append <intent_dir> <text> --stage Exec --author "plastic-executor (autonomous)"`),
|
|
@@ -33,7 +37,8 @@ valid lifecycle artifacts. Honor it as your live state; do not re-derive or cont
|
|
|
33
37
|
real `ACTION_N.md` with its failure-mode matrix, pasted in by the lead. Execute the action
|
|
34
38
|
files in order.
|
|
35
39
|
2. Write the matrix's tests; commit red.
|
|
36
|
-
3. Work one action at a time,
|
|
40
|
+
3. Work one action at a time, ticking its checklist item in the same commit that lands it
|
|
41
|
+
(box marked, line moved); prefer safe, non-destructive routes.
|
|
37
42
|
4. Run the full suite, iterate to zero failures and zero errors; commit green.
|
|
38
43
|
5. Produce (output handoff): the code changes, a checked-off `checklist.md`, and `## Insights`.
|
|
39
44
|
6. Report (see `## Completion Report`); the lead applies the risk rule and may dispatch a
|
|
@@ -46,7 +51,8 @@ preamble's `REPORT_CONTRACT` and `skills/auto/references/agent-report-contract.m
|
|
|
46
51
|
finish silently. Carry the common envelope (role, intent id, stage, status, artifacts written,
|
|
47
52
|
verification, checklist deltas, deviations, blockers, insights) plus the executor payload:
|
|
48
53
|
|
|
49
|
-
- Actions implemented this turn, mapped to checklist items checked off (checked / total)
|
|
54
|
+
- Actions implemented this turn, mapped to checklist items checked off (checked / total);
|
|
55
|
+
checked / total must equal the items whose commits exist
|
|
50
56
|
- A summary of the code changed (files and the shape of the change)
|
|
51
57
|
- Test result: the red commit's failing count, then the full-suite command and its pass / fail
|
|
52
58
|
counts
|
package/hooks/statusline
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# plastic-hook-version: 4.0.0
|
|
3
3
|
# StatusLine hook - Plastic owns the full statusline (no chaining).
|
|
4
4
|
# Renders: {model} - ctx {pct}% ({used}/{size}) - 5h {p}% - 7d {p}% - ${cost}
|
|
5
|
-
# -
|
|
6
|
-
# Every segment but
|
|
5
|
+
# - Plastic {version}[ -> {next}] - {path}
|
|
6
|
+
# Every segment but the Plastic version comes from the stdin payload.
|
|
7
7
|
# Pure bash (macOS 3.2 compatible). No ruby, no jq. Reads stdin once; small file reads
|
|
8
8
|
# only. The stdin JSON is walked in a single awk pass (below); nothing else in this
|
|
9
9
|
# script forks a second process per field, which is what keeps a render cheap.
|
|
@@ -17,7 +17,6 @@ C_OK='' # default - meter below 70%
|
|
|
17
17
|
C_WARN=$'\033[33m' # yellow - meter at 70% and above
|
|
18
18
|
C_CRIT=$'\033[38;2;231;76;60m' # red - meter at 90% and above
|
|
19
19
|
C_COST=$'\033[37m' # white - session cost
|
|
20
|
-
C_CLAUDISH=$'\033[38;2;249;140;30m' # orange - claudish rewrites
|
|
21
20
|
C_VER=$'\033[37m' # white - "Plastic {version}" and update arrow
|
|
22
21
|
C_NEXT=$'\033[33m' # yellow - next version
|
|
23
22
|
C_PATH=$'\033[38;2;128;134;144m' # gray - path (matches dim UI text)
|
|
@@ -309,40 +308,18 @@ if [ -n "$COST_RAW" ]; then
|
|
|
309
308
|
[ -n "$COST_FMT" ] && [ "$COST_FMT" != "0.00" ] && COST_SEG="${C_COST}\$${COST_FMT}${RST}"
|
|
310
309
|
fi
|
|
311
310
|
|
|
312
|
-
# --- claudish rewrites for THIS session (fork ledger, optional) ---
|
|
313
|
-
# Tab separated, one call per line; column 11 is the session id. Rows written
|
|
314
|
-
# before that column existed have 9 or 10 fields and never match, so an old
|
|
315
|
-
# ledger renders no segment instead of a wrong one.
|
|
316
|
-
CL_SEG=""
|
|
317
|
-
CL_LOG="${CLAUDISH_LOCAL_DIR:-$HOME/.claude/claudish-local}/usage.log"
|
|
318
|
-
if [ -n "$SID" ] && [ -f "$CL_LOG" ]; then
|
|
319
|
-
CL=$(awk -F'\t' -v sid="$SID" '
|
|
320
|
-
NF >= 11 && $11 == sid { n++; t += $5 + $6 }
|
|
321
|
-
END {
|
|
322
|
-
if (n > 0) {
|
|
323
|
-
if (t >= 1000) {
|
|
324
|
-
s = sprintf("%.1f", t / 1000); sub(/\.0$/, "", s); printf "%d %sk", n, s
|
|
325
|
-
} else {
|
|
326
|
-
printf "%d %d", n, t
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}' "$CL_LOG" 2>/dev/null)
|
|
330
|
-
[ -n "$CL" ] && CL_SEG="${C_CLAUDISH}claudish ${CL%% *} rw / ${CL#* }${RST}"
|
|
331
|
-
fi
|
|
332
|
-
|
|
333
311
|
# --- Assemble segments in order, joined by " . " ---
|
|
334
312
|
PARTS=""
|
|
335
313
|
add() { [ -z "$1" ] && return; if [ -z "$PARTS" ]; then PARTS="$1"; else PARTS="$PARTS$SEP$1"; fi; }
|
|
336
314
|
|
|
337
|
-
# Order: identity first (model), then this session's spend (context, meters, cost,
|
|
338
|
-
#
|
|
315
|
+
# Order: identity first (model), then this session's spend (context, meters, cost),
|
|
316
|
+
# then the volatile-length values last (version, path) so the line does
|
|
339
317
|
# not visually jump as they change.
|
|
340
318
|
[ -n "$MODEL" ] && add "${C_MODEL}${MODEL}${RST}"
|
|
341
319
|
add "$CTX_SEG"
|
|
342
320
|
add "$M5"
|
|
343
321
|
add "$M7"
|
|
344
322
|
add "$COST_SEG"
|
|
345
|
-
add "$CL_SEG"
|
|
346
323
|
if [ -n "$VERSION" ]; then
|
|
347
324
|
vseg="${C_VER}Plastic ${VERSION}${RST}"
|
|
348
325
|
[ -n "$NEXT" ] && vseg="${vseg}${C_VER} "$'\342\206\222'" ${RST}${C_NEXT}${NEXT}${RST}"
|
package/package.json
CHANGED
package/scripts/doctor.rb
CHANGED
|
@@ -30,6 +30,7 @@ require_relative "lib/power_tools"
|
|
|
30
30
|
require_relative "lib/preflight"
|
|
31
31
|
require_relative "lib/ruby_probe"
|
|
32
32
|
require_relative "lib/doctor_session_ledger"
|
|
33
|
+
require_relative "lib/intent_screen"
|
|
33
34
|
|
|
34
35
|
# Diagnostic engine, instantiable with an injected store/agent map so tests can
|
|
35
36
|
# run it hermetically (no eval, no global-constant rewriting).
|
|
@@ -1161,9 +1162,11 @@ end
|
|
|
1161
1162
|
#
|
|
1162
1163
|
# Doctor's fourth check scope, invoked by `--intent <id>`. Never a store-wide sweep:
|
|
1163
1164
|
# resolves exactly one intent directory (mirrors scripts/end-intent's resolve_intent_dir /
|
|
1164
|
-
# scripts/project-links's --intent disambiguation) and returns
|
|
1165
|
-
# FAIL-severity,
|
|
1166
|
-
# binding advisory-only ruling
|
|
1165
|
+
# scripts/project-links's --intent disambiguation) and returns six checks, four
|
|
1166
|
+
# FAIL-severity, two WARN-severity: intent_savepoint_truthful stays WARN per intent 134's
|
|
1167
|
+
# binding advisory-only ruling (see spec.md D2/D8 - do NOT escalate it to FAIL), and
|
|
1168
|
+
# intent_ticks_lag is WARN-only per intent 329's ruling that a lagging tick warns rather
|
|
1169
|
+
# than blocks.
|
|
1167
1170
|
def check_intent_end(id, store: nil, disposition: nil)
|
|
1168
1171
|
intent_dir, scope = resolve_single_intent_dir(id, store: store)
|
|
1169
1172
|
unless intent_dir
|
|
@@ -1185,6 +1188,7 @@ end
|
|
|
1185
1188
|
intent_structure_check(intent_dir),
|
|
1186
1189
|
intent_lifecycle_artifacts_check(intent_dir, disposition),
|
|
1187
1190
|
intent_checklist_complete_check(intent_dir),
|
|
1191
|
+
intent_ticks_lag_check(intent_dir),
|
|
1188
1192
|
intent_links_projection_check_for(id, scope),
|
|
1189
1193
|
intent_savepoint_truthful_check(intent_dir, index_path: index_path),
|
|
1190
1194
|
]
|
|
@@ -1263,6 +1267,45 @@ end
|
|
|
1263
1267
|
end
|
|
1264
1268
|
end
|
|
1265
1269
|
|
|
1270
|
+
# Intent 329: the checklist is the only input to the state screen's Progress bar, so an
|
|
1271
|
+
# intent whose commit ledger has entries and whose checklist has no ticked item is
|
|
1272
|
+
# reporting 0 progress on work that already landed. Advisory only (WARN), like
|
|
1273
|
+
# intent_savepoint_truthful: a lagging tick is a lead's review finding, never a machine
|
|
1274
|
+
# refusal. The commit count comes from this intent's own savepoint.md Commit ledger
|
|
1275
|
+
# (intent 317 D17), never from git: git's detected base is the repo default branch, which
|
|
1276
|
+
# is not the base a 2.0 intent branch forks from.
|
|
1277
|
+
def intent_ticks_lag_check(intent_dir)
|
|
1278
|
+
items = IntentScreen.checklist_items(intent_dir)
|
|
1279
|
+
if items.empty?
|
|
1280
|
+
return check(category: "intent_end", name: "intent_ticks_lag", status: "pass",
|
|
1281
|
+
message: "n/a: checklist.md has no items to tick")
|
|
1282
|
+
end
|
|
1283
|
+
|
|
1284
|
+
ticked = items.count { |i| i[:done] }
|
|
1285
|
+
commits = savepoint_commit_count(intent_dir)
|
|
1286
|
+
|
|
1287
|
+
if commits.positive? && ticked.zero?
|
|
1288
|
+
check(category: "intent_end", name: "intent_ticks_lag", status: "warn",
|
|
1289
|
+
message: "ticks lag the branch: #{commits} commit(s) recorded, " \
|
|
1290
|
+
"0 of #{items.size} checklist items ticked")
|
|
1291
|
+
else
|
|
1292
|
+
check(category: "intent_end", name: "intent_ticks_lag", status: "pass",
|
|
1293
|
+
message: "#{ticked} of #{items.size} ticked, #{commits} commit(s) recorded")
|
|
1294
|
+
end
|
|
1295
|
+
end
|
|
1296
|
+
|
|
1297
|
+
# Count `Commit` lines in the intent's savepoint ledger, through the one regex that parses
|
|
1298
|
+
# a savepoint line (IntentScreen::SAVEPOINT_RE; field 2 is the kind).
|
|
1299
|
+
def savepoint_commit_count(intent_dir)
|
|
1300
|
+
path = File.join(intent_dir, "savepoint.md")
|
|
1301
|
+
return 0 unless File.exist?(path)
|
|
1302
|
+
|
|
1303
|
+
File.readlines(path).count do |line|
|
|
1304
|
+
m = line.strip.match(IntentScreen::SAVEPOINT_RE)
|
|
1305
|
+
m && m[2] == "Commit"
|
|
1306
|
+
end
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1266
1309
|
def intent_links_projection_check_for(id, scope)
|
|
1267
1310
|
ctx = build_links_projection_context
|
|
1268
1311
|
node = ctx[:intents].find { |n| n[:id] == id && n[:scope] == scope }
|
package/scripts/verify-intent
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
# other flags exist.
|
|
16
16
|
#
|
|
17
17
|
# Checks, all run every invocation (the fourth only when --suite is given):
|
|
18
|
-
# 1. doctor - Doctor#run_intent_check(id, store: scope), fail-open on a crash
|
|
18
|
+
# 1. doctor - Doctor#run_intent_check(id, store: scope), fail-open on a crash; the doctor
|
|
19
|
+
# scan includes the intent_ticks_lag warning (intent 329)
|
|
19
20
|
# 2. em-dash - added lines only of `git diff <base>...HEAD`, never the whole tree
|
|
20
21
|
# 3. diffstat - `git diff --stat <base>...HEAD`, never a failure on its own
|
|
21
22
|
# 4. suite - the supplied --suite command, run with RUBYOPT cleared
|
package/skills/auto/SKILL.md
CHANGED
|
@@ -217,7 +217,7 @@ Then Exec.
|
|
|
217
217
|
then builds, then drives the full suite green.
|
|
218
218
|
2. Read its return by code: DONE or DONE_WITH_CONCERNS proceeds; NEEDS_CONTEXT re-dispatches
|
|
219
219
|
with the missing context; BLOCKED stops under the error procedure.
|
|
220
|
-
3. Tick the checklist as items land (the executor does this; verify
|
|
220
|
+
3. Tick the checklist as items land (the executor does this); verify tick-versus-diff against the diff. A mismatch is a review finding, not a lead cleanup.
|
|
221
221
|
|
|
222
222
|
## Review by risk (boot 3, only when a rule fires)
|
|
223
223
|
|
|
@@ -254,7 +254,7 @@ every choice is non-destructive and the team has full autonomy.
|
|
|
254
254
|
|
|
255
255
|
Read `../plastic-conventions/references/completion-and-done.md` for what "intent done" means.
|
|
256
256
|
|
|
257
|
-
1.
|
|
257
|
+
1. This is the merge gate: verify every checklist item is checked, verify tick-versus-diff against the diff, and confirm the suite is green once on the branch.
|
|
258
258
|
2. Write `outcome.md` from `~/.plastic/templates/outcome.md` with `disposition: delivered`,
|
|
259
259
|
`## Delivered` as the labeled table whose row labels match the action-file headings (317a).
|
|
260
260
|
3. Release, if configured: match the working directory against `~/.plastic/projects.yml`, read
|
|
@@ -108,11 +108,15 @@ Capture observations in `## Insights`. When ALL checklist items are checked:
|
|
|
108
108
|
|
|
109
109
|
## Tick-as-you-land
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
Progress` to `## Completed` in `checklist.md
|
|
113
|
-
row (Date, Items Completed, Notes).
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
A tick is two edits, made together: mark the item's box `[x]`, and move its
|
|
112
|
+
checklist item from `## In Progress` to `## Completed` in `checklist.md`;
|
|
113
|
+
then add one `## Session Log` row (Date, Items Completed, Notes). The box is
|
|
114
|
+
the half the state screen's Progress bar reads: `IntentScreen::ITEM_RE` and
|
|
115
|
+
`progress_fields` count `[x]`, not which section the line sits in, so a line
|
|
116
|
+
moved to `## Completed` with its box left unmarked still reads as zero
|
|
117
|
+
progress. Do not batch several tasks' worth of checklist updates into one
|
|
118
|
+
later edit; tick the moment the task is verified, before moving to the next
|
|
119
|
+
task.
|
|
116
120
|
|
|
117
121
|
## Verify before every owner review
|
|
118
122
|
|
|
@@ -20,12 +20,17 @@ You are implementing a specific task from a plan. You have been given the full t
|
|
|
20
20
|
2. Implement exactly what the task specifies — nothing more, nothing less.
|
|
21
21
|
3. Write tests first when the task includes test steps (TDD).
|
|
22
22
|
4. Follow the file paths specified in the task exactly.
|
|
23
|
-
5. Commit after each logical unit of work
|
|
23
|
+
5. Commit after each logical unit of work, and in the same step tick the checklist item that
|
|
24
|
+
unit lands: mark its box `[x]` and move the line to `## Completed`, then append the
|
|
25
|
+
savepoint `Commit` line
|
|
26
|
+
(`scripts/savepoint-note <intent_dir> --kind Commit --text "<sha> <what it proves>"`). A
|
|
27
|
+
commit without its tick is incomplete.
|
|
24
28
|
6. When done, self-review against this checklist:
|
|
25
29
|
- [ ] All steps in the task are completed
|
|
26
30
|
- [ ] Tests pass
|
|
27
31
|
- [ ] Code is clean and follows project conventions
|
|
28
32
|
- [ ] No unrelated changes
|
|
33
|
+
- [ ] Every landed unit's checklist item is ticked
|
|
29
34
|
|
|
30
35
|
## Report Format
|
|
31
36
|
|