@erclx/canon 5.14.0 → 5.15.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.
- package/README.md +3 -2
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/draft-screencast/REQUIREMENT.md +2 -1
- package/claude/skills/draft-screencast/SKILL.md +14 -9
- package/claude/skills/read-frames/SKILL.md +3 -2
- package/claude/skills/record-screencast/REQUIREMENT.md +3 -0
- package/claude/skills/record-screencast/SKILL.md +28 -5
- package/claude/skills/review-pr/SKILL.md +1 -1
- package/claude/skills/review-pr/references/close-out.md +1 -1
- package/claude/skills/review-pr/references/post.md +1 -1
- package/claude/skills/role-orchestrator/SKILL.md +1 -1
- package/claude/skills/role-orchestrator/references/orchestrator-poll.md +10 -10
- package/claude/skills/role-orchestrator/scripts/poll.ts +628 -0
- package/claude/skills/role-orchestrator/scripts/repo.ts +69 -0
- package/claude/skills/role-orchestrator/scripts/watch.ts +267 -0
- package/docs/agents/commands.md +3 -0
- package/docs/agents/demo.md +34 -7
- package/docs/agents/migrate.md +1 -1
- package/docs/agents/pr-reads.md +1 -1
- package/docs/agents/sandbox.md +28 -3
- package/docs/agents/state-scoped-risk.md +2 -2
- package/docs/target/migrations.md +1 -1
- package/docs/workflow/ai-workflow.md +2 -3
- package/docs/workflow/skill-map.md +1 -1
- package/governance/renames.toml +7 -5
- package/governance/rules/canon/630-requirements.md +1 -1
- package/package.json +8 -6
- package/scripts/core/check-color-source.sh +11 -1
- package/scripts/core/install-check.sh +13 -4
- package/scripts/lib/sandbox-dispatch.sh +1 -1
- package/scripts/lib/sandbox-fixtures.sh +2 -2
- package/scripts/lib/sandbox-path.sh +1 -1
- package/scripts/manage-sandbox.sh +2 -2
- package/src/canvas/client/app.tsx +85 -0
- package/src/canvas/client/main.tsx +62 -0
- package/src/canvas/client/pages-panel.tsx +123 -0
- package/src/canvas/client/shell.css +319 -0
- package/src/canvas/client/state.ts +186 -0
- package/src/canvas/client/surface.tsx +213 -0
- package/src/canvas/content.ts +326 -0
- package/src/canvas/index.html +14 -0
- package/src/canvas/server.ts +302 -0
- package/src/canvas/tokens.ts +71 -0
- package/src/claude/seeds.ts +0 -1
- package/src/cli.ts +2 -0
- package/src/commands/canvas.ts +325 -0
- package/src/commands/claude.ts +9 -14
- package/src/commands/demo.ts +6 -6
- package/src/commands/sandbox.ts +110 -2
- package/src/context/citations.ts +1 -1
- package/src/context/classify/prompts.ts +1 -1
- package/src/context/folders.ts +0 -1
- package/src/demo/compile.ts +8 -4
- package/src/demo/container.ts +1 -1
- package/src/gov/renames.ts +3 -2
- package/src/help.ts +1 -0
- package/src/record-root.ts +1 -0
- package/src/sandbox/census.ts +1 -1
- package/src/sandbox/coverage.ts +1 -1
- package/src/sandbox/equivalence.ts +847 -0
- package/src/sandbox/expect.ts +0 -1
- package/src/serve/static.ts +25 -11
- package/src/shipped/references.ts +8 -10
- package/src/surface-root.ts +0 -1
- package/src/targets/pulls.ts +2 -2
- package/standards/architecture.md +1 -1
- package/standards/context.md +1 -1
- package/standards/design.md +1 -1
- package/standards/index.md +0 -1
- package/standards/requirements.md +4 -6
- package/standards/wireframes.md +2 -2
- package/tooling/claude/reference.md +0 -1
- package/tooling/claude/seeds/canon/REQUIREMENTS.md +0 -2
- package/tsconfig.json +1 -1
- package/claude/skills/role-orchestrator/scripts/poll.sh +0 -504
- package/claude/skills/role-orchestrator/scripts/watch.sh +0 -181
- package/governance/rules/canon/645-decisions.md +0 -12
- package/standards/decisions.md +0 -105
- package/tooling/claude/seeds/canon/decisions/index.md +0 -8
package/src/sandbox/expect.ts
CHANGED
package/src/serve/static.ts
CHANGED
|
@@ -13,7 +13,7 @@ export const SERVE_HOST = '127.0.0.1'
|
|
|
13
13
|
export const DEFAULT_PORT = 8787
|
|
14
14
|
|
|
15
15
|
/** How far past the requested port to look before refusing. */
|
|
16
|
-
const PORT_ATTEMPTS = 20
|
|
16
|
+
export const PORT_ATTEMPTS = 20
|
|
17
17
|
|
|
18
18
|
const DEFAULT_ENTRY = 'index.html'
|
|
19
19
|
|
|
@@ -216,23 +216,23 @@ export function shouldWalkPast(error: unknown): boolean {
|
|
|
216
216
|
return (error as NodeJS.ErrnoException | null)?.code === 'EADDRINUSE'
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
type BoundServer = ReturnType<typeof Bun.serve>
|
|
220
|
+
|
|
219
221
|
/**
|
|
220
222
|
* Picks a listening port, starting at the requested one and walking forward.
|
|
221
223
|
* A busy port is the ordinary case rather than a failure, since a preview of
|
|
222
224
|
* one workspace is routinely open while another is started.
|
|
225
|
+
*
|
|
226
|
+
* Takes the bind as a parameter so every surface that serves walks ports the
|
|
227
|
+
* same way, whatever routes it binds.
|
|
223
228
|
*/
|
|
224
|
-
function
|
|
225
|
-
root: string,
|
|
229
|
+
export function bindFirstFree(
|
|
226
230
|
first: number,
|
|
227
|
-
|
|
228
|
-
): { server:
|
|
231
|
+
bind: (port: number) => BoundServer,
|
|
232
|
+
): { server: BoundServer; port: number } | undefined {
|
|
229
233
|
for (let port = first; port < first + PORT_ATTEMPTS; port++) {
|
|
230
234
|
try {
|
|
231
|
-
const server =
|
|
232
|
-
hostname: SERVE_HOST,
|
|
233
|
-
port,
|
|
234
|
-
fetch: (request) => respond(root, request, index),
|
|
235
|
-
})
|
|
235
|
+
const server = bind(port)
|
|
236
236
|
/**
|
|
237
237
|
* The bound port rather than the requested one. Port 0 asks the OS to
|
|
238
238
|
* choose, so reporting the request builds a URL pointing at nothing.
|
|
@@ -245,7 +245,7 @@ function listen(
|
|
|
245
245
|
* Contention is the one cause worth walking past. A permission failure
|
|
246
246
|
* or an unavailable interface swallowed here would be retried twenty
|
|
247
247
|
* times and then reported as a port range being full, which names a
|
|
248
|
-
* cause nothing checked.
|
|
248
|
+
* cause nothing checked. The caller turns the rethrow into a refusal.
|
|
249
249
|
*/
|
|
250
250
|
if (!shouldWalkPast(error)) throw error
|
|
251
251
|
}
|
|
@@ -253,6 +253,20 @@ function listen(
|
|
|
253
253
|
return undefined
|
|
254
254
|
}
|
|
255
255
|
|
|
256
|
+
function listen(
|
|
257
|
+
root: string,
|
|
258
|
+
first: number,
|
|
259
|
+
index: boolean,
|
|
260
|
+
): { server: BoundServer; port: number } | undefined {
|
|
261
|
+
return bindFirstFree(first, (port) =>
|
|
262
|
+
Bun.serve({
|
|
263
|
+
hostname: SERVE_HOST,
|
|
264
|
+
port,
|
|
265
|
+
fetch: (request) => respond(root, request, index),
|
|
266
|
+
}),
|
|
267
|
+
)
|
|
268
|
+
}
|
|
269
|
+
|
|
256
270
|
export async function respond(
|
|
257
271
|
root: string,
|
|
258
272
|
request: Request,
|
|
@@ -36,13 +36,10 @@ export const SHIPPED_CORPORA = [
|
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* Trees inside a corpus above that no target receives, matching the negations
|
|
39
|
-
* the `files` field already makes. A number under
|
|
40
|
-
*
|
|
39
|
+
* the `files` field already makes. A number under one names something its only
|
|
40
|
+
* reader can already resolve.
|
|
41
41
|
*/
|
|
42
|
-
export const SHIPPED_EXCLUSIONS = [
|
|
43
|
-
/^scripts\/sandbox\//,
|
|
44
|
-
/^scripts\/eval\//,
|
|
45
|
-
] as const
|
|
42
|
+
export const SHIPPED_EXCLUSIONS = [/^scripts\/eval\//] as const
|
|
46
43
|
|
|
47
44
|
/** Whether a repository-relative path sits in the gated corpus. */
|
|
48
45
|
export function isShippedCorpus(path: string): boolean {
|
|
@@ -97,10 +94,11 @@ const PULL_REQUEST = /(?<![0-9A-Za-z_])#([0-9]+)(?![0-9A-Za-z_])/g
|
|
|
97
94
|
* The third is the one a later author meets. Admitting an all-digit sha admits
|
|
98
95
|
* every run of seven or more decimal digits with it, so a date written without
|
|
99
96
|
* separators, a large count, or a float artifact reads as a commit reference.
|
|
100
|
-
* The corpus carries no instance and that is the
|
|
101
|
-
* twelve such runs
|
|
102
|
-
* `scripts
|
|
103
|
-
*
|
|
97
|
+
* The corpus carries no instance and that is the corpus bounds rather than luck:
|
|
98
|
+
* twelve such runs were counted when the scenario tree still sat under
|
|
99
|
+
* `scripts/`, eleven of them under that tree, `scripts/eval/`, or a test file,
|
|
100
|
+
* all now outside the corpus, and the twelfth is the genuine sha in
|
|
101
|
+
* `orchestrator-poll.md`. Write a seven-digit measurement into a
|
|
104
102
|
* shipped page and the push fails on it, which the marker answers and no
|
|
105
103
|
* narrowing can, since requiring a letter loses the all-digit sha above.
|
|
106
104
|
*/
|
package/src/surface-root.ts
CHANGED
package/src/targets/pulls.ts
CHANGED
|
@@ -8,7 +8,7 @@ const GH_TIMEOUT_MS = 30_000
|
|
|
8
8
|
* The two headings a review pass posts under.
|
|
9
9
|
*
|
|
10
10
|
* Owned by `review-pr`, which states the full set once, and pinned here
|
|
11
|
-
* the way `role-orchestrator/scripts/poll.
|
|
11
|
+
* the way `role-orchestrator/scripts/poll.ts` pins them. All three surfaces
|
|
12
12
|
* ship separately, so a heading added in that skill goes stale here with
|
|
13
13
|
* nothing comparing the copies.
|
|
14
14
|
*/
|
|
@@ -139,7 +139,7 @@ export function rollup(checks: readonly RawCheck[]): ChecksState | null {
|
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
141
|
* Reads the heading of the newest pass carrying one, matching on the first line
|
|
142
|
-
* alone the way `poll.
|
|
142
|
+
* alone the way `poll.ts` does.
|
|
143
143
|
*
|
|
144
144
|
* The reviews arrive oldest first, so the last match is the current state of
|
|
145
145
|
* the thread. A pass carrying neither heading is somebody reviewing by hand and
|
|
@@ -40,7 +40,7 @@ The slots come from a scale test. Ask whether the decision would still be in thi
|
|
|
40
40
|
- A decision that fills no slot. It lives in the domain context entry it constrains, and this file carries at most one line pointing at it.
|
|
41
41
|
- A measurement paragraph specific to one domain's own mechanism, even behind a slot decision. Route it to that domain's context entry and keep the choice, the alternative that lost, and one reason here.
|
|
42
42
|
- The instances of a build principle. The principle takes one sentence here, and each instance lives in the domain entry where it applies.
|
|
43
|
-
- The history of how a decision was reached or revised: rounds of candidates, a figure followed by its correction, a branch or change that moved a number.
|
|
43
|
+
- The history of how a decision was reached or revised: rounds of candidates, a figure followed by its correction, a branch or change that moved a number. Cut it. Git and the change that introduced it keep the trail.
|
|
44
44
|
|
|
45
45
|
## Sections
|
|
46
46
|
|
package/standards/context.md
CHANGED
|
@@ -100,7 +100,7 @@ Only the `development` entry carries this section. It is not a general-purpose h
|
|
|
100
100
|
- Anything already in `canon/REQUIREMENTS.md` or `canon/ARCHITECTURE.md`.
|
|
101
101
|
- The history of how the domain reached its current shape. An entry describes the repository as it stands, so a change number, release label, or date attached to a change goes wherever the project tracks work.
|
|
102
102
|
- A rejected alternative's provenance, which is the same rule at the one place the section above admits history. Keep what was tried and why it lost. Cut who tried it and when.
|
|
103
|
-
- The route to a decision: the rounds of candidates, the tuning steps a threshold passed through, the review pass that caught a miss. State the decision, what lost, and why, once and in the present tense.
|
|
103
|
+
- The route to a decision: the rounds of candidates, the tuning steps a threshold passed through, the review pass that caught a miss. State the decision, what lost, and why, once and in the present tense. Cut the route. Git and the change that introduced it keep it.
|
|
104
104
|
- Measured results a generated file already carries. Point at the file instead of copying the figure, so a re-run cannot leave the entry behind.
|
|
105
105
|
|
|
106
106
|
## Length
|
package/standards/design.md
CHANGED
|
@@ -27,7 +27,7 @@ Does not govern:
|
|
|
27
27
|
|
|
28
28
|
- CSS classes and prop names. Those live in code.
|
|
29
29
|
- Anything that needs updating every time the code is refactored
|
|
30
|
-
- The history of how a value or a mark was chosen: the candidates, the rounds, the date of a pick. State the rule and the current value
|
|
30
|
+
- The history of how a value or a mark was chosen: the candidates, the rounds, the date of a pick. State the rule and the current value, and cut the trail. Git keeps it.
|
|
31
31
|
|
|
32
32
|
## Format
|
|
33
33
|
|
package/standards/index.md
CHANGED
|
@@ -12,7 +12,6 @@ Reference docs for consistent authoring across the toolkit and target projects.
|
|
|
12
12
|
- [Branch reference](branch.md): Branch naming format and type conventions
|
|
13
13
|
- [Commit reference](commit.md): Commit message format and type conventions
|
|
14
14
|
- [Context entry reference](context.md): Shape and content rules for canon/context/<domain>.md entries
|
|
15
|
-
- [Decisions reference](decisions.md): Folder layout, ordinal filename, frontmatter, record sections, and the append-only lifecycle for canon/decisions/
|
|
16
15
|
- [Design reference](design.md): Shape and content rules for canon/DESIGN.md
|
|
17
16
|
- [Diagram reference](diagrams.md): Shape and content rules for .canon/diagrams/<kind>.md files
|
|
18
17
|
- [Docs reference](docs.md): Reader and jurisdiction, frontmatter, page structure, what a page links out to, the diagram permission, and when a category earns a subfolder
|
|
@@ -9,7 +9,7 @@ Applies to `canon/REQUIREMENTS.md`. Describes what the product does and why, not
|
|
|
9
9
|
|
|
10
10
|
## Scope
|
|
11
11
|
|
|
12
|
-
Governs the product-scope document at `canon/REQUIREMENTS.md`: problem, goals, non-goals, MVP features, distribution,
|
|
12
|
+
Governs the product-scope document at `canon/REQUIREMENTS.md`: problem, goals, non-goals, MVP features, distribution, and constraints.
|
|
13
13
|
|
|
14
14
|
Does not govern:
|
|
15
15
|
|
|
@@ -23,7 +23,6 @@ Does not govern:
|
|
|
23
23
|
- User-facing goals stated as outcomes, not implementation
|
|
24
24
|
- Explicit non-goals that prevent feature creep. Mark deferred items "(deferred)" so they read as paused, not excluded. A non-goal resting on how an outside tool, an installer, or the model behaves may close with one `Revisit when <finding>.` sentence, and a non-goal resting on scope alone takes none.
|
|
25
25
|
- MVP features as a numbered list: feature name and one-line description
|
|
26
|
-
- Tech stack as a plain list of tools
|
|
27
26
|
- Hard constraints that shape every decision
|
|
28
27
|
|
|
29
28
|
## What does not go in
|
|
@@ -31,14 +30,15 @@ Does not govern:
|
|
|
31
30
|
- Implementation details, API names, or internal component references
|
|
32
31
|
- Anything that describes how a feature is built rather than what it does
|
|
33
32
|
- Measured results, such as scores, benchmark figures, or token counts. They move on every run and this file changes least. Name where the results live instead.
|
|
33
|
+
- Content another canonical doc owns, such as the stack list, which the stack-and-runtime slot of `canon/ARCHITECTURE.md` holds, or the rules of this standard itself
|
|
34
34
|
|
|
35
35
|
## Sections
|
|
36
36
|
|
|
37
|
-
Use `## Problem`, `## Goals`, `## Non-goals`, `## MVP features`,
|
|
37
|
+
Use `## Problem`, `## Goals`, `## Non-goals`, `## MVP features`, and `## Constraints`. Add `## Distribution` when the rule below applies. Add `## Worldview` when the project holds beliefs that shape every decision, and keep a belief there only when it changes a decision, since a padded worldview turns into a second goals list. Add `## Premise` when the project exists to answer a question, stated as the question and what would count as an answer, never as the answer measured so far. Drop a section rather than pad it with filler.
|
|
38
38
|
|
|
39
39
|
## Lifecycle
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Once every entry in the MVP list, or in a later scope section, has shipped, delete the section. Git keeps the old text, and the document states the project as it stands. Do not annotate an entry as shipped and leave it in place. While any entry is unshipped, do not renumber the list or append to it.
|
|
42
42
|
|
|
43
43
|
Later scope arrives as a new section rather than as an extension of the MVP list. Name the section for what it delivers and state its entries as outcomes, the same way the goals are stated. Nothing sequences either list into versions. Work reaches the board as discrete tasks under `tasks.md`, and `board.md` orders them by readiness, so a section here states what is wanted and never when it lands.
|
|
44
44
|
|
|
@@ -65,7 +65,5 @@ State each entry as an outcome the consumer reaches, never as the mechanism that
|
|
|
65
65
|
|
|
66
66
|
<!-- ## Distribution: include only when shipping outside the repository -->
|
|
67
67
|
|
|
68
|
-
## Tech stack
|
|
69
|
-
|
|
70
68
|
## Constraints
|
|
71
69
|
```
|
package/standards/wireframes.md
CHANGED
|
@@ -76,11 +76,11 @@ Both fields feed `canon/wireframes/index.md` when regenerated.
|
|
|
76
76
|
## Not on this surface
|
|
77
77
|
|
|
78
78
|
- State what was deliberately left off, one bullet per exclusion, as a present-tense rule: `- No navigation rail`. This is the section that stops a draft from proposing what was already ruled out.
|
|
79
|
-
- Keep the reason to a clause where one is needed.
|
|
79
|
+
- Keep the reason to a clause where one is needed. Cut the rounds that ruled it out.
|
|
80
80
|
|
|
81
81
|
## What moves out
|
|
82
82
|
|
|
83
|
-
- Which candidate beat which, and when: the
|
|
83
|
+
- Which candidate beat which, and when: nowhere. Cut it, since git keeps the old text
|
|
84
84
|
- Measurements such as contrast ratios and timings: `canon/DESIGN.md` for tokens and floors, the surface's context entry for the rest
|
|
85
85
|
|
|
86
86
|
## What moves to canon/context/
|
|
@@ -14,7 +14,6 @@ canon/
|
|
|
14
14
|
├── ARCHITECTURE.md ← seeded. Technical design decisions and open questions
|
|
15
15
|
├── DESIGN.md ← seeded. Visual intent and the decisions behind it
|
|
16
16
|
├── context/ ← seeded. Per-domain narrative. `index.md` is the discovery anchor.
|
|
17
|
-
├── decisions/ ← seeded. Decision history a canonical doc points at, never loaded eagerly. `<nn>-<slug>.md` records.
|
|
18
17
|
└── wireframes/ ← seeded. Per-surface regions and states. `index.md` is the discovery anchor; `<surface>.md` files hold the regions list, the states table, and the behavior bullets.
|
|
19
18
|
|
|
20
19
|
.claude/
|
package/tsconfig.json
CHANGED