task-pipeline-skill 1.47.2 → 1.49.1
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/CHANGELOG.md +119 -0
- package/HOW-IT-WORKS.md +13 -2
- package/SKILL-CARD.md +1 -1
- package/bin/task-pipeline.js +34 -0
- package/package.json +1 -1
- package/plugins/task-pipeline/.claude-plugin/plugin.json +1 -1
- package/plugins/task-pipeline/skills/task-pipeline/references/acceptance.md +5 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/build.md +86 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/progress.md +6 -0
- package/plugins/task-pipeline/skills/task-pipeline/references/spec.md +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,124 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.49.1 — the entry states the count its own guard reads
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **v1.49.0 tagged but never released.** Its CHANGELOG entry stated no
|
|
8
|
+
`Guards: N → **M**` count, so two of this repo's negative self-tests had
|
|
9
|
+
nothing to patch and reported `PLANT DID NOT LAND` — the release job failed
|
|
10
|
+
after the tag was already public. Same class as v1.45.0, and the guard worked
|
|
11
|
+
exactly as designed: a probe that cannot plant says so instead of passing.
|
|
12
|
+
|
|
13
|
+
The count is unchanged because v1.49.0 added a feature, not enforcement.
|
|
14
|
+
|
|
15
|
+
Guards: 309 → **309**. Property checks: 9 → 9. The installer change is
|
|
16
|
+
behavioural and carries no new guard; the count is stated because two probes read
|
|
17
|
+
the newest section and a count-shaped sentence with no count is the one case
|
|
18
|
+
where silence and agreement look the same.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- Everything in v1.49.0, which never shipped: the installer now offers the
|
|
23
|
+
family's routing block via `npx sshlg-skills routers --member task-pipeline`,
|
|
24
|
+
scoped so it repairs only this skill's own section. See that entry below.
|
|
25
|
+
|
|
26
|
+
## v1.49.0 — the installer stops leaving the skill unrouted
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- **The installer now offers the family's routing block** (closing B-06 in the
|
|
31
|
+
umbrella). Until now only `super-ux` delegated: install this skill on its own
|
|
32
|
+
and no router was written at all, so an agent had the skill and no rule saying
|
|
33
|
+
when to reach for it. The bundle installer wrote all eight, which is why
|
|
34
|
+
nothing looked broken — the gap only opened for someone installing one member.
|
|
35
|
+
|
|
36
|
+
Delegated to `npx sshlg-skills routers --member task-pipeline` rather than
|
|
37
|
+
reimplemented, for three reasons:
|
|
38
|
+
|
|
39
|
+
- The block describes what the machine actually has. A lone member rendering
|
|
40
|
+
the whole thing would print a table for routers nobody installed.
|
|
41
|
+
- `--member` scopes the write to this skill's own section. Verified by damaging
|
|
42
|
+
two sections of a real block and running this installer: its own was
|
|
43
|
+
repaired, the other left exactly as it was.
|
|
44
|
+
- The launcher is the only writer that copies the operator's global instruction
|
|
45
|
+
file before touching it. That file has no version control behind it.
|
|
46
|
+
|
|
47
|
+
`--no-install` keeps it from silently downloading a package nobody asked for.
|
|
48
|
+
When the launcher is absent the command is printed instead of failing: ending
|
|
49
|
+
an install in an error over an optional follow-up reads as a failed install.
|
|
50
|
+
Both paths were exercised.
|
|
51
|
+
|
|
52
|
+
## v1.48.0 — a screen is the frame implemented, and four mechanisms this project owed itself
|
|
53
|
+
|
|
54
|
+
**A screen is the frame, implemented.** Until now Figma was an address and a link: the
|
|
55
|
+
brief recorded which file, `screens.md` carried frame URLs, the linter checked they were
|
|
56
|
+
not stale. Nothing said the screen is **built from** it. Now the order of authority is
|
|
57
|
+
fixed — `super-ux` says what the screen does, the **frame** says what it is made of, and
|
|
58
|
+
`sheleg-design` says how it looks and moves **where the frame is silent**, after the file
|
|
59
|
+
and never instead of it.
|
|
60
|
+
|
|
61
|
+
Made concrete rather than aspirational: the composition is compared against the node
|
|
62
|
+
tree, not recalled; layout is read from `get_design_context`, because from a screenshot
|
|
63
|
+
it is recovered approximately and approximate is indistinguishable from exact in a
|
|
64
|
+
report; a node with a Code Connect mapping is used, not reimplemented, since a rewrite
|
|
65
|
+
is a silent fork of the design system; and a raw hex where a variable exists is a token
|
|
66
|
+
that has quietly split in two.
|
|
67
|
+
|
|
68
|
+
With the honest boundary that keeps it followable: **a frame is one width.** Behaviour
|
|
69
|
+
at other breakpoints, and states the frame never draws — error, empty, loading — are
|
|
70
|
+
decisions that get **recorded**, not guessed. Without that line the rule is broken on
|
|
71
|
+
day one and then ignored entirely.
|
|
72
|
+
|
|
73
|
+
**No frame for a screen: build it, name it, offer to draw it, mark what gets drawn.**
|
|
74
|
+
Figma stays a recommendation whose absence is named and never blocks. The screen comes
|
|
75
|
+
from the style pack, the spec says so screen by screen, and the run offers to draw the
|
|
76
|
+
missing frames into the file the brief already named — which screens, where, from what,
|
|
77
|
+
so the size is visible before anyone says go. Drawing happens only on an explicit go,
|
|
78
|
+
and whatever is drawn is marked as coming from implementation. **A designer must be able
|
|
79
|
+
to tell a decision from a generation**; an unmarked generated frame is the same false
|
|
80
|
+
confidence as an unproven green.
|
|
81
|
+
|
|
82
|
+
**Another agent may be in this repository right now.** Isolation used to mean *your*
|
|
83
|
+
passes not colliding with each other. It now also means someone else's: a worktree per
|
|
84
|
+
agent, always, because sharing a checkout is what turns two independent changes into one
|
|
85
|
+
corrupted state — a copy taken mid-write, an edit staged into another commit, a branch
|
|
86
|
+
switched under a running test. And a lease before any shared register where the project
|
|
87
|
+
carries `.claude/agent-sync.json`, because a worktree separates files and answers nothing
|
|
88
|
+
about who may edit the board.
|
|
89
|
+
|
|
90
|
+
With the asymmetry that keeps the rule from becoming a licence: **on finding the other
|
|
91
|
+
agent mid-run, leave their work alone.** Their uncommitted edits are not yours to stage,
|
|
92
|
+
revert or stash. Put a ref on your own committed work so a branch reset cannot lose it,
|
|
93
|
+
and continue in a worktree of your own — ending someone else's work to unblock yours is
|
|
94
|
+
what `residue.md` refuses, one layer up.
|
|
95
|
+
|
|
96
|
+
This is measured, not feared. One session produced four version collisions, a `files[]`
|
|
97
|
+
entry dropped silently by a merge and caught only by the validator, and a test run that
|
|
98
|
+
failed because a probe copied the tree while another agent was writing to it. This
|
|
99
|
+
repository now carries the coordination config it was telling every other project to keep.
|
|
100
|
+
|
|
101
|
+
**Four mechanisms this project had decided on and never built.**
|
|
102
|
+
|
|
103
|
+
`DEC-0001` ruled that `SURFACED: 0` is checked against what the run filed — a run that
|
|
104
|
+
opened a board row and reports nothing surfaced contradicts its own artefacts, and the
|
|
105
|
+
`Source` column makes that computable. The decision was recorded and nothing implemented
|
|
106
|
+
it, which is R-006's own subject applied to a decision instead of a finding. It is a
|
|
107
|
+
check now, and it carries its residual in the same breath: it kills the silent zero, not
|
|
108
|
+
the blind spot.
|
|
109
|
+
|
|
110
|
+
`R-006` has been in force for four releases because nothing could read the distinction
|
|
111
|
+
it draws. Stage 10 now records, per finding, **one of two words** — `behaviour` or
|
|
112
|
+
`reporting`. A row saying `reporting` stays open on the board; only `behaviour` closes it.
|
|
113
|
+
|
|
114
|
+
**The release path now runs the suite it advertises.** Two releases shipped over a red
|
|
115
|
+
suite because the negatives ran on the PR and never on the tag. A tag is not evidence.
|
|
116
|
+
|
|
117
|
+
**And a version number already spoken for now fails at the commit rather than at the
|
|
118
|
+
merge.** Four collisions in one session, each costing a renumber of a whole branch.
|
|
119
|
+
|
|
120
|
+
Guards: 294 → **309**.
|
|
121
|
+
|
|
3
122
|
## v1.47.2 — the body stopped retelling its own references
|
|
4
123
|
|
|
5
124
|
`Prerequisites` was 2585 of the body's 6585 tokens, and most of it was a second
|
package/HOW-IT-WORKS.md
CHANGED
|
@@ -5,7 +5,7 @@ explains the machine — what routes a request into it, what each stage refuses
|
|
|
5
5
|
let past, and what makes any claim it prints believable. The README sells it and
|
|
6
6
|
tells you how to install it; this file tells you how it thinks.
|
|
7
7
|
|
|
8
|
-
> **Version 1.
|
|
8
|
+
> **Version 1.48.0.** The "What changed" section at the bottom carries the last
|
|
9
9
|
> few releases. Everything above it describes the pipeline as it is *now*, not as
|
|
10
10
|
> it was designed.
|
|
11
11
|
|
|
@@ -238,7 +238,7 @@ This is the part most pipelines skip, and it is the reason this one is trustwort
|
|
|
238
238
|
rather than merely tidy.
|
|
239
239
|
|
|
240
240
|
**Every guard is proven against a planted defect.** `npm run test:all` breaks the
|
|
241
|
-
thing each of the **
|
|
241
|
+
thing each of the **309** checks is about, and requires that check to reject it. A
|
|
242
242
|
guard that has never been watched failing is not a guard; it is a comment.
|
|
243
243
|
|
|
244
244
|
**The neighbour probe.** A check has a *subject* — the rule it is about — and
|
|
@@ -291,6 +291,17 @@ a run diverges → retro entry → retro.publish → upstream issue
|
|
|
291
291
|
|
|
292
292
|
## What changed, by version
|
|
293
293
|
|
|
294
|
+
### v1.48.0 — a screen is the frame implemented, and four mechanisms this project owed itself
|
|
295
|
+
Figma stops being an address and becomes the source: composition compared against the
|
|
296
|
+
node tree, layout read rather than eyeballed, Code Connect used rather than rewritten,
|
|
297
|
+
tokens naming their variables — with the honest boundary that a frame is one width, and
|
|
298
|
+
a no-frame branch that builds, names, offers to draw, and marks what it drew.
|
|
299
|
+
Plus a worktree per agent and a lease before any shared
|
|
300
|
+
register — measured at four version collisions in one session — the
|
|
301
|
+
SURFACED contradiction check DEC-0001 decided and nobody built, R-006 made readable, a
|
|
302
|
+
release path that runs its own suite, and a version guard that fails at the commit
|
|
303
|
+
rather than at the merge. Guards: 294 → 309.
|
|
304
|
+
|
|
294
305
|
### v1.47.1 — the fixes a reader found, which three releases shipped without
|
|
295
306
|
Three releases went out from another session while this branch was reviewed, and
|
|
296
307
|
each carried the same defects forward: the doc map forbidding the decisions register
|
package/SKILL-CARD.md
CHANGED
|
@@ -12,7 +12,7 @@ harmless.
|
|
|
12
12
|
|---|---|
|
|
13
13
|
| **Purpose** | Runs a substantial task through ten gated delivery stages — intake grill, docs study, brainstorm, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs+registers, acceptance — refusing to advance until each gate passes |
|
|
14
14
|
| **Owner** | ssheleg ([github.com/ssheleg/task-pipeline](https://github.com/ssheleg/task-pipeline)) |
|
|
15
|
-
| **Version** | 1.
|
|
15
|
+
| **Version** | 1.49.1 |
|
|
16
16
|
| **Surface** | Claude Code (filesystem skill + plugin) and the vercel `skills` CLI. **Not** uploaded to the Skills API; custom Skills do not sync across surfaces |
|
|
17
17
|
| **Dependencies** | None required. Optional: `context7` (MCP), `figma` (MCP), super-ux, agent-sync, graphify, obsidian-wiki. Every stage's doctrine ships in-repo; the one conditional requirement is super-ux for the stage-3 UX track on a user-facing task |
|
|
18
18
|
| **Evaluation status** | Suite authored, 5 categories. One recorded run, **self-observed by the author**; **zero blind runs on zero of three models** — the split, and the numbers, live in [`evals/RESULTS.md`](evals/RESULTS.md) and are computed by `evals/run.py` |
|
package/bin/task-pipeline.js
CHANGED
|
@@ -54,6 +54,39 @@ function installOne(label, src, dest, isDir, force) {
|
|
|
54
54
|
console.log(`Installed ${label} -> ${dest}`);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Ask the family launcher to write the routing block, for this member only.
|
|
59
|
+
*
|
|
60
|
+
* Delegated rather than reimplemented, for three reasons. The block describes
|
|
61
|
+
* what the machine actually has, so a lone member rendering the whole thing
|
|
62
|
+
* would produce a table for routers nobody installed. `--member` limits this to
|
|
63
|
+
* the `task-pipeline` section and leaves everyone else's alone, which is what
|
|
64
|
+
* lets the bundle and a single installer both write. And the launcher is the
|
|
65
|
+
* only writer that copies the operator's global instruction file before touching
|
|
66
|
+
* it — that file has no version control behind it, and two defects in this
|
|
67
|
+
* family's history destroyed it.
|
|
68
|
+
*
|
|
69
|
+
* `--no-install` keeps this from silently downloading a package the user did not
|
|
70
|
+
* ask for. When the launcher is absent, print the one command instead of
|
|
71
|
+
* failing: an installer that ends in an error because an OPTIONAL follow-up is
|
|
72
|
+
* missing reads as a failed install.
|
|
73
|
+
*/
|
|
74
|
+
function offerRouters() {
|
|
75
|
+
const { spawnSync } = require('child_process');
|
|
76
|
+
const r = spawnSync(
|
|
77
|
+
'npx',
|
|
78
|
+
['--no-install', 'sshlg-skills', 'routers', '--member', 'task-pipeline'],
|
|
79
|
+
{ stdio: 'inherit', shell: process.platform === 'win32' }
|
|
80
|
+
);
|
|
81
|
+
if (r.status !== 0) {
|
|
82
|
+
console.log(
|
|
83
|
+
'\nTo have this skill apply by default in every project, add the\n' +
|
|
84
|
+
"family's routing block to your agent's global instructions:\n\n" +
|
|
85
|
+
' npx --yes sshlg-skills routers --member task-pipeline\n'
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
57
90
|
function main(argv) {
|
|
58
91
|
const args = argv.slice(2);
|
|
59
92
|
if (args.includes('--help') || args.includes('-h')) {
|
|
@@ -115,6 +148,7 @@ Rerun with --force if you deliberately want the plain copy instead.`);
|
|
|
115
148
|
false,
|
|
116
149
|
force
|
|
117
150
|
);
|
|
151
|
+
offerRouters();
|
|
118
152
|
return 0;
|
|
119
153
|
}
|
|
120
154
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "task-pipeline-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.49.1",
|
|
4
4
|
"description": "Full-cycle delivery pipeline for coding agents: a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine ships inside the skill — no companion plugin required. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"task-pipeline": "bin/task-pipeline.js"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "task-pipeline",
|
|
3
3
|
"displayName": "Task Pipeline",
|
|
4
4
|
"description": "Runs a substantial task through a mandatory built-in intake grill, then 10 gated stages (docs, brainstorm+decompose, spec, plan, subagent build, tests, lint/deploy, post-deploy, docs/wiki, acceptance). Every stage's doctrine is built into the skill — no companion plugin required — with typed auto/manual gates, a frozen requirement spine that closes with evidence, a work board and a verification ledger that outlive a run, an exposure line naming what shipped unconfirmed, a progress rail computed from the project's own config, a loop guard whose review ceiling measures rather than stops, and stage-3 tracks for what a product does, how it sounds and how it looks. Two modes need no task: `checkup` (what is unverified) and `setup` (audit existing docs). Retro insights can publish upstream as issues, opt-in and redacted.",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.49.1",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "ssheleg",
|
|
8
8
|
"url": "https://x.com/sshlg93"
|
|
@@ -311,6 +311,11 @@ table substitute for that answer.
|
|
|
311
311
|
its four registers with their ids. A run that cannot say what happened has not
|
|
312
312
|
finished; it has stopped. This file is the one stage 10 opens, and it carried every
|
|
313
313
|
other criterion while omitting this one for a release.
|
|
314
|
+
12a. **Every finding closed in this run records which changed — the behaviour or
|
|
315
|
+
only the reporting.** One of two words per finding, `behaviour` or `reporting`,
|
|
316
|
+
beside its id. Reporting a gap honestly is not fixing it, and the two have
|
|
317
|
+
looked identical in every close-out that did not say which. A finding whose row
|
|
318
|
+
says `reporting` stays open on the board with its id; only `behaviour` closes it.
|
|
314
319
|
13. **The run has given the environment back** ([`residue.md`](residue.md)) — all
|
|
315
320
|
eight classes enumerated **by class, never by one tool**, everything this run
|
|
316
321
|
started ended in dependency order, each teardown verified by **re-enumerating
|
|
@@ -41,9 +41,11 @@ reviewer's.
|
|
|
41
41
|
## Contents
|
|
42
42
|
|
|
43
43
|
- 1. Isolation
|
|
44
|
+
- 1a. Another agent may be in this repository right now
|
|
44
45
|
- 2. Workspace and ledger
|
|
45
46
|
- 3. Models
|
|
46
47
|
- 4. The task loop
|
|
48
|
+
- 4a. A screen is the frame, implemented
|
|
47
49
|
- 5. Final whole-branch review
|
|
48
50
|
- 6. Integrate, then finish
|
|
49
51
|
- GATE (auto)
|
|
@@ -93,6 +95,36 @@ download`), then run the test command from the brief's autonomy sweep. A dirty
|
|
|
93
95
|
baseline makes every later failure ambiguous: report failures and let the operator
|
|
94
96
|
decide whether to proceed.
|
|
95
97
|
|
|
98
|
+
## 1a. Another agent may be in this repository right now
|
|
99
|
+
|
|
100
|
+
Isolation above is about *your* passes not colliding with each other. This is about
|
|
101
|
+
someone else's.
|
|
102
|
+
|
|
103
|
+
**Check before you start, and check by looking rather than by assuming.** A second
|
|
104
|
+
agent leaves traces: uncommitted changes you did not make, a branch that moved under
|
|
105
|
+
you, a version number that was free an hour ago and is taken now. The cost is not
|
|
106
|
+
hypothetical — one session measured four version collisions, a `files[]` entry dropped
|
|
107
|
+
silently by a merge, and a test run that failed because a probe copied the tree while
|
|
108
|
+
someone else was writing to it.
|
|
109
|
+
|
|
110
|
+
**Two mechanisms, and they answer different questions.**
|
|
111
|
+
|
|
112
|
+
1. **A worktree per agent, always.** Sharing a checkout is what turns two independent
|
|
113
|
+
changes into one corrupted state: a copy taken mid-write, an edit staged into
|
|
114
|
+
somebody else's commit, a branch switched under a running test. `git worktree add`
|
|
115
|
+
costs nothing and removes the class outright. Never work in a tree another agent is
|
|
116
|
+
editing, even briefly, even to "just check something".
|
|
117
|
+
2. **A lease before any shared register.** Where the project has
|
|
118
|
+
`.claude/agent-sync.json`, the board, the decisions register, the open questions and
|
|
119
|
+
the roadmap are claimed before they are edited — that is what the file is for. Where
|
|
120
|
+
it does not exist, say so in the brief rather than discovering it at merge time.
|
|
121
|
+
|
|
122
|
+
**What to do when you find the other agent mid-run:** stop, name what you found, and
|
|
123
|
+
leave their work alone. Their uncommitted edits are not yours to stage, revert or
|
|
124
|
+
stash. Your own committed work is safe; put a ref on it so a branch reset cannot lose
|
|
125
|
+
it, and continue in a worktree of your own. Ending someone else's work to unblock
|
|
126
|
+
yourself is the same asymmetry `residue.md` refuses, one layer up.
|
|
127
|
+
|
|
96
128
|
## 2. Workspace and ledger
|
|
97
129
|
|
|
98
130
|
Conversation memory does not survive compaction. A controller that lost its place
|
|
@@ -392,6 +424,60 @@ When the review is clean — or every open finding is parked with a ruling at th
|
|
|
392
424
|
Mark the todo complete, move on. Never start the next task while Critical/Important
|
|
393
425
|
findings are neither fixed nor parked-with-ruling at the cap.
|
|
394
426
|
|
|
427
|
+
## 4a. A screen is the frame, implemented
|
|
428
|
+
|
|
429
|
+
When Figma is connected, a screen is not *informed by* the design file — it **is** the
|
|
430
|
+
frame, in code. Values, structure and composition all come from the file, and the order
|
|
431
|
+
of authority is fixed:
|
|
432
|
+
|
|
433
|
+
| Question | Answer comes from |
|
|
434
|
+
|---|---|
|
|
435
|
+
| what the screen **does** — states, errors, empties | `super-ux`'s scenarios |
|
|
436
|
+
| what it is **made of** — elements, hierarchy, layout, tokens | **the frame** |
|
|
437
|
+
| how it **looks and moves** where the frame is silent | `sheleg-design` |
|
|
438
|
+
|
|
439
|
+
`sheleg-design` runs **after** the file, never instead of it. It owns rhythm, motion and
|
|
440
|
+
motion's degradation to stillness — the things a frame does not carry. Put it first and
|
|
441
|
+
it invents what was already decided.
|
|
442
|
+
|
|
443
|
+
**Five things this makes concrete.**
|
|
444
|
+
|
|
445
|
+
1. **The composition is compared, not recalled.** A frame has a node tree
|
|
446
|
+
(`get_metadata`). Every node has a counterpart in the screen, and nothing is present
|
|
447
|
+
that the frame does not have. A missing element is incomplete; an invented one is a
|
|
448
|
+
divergence, not an improvement.
|
|
449
|
+
2. **Layout is read, not eyeballed.** Auto-layout direction, gaps, padding and
|
|
450
|
+
constraints come from `get_design_context`. From a screenshot they are recovered
|
|
451
|
+
approximately, and approximate is indistinguishable from exact in a report.
|
|
452
|
+
3. **A component with a Code Connect mapping is not rewritten.** If
|
|
453
|
+
`get_code_connect_map` names a code component for that node, the screen uses it.
|
|
454
|
+
Reimplementing it is a silent fork of the design system.
|
|
455
|
+
4. **A token names its variable.** A raw hex or px where the file has a variable is a
|
|
456
|
+
token that has quietly split in two. `get_variable_defs` is the canon; a screenshot
|
|
457
|
+
is a way to *look*, never a way to *know*.
|
|
458
|
+
5. **The frame is a contract at its own width.** It is one width and said nothing about
|
|
459
|
+
the others, so behaviour at other breakpoints — and states the frame does not draw,
|
|
460
|
+
like error, empty and loading — is a **decision that gets recorded**, not guessed.
|
|
461
|
+
Without this the rule is either unfollowable or vacuous.
|
|
462
|
+
|
|
463
|
+
**When there is no frame for a screen — build it, name it, offer to draw it.**
|
|
464
|
+
|
|
465
|
+
Figma is a recommendation like the graph and the wiki: its absence is named and never
|
|
466
|
+
blocks. So the screen is built from `sheleg-design`'s style pack, the spec records
|
|
467
|
+
*"no frame — source: sheleg-design"*, and the run **offers to draw the missing screens**
|
|
468
|
+
into the file the brief already named. Concretely: which screens, where they land, what
|
|
469
|
+
they are drawn from — so the operator sees the size before saying go.
|
|
470
|
+
|
|
471
|
+
Drawing happens **only on an explicit go**, into the recorded destination, never into a
|
|
472
|
+
new file. And whatever is drawn is **marked as coming from implementation** — its own
|
|
473
|
+
page or a naming convention that says so. A designer opening the file must be able to
|
|
474
|
+
tell what a person decided from what a run generated; an unmarked generated frame is the
|
|
475
|
+
same false confidence as an unproven green.
|
|
476
|
+
|
|
477
|
+
**Deviation is a line, not a silence.** Where the implementation must differ — a
|
|
478
|
+
platform constraint, an accessibility floor, a breakpoint — write what and why.
|
|
479
|
+
Otherwise *"built from the frame"* and *"built to look like it"* read identically.
|
|
480
|
+
|
|
395
481
|
## 5. Final whole-branch review
|
|
396
482
|
|
|
397
483
|
After the last task: build a package over `MERGE_BASE`..`HEAD`
|
|
@@ -303,6 +303,12 @@ Three things make the line worth writing rather than a habit:
|
|
|
303
303
|
- **It records how many classes were enumerated.** `8/8` and `7/8, unlooked:
|
|
304
304
|
containers` are different facts, and a run without container tooling must print
|
|
305
305
|
the second rather than a clean zero it did not earn.
|
|
306
|
+
- **`SURFACED: 0` is checked against what the run filed.** A run that opened a board
|
|
307
|
+
row, a carry-over row, an open question or a retro entry has provably surfaced
|
|
308
|
+
something; reporting zero contradicts its own artefacts, and that disagreement is
|
|
309
|
+
computable from the `Source` column every board row carries. The residual belongs
|
|
310
|
+
in the same sentence: a run can surface something, file it nowhere, report zero,
|
|
311
|
+
and **nothing will notice** — this check kills the silent zero, not the blind spot.
|
|
306
312
|
- **It is a disclosure, never a ratchet.** No floor, no direction, no target. A
|
|
307
313
|
build stage legitimately holding a worktree and a database prints `2` and
|
|
308
314
|
passes; a run that tears its database down to make the number tidy and brings
|
|
@@ -54,6 +54,13 @@ give the install line and stop; don't improvise a half-chain.
|
|
|
54
54
|
5. **Run the linter** (`/ux-lint`, i.e. `python3 docs/ux/lint.py`). It must pass:
|
|
55
55
|
no drift, no orphans, no broken traces, no stale Figma links.
|
|
56
56
|
|
|
57
|
+
**The screen's source of truth is recorded here, not assumed.** Figma on → the frame
|
|
58
|
+
supplies composition, layout and tokens, and `sheleg-design` supplies only what the
|
|
59
|
+
frame is silent about. Figma off, or no frame for this screen → the style pack is the
|
|
60
|
+
source and the spec says so, screen by screen. A screen whose values were taken from a
|
|
61
|
+
screenshot is named as such: *sighted* and *read from the file* are different claims
|
|
62
|
+
([`build.md`](build.md) → *A screen is the frame, implemented*).
|
|
63
|
+
|
|
57
64
|
These skills are **idempotent** — extend the existing `docs/ux/` layers, never
|
|
58
65
|
rebuild them. If the chain already exists and is validated (typically when the run
|
|
59
66
|
entered from super-ux), verify it and embed it; build only what's missing.
|