@erclx/aitk 0.32.0 → 0.34.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/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/bash-script/REQUIREMENT.md +36 -0
- package/claude/skills/ci-workflow/REQUIREMENT.md +35 -0
- package/claude/skills/claude-groundwork/SKILL.md +2 -1
- package/claude/skills/claude-memory-review/REQUIREMENT.md +1 -0
- package/claude/skills/claude-memory-review/SKILL.md +1 -1
- package/claude/skills/claude-orchestrate/SKILL.md +2 -2
- package/claude/skills/claude-pr-review/REQUIREMENT.md +6 -5
- package/claude/skills/claude-pr-review/SKILL.md +19 -14
- package/claude/skills/claude-seed-sync/REQUIREMENT.md +40 -0
- package/claude/skills/claude-seed-sync/SKILL.md +1 -1
- package/claude/skills/docs-sync/REQUIREMENT.md +38 -0
- package/docs/agents.md +17 -9
- package/docs/ai-workflow.md +3 -3
- package/docs/operating-model.md +7 -6
- package/governance/rules/claude/510-context.md +1 -0
- package/package.json +1 -1
- package/src/claude/skills-list.ts +6 -0
- package/src/commands/context.ts +27 -4
- package/src/context/audit.ts +46 -3
- package/src/context/folders.ts +9 -1
- package/standards/context.md +1 -0
- package/standards/tasks.md +27 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bash-script
|
|
3
|
+
description: Scope boundary for the interactive script house style and the stream discipline underneath it
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Bash script requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, a session asked for a human-facing shell tool writes one whose frame decoration, log lines, and prompts all land on stdout, so the script cannot be piped and any data it emits arrives mixed with its own presentation.
|
|
11
|
+
|
|
12
|
+
Three more failures share a cause, which is that an interactive script is written as though a person is always watching. A prompt blocks forever when stdin is not a terminal, which is the shape every CI job and every agent run has. A cancellation path prints both a cancel line and an error, or an exit trap prints a closing frame the success path already printed, so the same run reports twice. And each generated script picks its own icons, casing, and frame characters, so a folder of them reads as several unrelated tools.
|
|
13
|
+
|
|
14
|
+
The visual conventions this skill fixes are otherwise arbitrary. Their value is that they are the same across every script, which is a property no individual script can establish for itself.
|
|
15
|
+
|
|
16
|
+
## Must
|
|
17
|
+
|
|
18
|
+
- Keep every frame, log line, and prompt on stderr, and reserve stdout for data. `--help` is the one exception, since its consumer is a person rather than a pipe.
|
|
19
|
+
- Guard every prompt on an attached terminal and refuse inside the frame rather than blocking on a read that will never return
|
|
20
|
+
- Give the timeline one owner per exit path, so success, cancellation, and error each close it exactly once
|
|
21
|
+
- Copy the shared templates rather than restating them, keeping only the colors and functions the script uses
|
|
22
|
+
|
|
23
|
+
## Must not
|
|
24
|
+
|
|
25
|
+
- Assert a convention the generated script cannot be checked against by reading it. A rule that cannot be verified from the output is style with no gate behind it.
|
|
26
|
+
- Carry a second copy of the timeline, logging, or prompt implementations. The bundled reference is the single copy, and a body that restates it drifts from it.
|
|
27
|
+
|
|
28
|
+
## Guards
|
|
29
|
+
|
|
30
|
+
- A request for a script with no human at the terminal stops and routes to `cli-script` rather than generating a timeline nothing will render
|
|
31
|
+
|
|
32
|
+
## Out of scope
|
|
33
|
+
|
|
34
|
+
- Non-interactive automation, CI, and agent-run scripts: `cli-script`, which keeps the error handling and the stdout contract and drops the timeline, the icons, and the prompts
|
|
35
|
+
- GitHub Actions workflow files: `ci-workflow`
|
|
36
|
+
- What the generated script does. This skill fixes the shape of the output and the stream it goes to, and the commands belong to the request.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci-workflow
|
|
3
|
+
description: Scope boundary for pipeline structure against job contents, and the reproducibility rules under it
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CI workflow requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, a session writes a pipeline whose jobs run in sequence because `needs` was used to express the order a person reads them in rather than a data dependency. The pipeline then costs the sum of its jobs where it could have cost the longest one, and the waste compounds on every push.
|
|
11
|
+
|
|
12
|
+
The rest are reproducibility failures that surface as flakes. An action pinned to a moving ref changes under the project, so a run that passed yesterday fails today with no commit behind it and the diff explains nothing. A cache keyed on a static string serves a stale browser or toolchain after a version bump, and the failure reads as a broken test rather than a stale cache. Artifacts upload on every run and never expire, so storage grows with the commit count while the ones worth reading are the failures. And a workflow with no manual trigger can only be reproduced by pushing a commit, which is the wrong instrument for a run that failed for an environmental reason.
|
|
13
|
+
|
|
14
|
+
## Must
|
|
15
|
+
|
|
16
|
+
- Gate a job only on a data dependency or on a cost that justifies the wait, and leave every other job parallel
|
|
17
|
+
- Pin every action to a tag that cannot cross a major version
|
|
18
|
+
- Key a cache on the version string of the thing it caches
|
|
19
|
+
- Give every workflow a manual trigger beside its primary one
|
|
20
|
+
- Bound artifact upload to failures and set an expiry on it
|
|
21
|
+
|
|
22
|
+
## Must not
|
|
23
|
+
|
|
24
|
+
- Own what runs inside a job. The build, test, and deploy commands come from the project, and a workflow asserting its own is a second copy of the project's scripts.
|
|
25
|
+
- Enumerate the job set as a fixed list. Projects add and remove jobs, and what has to survive that is the parallel and gated structure rather than the roster.
|
|
26
|
+
|
|
27
|
+
## Guards
|
|
28
|
+
|
|
29
|
+
- A request for a deploy, publish, or release step stops at the gate. The job's contents carry credentials and an environment this skill cannot see, so it emits the `needs` wiring and names what the caller has to fill in rather than guessing a deploy command.
|
|
30
|
+
|
|
31
|
+
## Out of scope
|
|
32
|
+
|
|
33
|
+
- The shell scripts a job invokes: `cli-script`
|
|
34
|
+
- Secrets, environments, and deploy targets, which live in the repository settings rather than in the workflow this skill writes
|
|
35
|
+
- CI systems other than GitHub Actions. The structure rules generalize and the file format does not, so a different system is a different skill rather than a flag on this one.
|
|
@@ -12,7 +12,8 @@ Read `${CLAUDE_SKILL_DIR}/references/folder-format.md` before writing any file i
|
|
|
12
12
|
## Guards
|
|
13
13
|
|
|
14
14
|
- If no topic is given, stop: `❌ No topic. Name what needs measuring.`
|
|
15
|
-
- Apply the qualifying test before
|
|
15
|
+
- Apply the qualifying test in open mode alone, after Step 1 resolves the mode and before the folder is created. Two of these three must hold: the current state is not known, more than one approach is live, and committing wrong costs more than a day of measuring. When one or fewer holds, stop: `❌ Already decided enough to plan. Run /claude-feature instead.`
|
|
16
|
+
- Resume and close are exempt from the test above. A track that has already been measured fails it by definition, since its current state is now known and its approaches have narrowed, so applying the test to either mode refuses the folder that same test admitted.
|
|
16
17
|
- Do not pause for approval between steps. The write scope below is what makes that safe.
|
|
17
18
|
|
|
18
19
|
## Write scope
|
|
@@ -15,6 +15,7 @@ Without this skill, the memory folder grows and never drains. Entries pile up re
|
|
|
15
15
|
- Verify the rule is not already stated or implied in the target before proposing a promotion, by reading the target rather than trusting the memory's claim about it
|
|
16
16
|
- Rewrite a rule into the destination's voice instead of moving it unchanged
|
|
17
17
|
- Write the proposal to a receipt on disk and take no action until the user decides per item
|
|
18
|
+
- Route every decision channel through the receipt, writing a decision given in chat into its item's slot before the parse reads the file, so a channel the skill advertises drains the pen rather than passing over it
|
|
18
19
|
- Keep a promotion on its own commit, since a change to how the agent operates should not ride inside a feature a reviewer is vetting for something else
|
|
19
20
|
- Confine the pass that runs after application to the one receipt it tested, so tidying up removes a file whose decisions are known to be resolved and leaves the pen and every untested receipt alone
|
|
20
21
|
|
|
@@ -181,7 +181,7 @@ Apply edits one at a time via `Edit`. Claude Code's tool permission dialog is th
|
|
|
181
181
|
|
|
182
182
|
As each item resolves, update its status in the review file: flip the H2 emoji from 📝 to ✅ for applied, ⏭ for skipped, 🗑 for deleted, or 🤝 for handed off. Refresh the summary block counts at the top. Do not delete the review file. It stays as a receipt until Cleanup runs or the next Propose pass overwrites it.
|
|
183
183
|
|
|
184
|
-
**Chat shortcut:** the user replies with `all`, `none`,
|
|
184
|
+
**Chat shortcut:** the user replies with `all`, `none`, a comma-separated list of numbers, or `skip <nums>`. Write the matching verb into the `Decision:` slot of every item the reply names, `apply` for `all` or a bare list and `skip` for a `skip` reply, then run the parse above against the file. A reply of `none` writes nothing. A slot the reply does not name keeps its own value, so the receipt stays the source of truth and an empty slot still means take no action.
|
|
185
185
|
|
|
186
186
|
End with: `✅ Applied: <nums> | ⏭ Skipped: <nums> | 📝 Pending: <nums>`. Omit empty buckets. If anything is pending, remind the user they can refine `Decision:` lines and re-ping, run "discuss" for question items, or commit a skip with `skip <nums>` in chat.
|
|
187
187
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: claude-orchestrate
|
|
3
|
-
description: Asserts the orchestrator role for the current session, holds the build loop and the queue-refill sweep, and dispatches to the
|
|
3
|
+
description: Asserts the orchestrator role for the current session, holds the build loop and the queue-refill sweep, and dispatches to the feature, review, and worktree skills. Use when asked to "be the orchestrator", "run the orchestrator", "orchestrate this project", or to set up the control session for parallel feature builds. Do NOT build features or merge PRs in this session.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -70,7 +70,7 @@ That command returns nothing for a roadmap that exists but has never been commit
|
|
|
70
70
|
|
|
71
71
|
## The loop
|
|
72
72
|
|
|
73
|
-
1. Own the roadmap while a scope exists to sequence.
|
|
73
|
+
1. Own the roadmap while a scope exists to sequence. Capture a needed draft or resequence of `.claude/ROADMAP.md` in the plan or a task file, naming the MVP list in `.claude/REQUIREMENTS.md` as the source, so a worker runs `claude-roadmap` in its branch and the tracked edit ships in a PR rather than dirtying main. Stop owning it once that list has shipped, since later work then arrives as discrete items rather than as versions.
|
|
74
74
|
2. Plan the next feature. Run `claude-feature` here, with the cross-feature context, to write a plan to `.claude/plans/`. Planning stays in this warm session so the plan front-loads reasoning a cold worker would otherwise re-derive.
|
|
75
75
|
3. Decide parallelism and merge order. Note which plans touch a shared wiring seam so their PRs merge in sequence, not at once.
|
|
76
76
|
4. Verify the plan against the tree. Reading it is not enough, since a plan goes stale from whatever merged after it was written. Grep for each construct it names and count the sites against the count it claims. Check that every phase label it cites is still open. Open each file it describes rather than trusting its account of the contents. Correct the plan before handing it over.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: claude-pr-review
|
|
3
|
-
description: What the independent pull request review is for, the gaps it closes, and why it posts
|
|
3
|
+
description: What the independent pull request review is for, the gaps it closes, and why it posts until nothing is open
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Claude PR review requirement
|
|
@@ -11,11 +11,12 @@ Without this skill, a pull request is reviewed only by the session that wrote it
|
|
|
11
11
|
|
|
12
12
|
## Must
|
|
13
13
|
|
|
14
|
-
- Post
|
|
14
|
+
- Post until the review closes. A first pass opens against the whole change, and each later pass checks whether the prior findings landed.
|
|
15
|
+
- Set the heading from the finding count rather than the pass number, so the most recent review comment's heading reports whether anything is open
|
|
15
16
|
- Detect the pass from the thread rather than taking it from the caller, matching the heading for equality so a neighboring comment cannot be read as a prior pass
|
|
16
|
-
- Scope a
|
|
17
|
+
- Scope a later pass to the commits added since the prior one, once that commit is confirmed to still reach the head
|
|
17
18
|
- Apply the integration, contract, and consumer lenses a self-review structurally cannot
|
|
18
|
-
- Post
|
|
19
|
+
- Post the closing pass even with nothing to report, since a review left unanswered reads as one nobody closed
|
|
19
20
|
- Key the body file on both the pull request number and the head commit, so no two passes overwrite each other
|
|
20
21
|
- Scan the comment for banned characters and internal phase labels before posting, since a finding phrased against a phase label reaches a reader with no task board
|
|
21
22
|
|
|
@@ -23,7 +24,7 @@ Without this skill, a pull request is reviewed only by the session that wrote it
|
|
|
23
24
|
|
|
24
25
|
- Merge. Review and post, and leave the gate to the human.
|
|
25
26
|
- Publish a claim the skill did not check. A failed fetch and a rebase both strand the prior commit, and only one of them is a rebase.
|
|
26
|
-
- Invent a
|
|
27
|
+
- Invent a heading beyond the two it posts and the response heading `claude-address-review` owns, or append a number GitHub already renders
|
|
27
28
|
- Review local uncommitted changes
|
|
28
29
|
- Lecture on process. The lenses land as findings, not as asides.
|
|
29
30
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: claude-pr-review
|
|
3
|
-
description: Reviews an open pull request from an independent session and posts findings as a review comment on the PR. Posts a first pass
|
|
3
|
+
description: Reviews an open pull request from an independent session and posts findings as a review comment on the PR. Posts a first pass against the whole change and every later pass against only the commits added since, under `## Review` while anything is open and `## Review closed` once nothing is. Reads project docs and the roadmap for cross-feature context a self-review lacks. Use when asked to "review the PR", "review this feature's PR", "post a PR review", "re-review the PR", "close out the review", "confirm the findings are fixed", or acting as the orchestrator reviewing a worker's PR. Do NOT use to review local uncommitted changes. That is `claude-review`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Claude PR review
|
|
@@ -10,9 +10,12 @@ This is the orchestrator's independent review, distinct from `claude-review`.
|
|
|
10
10
|
to disk. This one reviews an open PR the session did not write and posts the
|
|
11
11
|
findings to the PR, so the vantage is independent and the output is durable.
|
|
12
12
|
|
|
13
|
-
It posts twice over a pull request's life. A first pass opens the
|
|
14
|
-
the whole change
|
|
15
|
-
|
|
13
|
+
It posts at least twice over a pull request's life. A first pass opens the
|
|
14
|
+
review against the whole change, and every later pass reads only the commits
|
|
15
|
+
added since. The heading reports state rather than pass number: a pass carrying
|
|
16
|
+
findings takes `## Review`, and `## Review closed` is reserved for a pass
|
|
17
|
+
carrying none, so the most recent comment's heading reports where the review
|
|
18
|
+
stands. Every pass is this skill, and which one it is gets detected from the
|
|
16
19
|
thread rather than named by the caller.
|
|
17
20
|
|
|
18
21
|
## Guards
|
|
@@ -42,7 +45,7 @@ Find the commit the last pass covered:
|
|
|
42
45
|
gh pr view <number> --json reviews --jq '[.reviews[] | select(.body // "" | split("\n")[0] | rtrimstr("\r") | . == "## Review" or . == "## Review closed")] | last | .commit.oid'
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
Match the first line for equality against the two headings this skill posts. A prefix test also matches `## Review response` and any heading merely starting with those words, which would scope the
|
|
48
|
+
Match the first line for equality against the two headings this skill posts. A prefix test also matches `## Review response` and any heading merely starting with those words, which would scope the pass to whatever commit that comment carried. The `\r` trim covers a body composed in the GitHub web editor, which stores CRLF.
|
|
46
49
|
|
|
47
50
|
An empty result is a first pass. Read the whole change:
|
|
48
51
|
|
|
@@ -54,7 +57,7 @@ gh pr diff <number>
|
|
|
54
57
|
gh pr diff <number> --name-only
|
|
55
58
|
```
|
|
56
59
|
|
|
57
|
-
A commit is a
|
|
60
|
+
A commit is a later pass. Fetch the pull request head so both commits are local:
|
|
58
61
|
|
|
59
62
|
```bash
|
|
60
63
|
git fetch -q origin pull/<number>/head
|
|
@@ -82,7 +85,7 @@ Review the diff and files for the same axes as `claude-review` (bugs, edge cases
|
|
|
82
85
|
|
|
83
86
|
Apply the high-signal filter: flag only what will cause incorrect behavior, break a documented rule, or mislead a downstream feature. If uncertain, do not flag.
|
|
84
87
|
|
|
85
|
-
A
|
|
88
|
+
A later pass applies the same axes to the delta, and adds one check the first pass cannot make: did each prior finding land, and did the fix regress anything it touched. Findings of its own are normal findings, stated at the same severity and counted the same way. That count is what Step 4 reads to pick the heading, so a pass raising one of its own is not a close-out.
|
|
86
89
|
|
|
87
90
|
Use severity: `critical` (blocks merge), `should-fix` (fix before merge), `minor` (visibility only).
|
|
88
91
|
|
|
@@ -109,10 +112,10 @@ X critical, Y should-fix, Z minor. Reviewed against project docs and roadmap.
|
|
|
109
112
|
🤖 Reviewed by Claude Code
|
|
110
113
|
```
|
|
111
114
|
|
|
112
|
-
A
|
|
115
|
+
A later pass carrying findings keeps that shape and changes only the summary line:
|
|
113
116
|
|
|
114
117
|
```markdown
|
|
115
|
-
## Review
|
|
118
|
+
## Review
|
|
116
119
|
|
|
117
120
|
Re-reviewed `<short-sha>`, N commits since the prior pass. X critical, Y should-fix, Z minor.
|
|
118
121
|
|
|
@@ -123,9 +126,13 @@ Re-reviewed `<short-sha>`, N commits since the prior pass. X critical, Y should-
|
|
|
123
126
|
🤖 Reviewed by Claude Code
|
|
124
127
|
```
|
|
125
128
|
|
|
126
|
-
|
|
129
|
+
The heading reports whether anything is open and the summary line reports which pass this is. Post under `## Review` whenever the pass carries a finding at any severity, whether it is the first pass or the fourth. Reserve `## Review closed` for a pass carrying none, which makes it the marker worth scanning for rather than a label on a kind of pass. A pull request thread then reads as `## Review`, the worker's answer under `## Review response` from `claude-address-review`, another `## Review` while anything is still open, and `## Review closed` when nothing is.
|
|
130
|
+
|
|
131
|
+
Read the state off the most recent review comment rather than off the presence of a closed one. A close-out does not close the pull request, so a commit pushed after it gets its own pass, and that pass reopens the review under `## Review` when it raises anything.
|
|
127
132
|
|
|
128
|
-
|
|
133
|
+
Both of this skill's headings anchor as a section distinct from human threads. Do not invent one beyond those two and the `## Review response` a sibling owns, and do not append the PR number, which GitHub already renders above the comment.
|
|
134
|
+
|
|
135
|
+
Name the scope in every summary line after the first pass, since a reader cannot otherwise tell a narrow read from a full one. When the fallback in Step 2 fired, replace the commit count with `Re-reviewed the full change, the prior pass's commit is no longer on the branch`. Budget the body. State each finding as the failure and the fix in two or three sentences, not a paragraph of reasoning. Omit files with no findings. Do not lecture on process. The integration, contract, and consumer lenses stay, but as findings, not asides.
|
|
129
136
|
|
|
130
137
|
The `What is right` section is optional, capped at three bullets, and included only when it changes the merge decision. Drop it otherwise and let the summary line carry the approval.
|
|
131
138
|
|
|
@@ -137,9 +144,7 @@ Before posting, run the scan in `.claude/standards/publish.md` against the body,
|
|
|
137
144
|
gh pr review <number> --comment --body-file .claude/.tmp/pr-review/body-<number>-<short-sha>.md
|
|
138
145
|
```
|
|
139
146
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
If a close-out has no findings, post `✅ Prior findings addressed. Re-reviewed <short-sha>, N commits since the prior pass.` under `## Review closed`, again with the footer. Post it even when there is nothing to report. A first pass left with no closing comment reads as a review nobody answered.
|
|
147
|
+
A pass with no findings takes `## Review closed` and a short body, with the footer line included either way. On a first pass, post `✅ No blocking findings. Reviewed against project docs and roadmap.` On a later pass, post `✅ Prior findings addressed. Re-reviewed <short-sha>, N commits since the prior pass.` Post that one even when there is nothing to report. A review left with no closing comment reads as one nobody answered.
|
|
143
148
|
|
|
144
149
|
## Step 5: output
|
|
145
150
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claude-seed-sync
|
|
3
|
+
description: Scope boundary for section-granular seed reconciliation against the bulk install and sync commands
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Claude seed sync requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, a project that edited an installed seed or standard has two ways to take an upstream change and both lose something. `aitk standards install` overwrites every file, so the edits are gone with no record of what they were. `aitk standards sync` updates only files it already finds and adds none, so a standard written after the project installed never arrives at all. Neither can deliver one upstream section into a file the project has customized, which is the case a grown project is always in.
|
|
11
|
+
|
|
12
|
+
A whole-file diff does not close it either. It cannot separate a section the user rewrote on purpose from a section the toolkit moved on without them, so the choice reaches the user as accept everything or lose everything, and the safe answer is always to skip.
|
|
13
|
+
|
|
14
|
+
Two failures belong to the audit rather than to the diff. A decision taken in chat dies with the session, so an audit half applied cannot be resumed and the second run starts over. And a file the toolkit generates rather than ships, such as an index rebuilt from sibling frontmatter, is absent from every source catalog by design, so a naive comparison reports it as a local addition and invites the user to reconcile something nothing owns.
|
|
15
|
+
|
|
16
|
+
## Must
|
|
17
|
+
|
|
18
|
+
- Read seed and standard content from the CLI rather than holding a copy, so the audit and the install cannot disagree
|
|
19
|
+
- Diff per section, treating the preamble as a section of its own
|
|
20
|
+
- Separate a customized section from a stale one, and default the customized one to no action
|
|
21
|
+
- Persist the proposal and every decision to a review file that stays the source of truth across re-pings
|
|
22
|
+
- Apply one section at a time, never by rewriting a file
|
|
23
|
+
|
|
24
|
+
## Must not
|
|
25
|
+
|
|
26
|
+
- Propose removing a section present only in the target. Those are the customizations the skill exists to preserve.
|
|
27
|
+
- Write a target file before a decision is recorded against the item
|
|
28
|
+
- Read an empty decision slot as consent
|
|
29
|
+
|
|
30
|
+
## Guards
|
|
31
|
+
|
|
32
|
+
- No `aitk` on PATH, or no `.claude/` directory at the project root, stops before any read
|
|
33
|
+
|
|
34
|
+
## Out of scope
|
|
35
|
+
|
|
36
|
+
- Bulk install and sync of a whole domain, which `aitk <domain> install` and `aitk <domain> sync` own and `toolkit-cli` documents. Reach for this skill when the target holds edits worth keeping, and for those commands when it does not.
|
|
37
|
+
- Golden configs, which overwrite by design and carry no section structure to diff
|
|
38
|
+
- Governance rules: `aitk gov sync`
|
|
39
|
+
- First-time scaffold of a project that has installed nothing yet: `setup-init`
|
|
40
|
+
- Public `README.md` and `docs/` prose: `docs-sync`
|
|
@@ -121,7 +121,7 @@ Re-read the review file as source of truth. For each item, parse `Decision:`:
|
|
|
121
121
|
- `defer` or empty: leave 📝 pending, no action.
|
|
122
122
|
- Contains `?` or unrecognized verb: leave 📝 pending, no action.
|
|
123
123
|
|
|
124
|
-
Chat shortcut: the user replies with `all`, `none`,
|
|
124
|
+
Chat shortcut: the user replies with `all`, `none`, a comma-separated list of numbers, or `skip <nums>`. Write the matching verb into the `Decision:` slot of every item the reply names, `apply` for `all` or a bare list and `skip` for a `skip` reply, then run the parse above against the file. A reply of `none` writes nothing. A slot the reply does not name keeps its own value, so the receipt stays the source of truth and an empty slot still means take no action.
|
|
125
125
|
|
|
126
126
|
Apply edits one at a time via `Edit`, replacing one section at a time. Never rewrite a whole file. Claude Code's tool permission dialog is the confirmation gate per edit.
|
|
127
127
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docs-sync
|
|
3
|
+
description: Scope boundary for consumer-facing prose against the agent-facing docs the ship chain syncs beside it
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Docs sync requirement
|
|
7
|
+
|
|
8
|
+
## Gap
|
|
9
|
+
|
|
10
|
+
Without this skill, a rename or a dropped flag ships with the README still describing the old surface. Nothing fails, because no test reads prose, so the doc stays wrong until a person hits it.
|
|
11
|
+
|
|
12
|
+
Three failures belong to the sync itself rather than to the drift. A session that syncs by rewriting whole files churns sections the change never reached, which costs the reviewer the ability to tell the sync from the feature. A doc edited earlier in the same session reads as current while a later change leaves one of its sections stale, so file-level classification passes where section-level would not. And a hardcoded doc list never checks the file someone added after the list was written.
|
|
13
|
+
|
|
14
|
+
The quiet one is the baseline. A diff resolved against a bare local ref equals HEAD on `main` and on a branch before its first commit, so every committed change drops out of the set. The skill then reports nothing to sync, which reads as a clean result rather than as an admission that it could not see the work.
|
|
15
|
+
|
|
16
|
+
## Must
|
|
17
|
+
|
|
18
|
+
- Resolve one merge base, prefer the remote ref over the local one, and reuse it everywhere the skill reads the diff
|
|
19
|
+
- Say so in the output when the baseline degrades, rather than reporting a clean pass off a set it could not build
|
|
20
|
+
- Discover the doc set by glob at run time
|
|
21
|
+
- Classify and rewrite at section level, so a partly stale file is partly rewritten
|
|
22
|
+
- Write immediately after the preview, since the tool permission dialog is the confirmation gate
|
|
23
|
+
|
|
24
|
+
## Must not
|
|
25
|
+
|
|
26
|
+
- Touch a section the change does not reach
|
|
27
|
+
- Rewrite a doc to match the diff when the doc records an intent the diff departed from. That is a finding rather than a sync.
|
|
28
|
+
|
|
29
|
+
## Guards
|
|
30
|
+
|
|
31
|
+
- No committed change and no working-tree change stops the skill before it reads any doc
|
|
32
|
+
|
|
33
|
+
## Out of scope
|
|
34
|
+
|
|
35
|
+
- `.claude/` planning docs, tasks, plans, and context entries: `claude-docs`, which runs immediately before this skill in the ship chain and resolves the same baseline. The split is by audience, so a file's location decides which skill owns it rather than its subject.
|
|
36
|
+
- `CLAUDE.md` and the installed seed docs: `claude-seed-sync`, which reconciles them per section against the toolkit source
|
|
37
|
+
- Changelog entries, which release tooling generates from commit messages
|
|
38
|
+
- Whether the prose conforms to its standards. `claude-standards-audit` reports violations and fixes none, and this skill writes prose it does not audit.
|
package/docs/agents.md
CHANGED
|
@@ -399,6 +399,8 @@ The table check reports a catalog that grows a row per shipped thing, not a tabl
|
|
|
399
399
|
|
|
400
400
|
The provenance check reports the markers narrating how a domain reached its shape rather than describing what it is: a date, a change number, or a release label. The standard admits a rejected alternative and the reasoning that killed it while refusing the provenance attached to it, so a marker names a line to read rather than a line to delete. Findings group by entry and sort left to right within a line, since what a reader acts on is which file to open. Fenced blocks are excluded, which keeps a pinned version in an install command from reading as a claim the entry makes. Frontmatter is excluded with them, since the content checks read the body alone, and that is what keeps a diagram entry's dated `verified` stamp a record of its last check rather than a marker to settle. Length is the exception, counting the whole file, so a reader applying the 150-rendered-line checkpoint against the body alone lands a few lines under what the tool reports.
|
|
401
401
|
|
|
402
|
+
This one check covers `.claude/context/` alone, while length, depth, and the table finding reach every audited folder. The rule is stated in `.claude/standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere. The split is between kinds of rule rather than kinds of folder: a threshold on how far a reader travels generalizes across entry types, while a rule about what an entry may say is the jurisdiction a scope statement exists to settle. The scoping key is the folder an entry was audited under, so `--folder` still reaches a folder the default list does not carry, and a domain split into `context/<sub-area>/` is governed as `context`. Every run states the reach, including a run where no audited folder is the governed one. The JSON record carries it as `checkpoints.provenanceFolder` and a per-folder `governsContent`.
|
|
403
|
+
|
|
402
404
|
Index drift compares an index against its siblings in both directions. An entry the index does not link is invisible to a session choosing what to open, and a linked name resolving to nothing sends one to a path that opens nothing.
|
|
403
405
|
|
|
404
406
|
### The citation gate
|
|
@@ -413,15 +415,15 @@ What remains is a sentence naming a hypothetical entry to show the shape of a na
|
|
|
413
415
|
|
|
414
416
|
Use these to discover what's available instead of hardcoding names.
|
|
415
417
|
|
|
416
|
-
| Command | Returns
|
|
417
|
-
| -------------------------------- |
|
|
418
|
-
| `aitk tooling list --json` | Stacks, extends chain, dep and script counts
|
|
419
|
-
| `aitk snippets list --json` | Presets and categories with their slugs
|
|
420
|
-
| `aitk standards list --json` | Standards docs and the paths each governs
|
|
421
|
-
| `aitk gov list --json` | Governance stacks and rule sets
|
|
422
|
-
| `aitk claude seeds list --json` | Seed doc sources with content
|
|
423
|
-
| `aitk claude skills list --json` | Plugin skills
|
|
424
|
-
| `aitk docs list --json` | Consumer docs plus per-domain context
|
|
418
|
+
| Command | Returns |
|
|
419
|
+
| -------------------------------- | --------------------------------------------- |
|
|
420
|
+
| `aitk tooling list --json` | Stacks, extends chain, dep and script counts |
|
|
421
|
+
| `aitk snippets list --json` | Presets and categories with their slugs |
|
|
422
|
+
| `aitk standards list --json` | Standards docs and the paths each governs |
|
|
423
|
+
| `aitk gov list --json` | Governance stacks and rule sets |
|
|
424
|
+
| `aitk claude seeds list --json` | Seed doc sources with content |
|
|
425
|
+
| `aitk claude skills list --json` | Plugin skills, descriptions, requirement flag |
|
|
426
|
+
| `aitk docs list --json` | Consumer docs plus per-domain context |
|
|
425
427
|
|
|
426
428
|
Every catalog serializes through `JSON.stringify`, so a name carrying a quote
|
|
427
429
|
emits valid JSON. `aitk tooling list` and `aitk snippets list` previously built
|
|
@@ -448,6 +450,12 @@ or unparseable returns an empty description rather than failing the listing, so
|
|
|
448
450
|
one malformed file cannot hide the rest of the catalog. `--names` emits skill
|
|
449
451
|
names one per line.
|
|
450
452
|
|
|
453
|
+
Each entry also carries `requirement`, whether the folder holds a sibling
|
|
454
|
+
`REQUIREMENT.md`. Coverage of that file is selective by design, so a `false` is
|
|
455
|
+
not a gap to close and the flag answers which skills carry one without a caller
|
|
456
|
+
listing the directory itself. It says nothing about why, which is a judgment the
|
|
457
|
+
toolkit records against its own corpus rather than in the catalog.
|
|
458
|
+
|
|
451
459
|
## Non-interactive examples
|
|
452
460
|
|
|
453
461
|
```bash
|
package/docs/ai-workflow.md
CHANGED
|
@@ -68,7 +68,7 @@ When features are independent, run them in parallel instead of sequentially. Use
|
|
|
68
68
|
- Ship each worktree separately with `aitk:git-ship`
|
|
69
69
|
- For full autonomy per worktree, invoke `aitk:claude-autoship` instead of the manual chain. Approve the plan, walk away, come back to draft PRs.
|
|
70
70
|
|
|
71
|
-
To run several worktrees as a coordinated flow rather than ad hoc, assert the orchestrator role in one warm session with `aitk:claude-orchestrate`. It owns the roadmap
|
|
71
|
+
To run several worktrees as a coordinated flow rather than ad hoc, assert the orchestrator role in one warm session with `aitk:claude-orchestrate`. It owns the roadmap, handing a needed draft or resequence to a worker that runs `aitk:claude-roadmap` in its branch, plans each feature, refills the ready queue so a free worker never waits, and reviews each worker's PR with `aitk:claude-pr-review`, while workers address the posted findings with `aitk:claude-address-review`. The human launches workers and merges. See [operating model](operating-model.md) for the full loop.
|
|
72
72
|
|
|
73
73
|
Roadmap ownership holds while a scope exists to sequence. Once the MVP list in `.claude/REQUIREMENTS.md` has shipped, later work arrives as discrete items and the orchestrator reads `.claude/tasks/priority.md` for execution order instead.
|
|
74
74
|
|
|
@@ -131,11 +131,11 @@ Before the first feature session on a UI-heavy project, pick a design tier. The
|
|
|
131
131
|
| `aitk:claude-groundwork` | Before a plan is warranted, measure an unknown in a scratch folder under `.claude/.tmp/groundwork/` |
|
|
132
132
|
| `aitk:claude-feature` | Before implementation, scan for conflicts and ambiguities |
|
|
133
133
|
| `aitk:claude-roadmap` | Sequence MVP scope into ordered versions in `.claude/ROADMAP.md` |
|
|
134
|
-
| `aitk:claude-orchestrate` | Assert the orchestrator role, refill the ready queue, and dispatch the
|
|
134
|
+
| `aitk:claude-orchestrate` | Assert the orchestrator role, refill the ready queue, and dispatch the feature, review, and worktree skills |
|
|
135
135
|
| `aitk:claude-diagram` | Draft per-kind mermaid entries under `.claude/diagrams/` from architecture and code, then verify each rendered image |
|
|
136
136
|
| `aitk:claude-design-extract` | Draft `.claude/DESIGN.md`, sourcing tokens from existing UI code or proposing them from requirements on day one |
|
|
137
137
|
| `aitk:claude-review` | In a fresh session, review all changes since main |
|
|
138
|
-
| `aitk:claude-pr-review` | Review an open PR from an independent session, then
|
|
138
|
+
| `aitk:claude-pr-review` | Review an open PR from an independent session, then re-review the commits added since until nothing is open |
|
|
139
139
|
| `aitk:claude-address-review` | Address PR findings and CI status, refresh stale docs, then push a follow-up |
|
|
140
140
|
| `aitk:claude-tasks` | Add a task to `.claude/tasks/` or archive a shipped one out of the folder |
|
|
141
141
|
| `aitk:claude-docs` | When decisions diverged from plan, update `.claude/` docs |
|
package/docs/operating-model.md
CHANGED
|
@@ -29,12 +29,12 @@ dispatch, not logic.
|
|
|
29
29
|
|
|
30
30
|
One feature travels this path end to end.
|
|
31
31
|
|
|
32
|
-
1. Orchestrator
|
|
32
|
+
1. Orchestrator captures a needed roadmap draft or resequence in the plan or a task file, naming `.claude/REQUIREMENTS.md` as the scope source, and a worker runs `claude-roadmap` in its branch so the tracked edit ships in a PR. The skill stops when that file carries a later scope section, since the MVP list it sequences has shipped and a fresh requirements pass owns what follows.
|
|
33
33
|
2. Orchestrator plans the next feature with `claude-feature`, writing a plan to `.claude/plans/`. Planning stays in the warm session because good planning is cross-feature. It needs the contract other features consume and the shared wiring seam. A cold session would re-derive or guess.
|
|
34
34
|
3. The human opens a worker worktree with `claude-worktree` and runs `claude-autoship` against the plan. The worker builds, self-checks, opens a PR, and stops at the PR boundary.
|
|
35
35
|
4. Orchestrator reviews the PR with `claude-pr-review` and posts findings to it.
|
|
36
36
|
5. Worker addresses the findings with `claude-address-review`, then pushes a follow-up.
|
|
37
|
-
6. Orchestrator closes the review out with `claude-pr-review` again. The second pass reads only the commits the follow-up added and posts under `## Review closed
|
|
37
|
+
6. Orchestrator closes the review out with `claude-pr-review` again. The second pass reads only the commits the follow-up added, and posts under `## Review closed` when it finds nothing open or under `## Review` when it does, so a reader learns the state from the heading. Repeat from step 5 until the review closes.
|
|
38
38
|
7. The human reads the result and merges. The orchestrator tells any trailing worker to rebase when its branch shares a seam with the merged one.
|
|
39
39
|
|
|
40
40
|
There is no loop construct here. Each worker is a single build that halts at the
|
|
@@ -58,11 +58,12 @@ merge is the final gate. No layer repeats another.
|
|
|
58
58
|
|
|
59
59
|
Review travels on the PR, not through chat. `claude-pr-review` posts findings to
|
|
60
60
|
the PR. `claude-address-review` reads them back, fixes each, replies or resolves
|
|
61
|
-
the threads, and pushes a follow-up. `claude-pr-review` then runs
|
|
62
|
-
|
|
61
|
+
the threads, and pushes a follow-up. `claude-pr-review` then runs again, reading
|
|
62
|
+
only what the follow-up added.
|
|
63
63
|
|
|
64
|
-
The
|
|
65
|
-
a
|
|
64
|
+
The heading carries the state rather than the pass number. A pass with a finding
|
|
65
|
+
takes `## Review` and a pass with none takes `## Review closed`, so a thread can
|
|
66
|
+
be scanned for what is still open without opening a comment. The feedback
|
|
66
67
|
becomes a durable artifact both sessions read, survives a session ending, and
|
|
67
68
|
anchors to the change. That removes the copy-paste that otherwise routes review
|
|
68
69
|
through the human between two sessions.
|
|
@@ -10,6 +10,7 @@ paths:
|
|
|
10
10
|
|
|
11
11
|
- Before non-trivial work in a domain, read its `.claude/context/<domain>.md` entry. Use `.claude/context/index.md` to find it.
|
|
12
12
|
- Leave the entry conforming when work in its domain changes what it describes.
|
|
13
|
+
- Rewrite the decision a change supersedes rather than appending a second one narrating the transition.
|
|
13
14
|
|
|
14
15
|
## Authority
|
|
15
16
|
|
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ const FRONTMATTER = /^---\n([\s\S]*?)\n---/
|
|
|
6
6
|
export interface SkillListing {
|
|
7
7
|
readonly name: string
|
|
8
8
|
readonly description: string
|
|
9
|
+
readonly requirement: boolean
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -15,6 +16,10 @@ export interface SkillListing {
|
|
|
15
16
|
*
|
|
16
17
|
* The folder name wins over the frontmatter `name` when they disagree, because
|
|
17
18
|
* Claude Code invokes a skill by its directory.
|
|
19
|
+
*
|
|
20
|
+
* `requirement` reports whether the folder carries `REQUIREMENT.md`. Coverage is
|
|
21
|
+
* selective by design, so a false is not a gap to close and this field carries no
|
|
22
|
+
* reason for one. The toolkit records those separately from the catalog.
|
|
18
23
|
*/
|
|
19
24
|
export function listSkills(root: string): SkillListing[] {
|
|
20
25
|
const skillsRoot = join(root, 'claude', 'skills')
|
|
@@ -30,6 +35,7 @@ export function listSkills(root: string): SkillListing[] {
|
|
|
30
35
|
return paths.map((path) => ({
|
|
31
36
|
name: dirname(path),
|
|
32
37
|
description: readDescription(join(skillsRoot, path)),
|
|
38
|
+
requirement: existsSync(join(skillsRoot, dirname(path), 'REQUIREMENT.md')),
|
|
33
39
|
}))
|
|
34
40
|
}
|
|
35
41
|
|
package/src/commands/context.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { resolve } from 'node:path'
|
|
|
2
2
|
import type { Command } from 'commander'
|
|
3
3
|
import {
|
|
4
4
|
type EntryReport,
|
|
5
|
+
governsContent,
|
|
5
6
|
LENGTH_CHECKPOINT,
|
|
6
7
|
measureFolders,
|
|
7
8
|
PEER_BULLET_CHECKPOINT,
|
|
9
|
+
PROVENANCE_FOLDER,
|
|
8
10
|
RENDER_WIDTH,
|
|
9
11
|
RUN_CHECKPOINT,
|
|
10
12
|
} from '@/context/audit'
|
|
@@ -90,8 +92,8 @@ function parseFolders(list: string | undefined): string[] | string {
|
|
|
90
92
|
|
|
91
93
|
if (names.length === 0) return 'Empty --folder list. Pass at least one name.'
|
|
92
94
|
|
|
93
|
-
// `..` would resolve the
|
|
94
|
-
//
|
|
95
|
+
// `..` would resolve the audited folder above `.claude/`, taking the scan
|
|
96
|
+
// and the citation pattern outside the tree the audit describes.
|
|
95
97
|
const invalid = names.filter((name) => !FOLDER_NAME.test(name))
|
|
96
98
|
if (invalid.length > 0) {
|
|
97
99
|
return `--folder takes folder names under .claude/, not paths: ${invalid.join(', ')}`
|
|
@@ -138,7 +140,7 @@ async function runAudit(
|
|
|
138
140
|
reportLength(entries)
|
|
139
141
|
reportDepth(entries)
|
|
140
142
|
reportTables(entries)
|
|
141
|
-
reportProvenance(entries)
|
|
143
|
+
reportProvenance(entries, folders)
|
|
142
144
|
reportDrift(drift)
|
|
143
145
|
outro()
|
|
144
146
|
}
|
|
@@ -150,6 +152,7 @@ async function runAudit(
|
|
|
150
152
|
folders: folders.map((folder) => ({
|
|
151
153
|
path: folder.rel,
|
|
152
154
|
entries: folder.entries.length,
|
|
155
|
+
governsContent: governsContent(folder),
|
|
153
156
|
})),
|
|
154
157
|
citations: {
|
|
155
158
|
scanned: citations.scanned,
|
|
@@ -164,6 +167,7 @@ async function runAudit(
|
|
|
164
167
|
runCountsBlankLines: true,
|
|
165
168
|
renderWidth: RENDER_WIDTH,
|
|
166
169
|
peerBullet: PEER_BULLET_CHECKPOINT,
|
|
170
|
+
provenanceFolder: PROVENANCE_FOLDER,
|
|
167
171
|
},
|
|
168
172
|
})}\n`,
|
|
169
173
|
)
|
|
@@ -332,9 +336,28 @@ function reportTables(entries: readonly EntryReport[]): void {
|
|
|
332
336
|
* time, and a flat list of those buries the entries holding one. What a reader
|
|
333
337
|
* acts on is which file to open, so the count sits beside the name and the
|
|
334
338
|
* lines follow it.
|
|
339
|
+
*
|
|
340
|
+
* The reach is stated on every run, including the run where nothing is in
|
|
341
|
+
* scope. A check that covered three folders and now covers one reads as quietly
|
|
342
|
+
* missing things unless the report says which folder it measured.
|
|
335
343
|
*/
|
|
336
|
-
function reportProvenance(
|
|
344
|
+
function reportProvenance(
|
|
345
|
+
entries: readonly EntryReport[],
|
|
346
|
+
folders: readonly AuditedFolder[],
|
|
347
|
+
): void {
|
|
337
348
|
logStep('Provenance')
|
|
349
|
+
|
|
350
|
+
const governed = folders.filter(governsContent)
|
|
351
|
+
if (governed.length === 0) {
|
|
352
|
+
logInfo(
|
|
353
|
+
`Out of scope. The rule is stated in the standard governing .claude/${PROVENANCE_FOLDER}/, and no audited folder is that one.`,
|
|
354
|
+
)
|
|
355
|
+
return
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
logInfo(
|
|
359
|
+
`Covers .claude/${PROVENANCE_FOLDER}/ alone, whose standard carries the rule. The sibling standards do not restate it.`,
|
|
360
|
+
)
|
|
338
361
|
logInfo('Fenced blocks are excluded. A marker is a judgment, never a defect.')
|
|
339
362
|
|
|
340
363
|
const carrying = entries
|
package/src/context/audit.ts
CHANGED
|
@@ -61,6 +61,25 @@ const PROVENANCE: readonly { kind: ProvenanceKind; pattern: RegExp }[] = [
|
|
|
61
61
|
{ kind: 'release', pattern: /\bv\d+\.\d+(?:\.\d+)?\b/g },
|
|
62
62
|
]
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* The folder whose standard carries the exclusion above.
|
|
66
|
+
*
|
|
67
|
+
* `standards/context.md` opens its scope by handing diagrams and wireframes to
|
|
68
|
+
* `diagrams.md` and `wireframes.md`, so a marker reported in either would cite
|
|
69
|
+
* a rule that entry's own standard routes elsewhere. The length, depth, and
|
|
70
|
+
* table checkpoints are quoted from the same standard and keep reaching every
|
|
71
|
+
* audited folder, because a threshold on how far a reader travels generalizes
|
|
72
|
+
* across entry types while a rule about what an entry may say does not.
|
|
73
|
+
*
|
|
74
|
+
* Restating the exclusion in the sibling standards was the alternative. It
|
|
75
|
+
* duplicates one knowledge item across three surfaces, which the root
|
|
76
|
+
* instruction file forbids, and pointing is not available because the surface
|
|
77
|
+
* they would point at is the one disclaiming them. Should a diagram entry ever
|
|
78
|
+
* accumulate narration, the escalation is an attribute standard owning the rule
|
|
79
|
+
* across document types, not restoring this reach without an owner.
|
|
80
|
+
*/
|
|
81
|
+
export const PROVENANCE_FOLDER = 'context'
|
|
82
|
+
|
|
64
83
|
export type ProvenanceKind = 'date' | 'change' | 'release'
|
|
65
84
|
|
|
66
85
|
export interface TableFinding {
|
|
@@ -95,6 +114,7 @@ export interface EntryReport {
|
|
|
95
114
|
/** First line of the longest run, or 0 when the entry has no run at all. */
|
|
96
115
|
readonly longestRunLine: number
|
|
97
116
|
readonly catalogTables: readonly TableFinding[]
|
|
117
|
+
/** Empty for an entry no standard bans a change narrative in. */
|
|
98
118
|
readonly provenance: readonly ProvenanceFinding[]
|
|
99
119
|
}
|
|
100
120
|
|
|
@@ -320,7 +340,18 @@ function provenance(lines: readonly BodyLine[]): ProvenanceFinding[] {
|
|
|
320
340
|
.map((each) => each.finding)
|
|
321
341
|
}
|
|
322
342
|
|
|
323
|
-
|
|
343
|
+
/**
|
|
344
|
+
* Measures one entry, scanning for provenance only when a standard claims it.
|
|
345
|
+
*
|
|
346
|
+
* The caller passes jurisdiction rather than deriving it from `rel`, because a
|
|
347
|
+
* path prefix hardcodes what `--folder` exists to override and misses a domain
|
|
348
|
+
* split into `context/<sub-area>/`.
|
|
349
|
+
*/
|
|
350
|
+
export function measureEntry(
|
|
351
|
+
rel: string,
|
|
352
|
+
source: string,
|
|
353
|
+
governsContent = true,
|
|
354
|
+
): EntryReport {
|
|
324
355
|
const lines = bodyLines(source)
|
|
325
356
|
const run = longestRun(lines)
|
|
326
357
|
|
|
@@ -333,7 +364,7 @@ export function measureEntry(rel: string, source: string): EntryReport {
|
|
|
333
364
|
longestRun: run.length,
|
|
334
365
|
longestRunLine: run.line,
|
|
335
366
|
catalogTables: catalogTables(lines),
|
|
336
|
-
provenance: provenance(lines),
|
|
367
|
+
provenance: governsContent ? provenance(lines) : [],
|
|
337
368
|
}
|
|
338
369
|
}
|
|
339
370
|
|
|
@@ -341,6 +372,9 @@ export function measureEntry(rel: string, source: string): EntryReport {
|
|
|
341
372
|
* Measures every entry in the audited folders. A generated `index.md` is not
|
|
342
373
|
* among them, since its body is rewritten on every regen and no checkpoint
|
|
343
374
|
* describes a catalog.
|
|
375
|
+
*
|
|
376
|
+
* Jurisdiction is applied here rather than at the report, so the JSON record
|
|
377
|
+
* and the printed run agree on which entries a content rule reached.
|
|
344
378
|
*/
|
|
345
379
|
export async function measureFolders(
|
|
346
380
|
root: string,
|
|
@@ -351,10 +385,19 @@ export async function measureFolders(
|
|
|
351
385
|
for (const folder of folders) {
|
|
352
386
|
for (const path of folder.entries) {
|
|
353
387
|
reports.push(
|
|
354
|
-
measureEntry(
|
|
388
|
+
measureEntry(
|
|
389
|
+
relative(root, path),
|
|
390
|
+
await readFile(path, 'utf8'),
|
|
391
|
+
governsContent(folder),
|
|
392
|
+
),
|
|
355
393
|
)
|
|
356
394
|
}
|
|
357
395
|
}
|
|
358
396
|
|
|
359
397
|
return reports
|
|
360
398
|
}
|
|
399
|
+
|
|
400
|
+
/** Reports whether the folder's standard is the one carrying the exclusion. */
|
|
401
|
+
export function governsContent(folder: AuditedFolder): boolean {
|
|
402
|
+
return folder.name === PROVENANCE_FOLDER
|
|
403
|
+
}
|
package/src/context/folders.ts
CHANGED
|
@@ -18,6 +18,13 @@ export const DEFAULT_FOLDERS: readonly string[] = [
|
|
|
18
18
|
]
|
|
19
19
|
|
|
20
20
|
export interface AuditedFolder {
|
|
21
|
+
/**
|
|
22
|
+
* The requested folder name this was resolved under, which is what says
|
|
23
|
+
* which standard governs the entries. A nested split folder carries the name
|
|
24
|
+
* of the folder it sits beneath rather than its own, so
|
|
25
|
+
* `.claude/context/claude-plugin` is governed as `context`.
|
|
26
|
+
*/
|
|
27
|
+
readonly name: string
|
|
21
28
|
/** Repo-relative folder path, used verbatim in every report line. */
|
|
22
29
|
readonly rel: string
|
|
23
30
|
readonly indexPath: string
|
|
@@ -35,7 +42,7 @@ export interface AuditedFolder {
|
|
|
35
42
|
* here for the sole reason that this repository has no wireframes.
|
|
36
43
|
*/
|
|
37
44
|
export function presentNames(folders: readonly AuditedFolder[]): string[] {
|
|
38
|
-
return [...new Set(folders.map((folder) => folder.
|
|
45
|
+
return [...new Set(folders.map((folder) => folder.name))]
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
async function readEntries(dir: string): Promise<string[]> {
|
|
@@ -80,6 +87,7 @@ export async function resolveFolders(
|
|
|
80
87
|
|
|
81
88
|
for (const each of [...new Set(dirs)].sort()) {
|
|
82
89
|
folders.push({
|
|
90
|
+
name,
|
|
83
91
|
rel: relative(root, each),
|
|
84
92
|
indexPath: `${each}/${INDEX_FILE}`,
|
|
85
93
|
entries: await readEntries(each),
|
package/standards/context.md
CHANGED
|
@@ -105,6 +105,7 @@ Only the `development` entry carries this section. It is not a general-purpose h
|
|
|
105
105
|
- Both checkpoints count rendered lines, so wrap each source line at 80 columns and sum the heights. Source lines undercount an entry authored one line per bullet, where a block of fifteen paragraph-bullets occupies fifteen lines and renders past sixty. Counting the two checkpoints in different units would put a file measured one way beside a run measured another.
|
|
106
106
|
- Exempt a block whose lines are all list items at one level averaging under roughly 130 characters. A flat list of short peers is already navigable, and a subheading dropped into it splits a set that belongs together. Bullet count says nothing on its own, since a catalog of one-liners and a stack of paragraphs reach the same count and read nothing alike, so weight is what decides. Mixing prose with the list, or nesting levels inside it, ends the exemption at any weight.
|
|
107
107
|
- Never cut a `## Decisions` or `## Gotchas` entry to shorten a file. Cut a `## Layout` or `## CLI` section instead.
|
|
108
|
+
- Retire a decision or gotcha once its subject is gone, rewriting the bullet to state the current design rather than leaving the narration of what it replaced beside it. A rejected alternative is not a retired one, so what was tried and why it lost stays whatever its age. The rule above protects content whose subject is live, and this one releases content whose subject is not.
|
|
108
109
|
- Split into a folder (`.claude/context/<domain>/<sub-area>.md`) when a domain has three or more sub-areas that do not fit cleanly in one file. That split is the natural ceiling.
|
|
109
110
|
- Keep a split domain's `index.md` generated. The catalog body is rewritten on every regen, so the domain's own overview and layout belong in a sibling file rather than in it, and the `subtitle` is what names the file to start with.
|
|
110
111
|
- Author a catalog that grows a row per shipped thing as a bullet list, never a markdown table. A table pads its columns to a shared width, so one row outgrowing its column reflows every row and turns a one-line edit into a whole-file rewrite that conflicts with any sibling branch. This is what forced the split above.
|
package/standards/tasks.md
CHANGED
|
@@ -48,7 +48,33 @@ Readiness is three groups under fixed headings, `## Run now`, `## Up next`, and
|
|
|
48
48
|
- `## Up next`: a written plan exists, and the task either collides with something running or waits on another task to land. The blocker column names which.
|
|
49
49
|
- `## Needs a plan`: everything else. The task has no plan, or the plan it carries no longer describes the work.
|
|
50
50
|
|
|
51
|
-
Each group fixes its own columns, which follow from the test above it rather than from preference. `## Run now`
|
|
51
|
+
Each group fixes its own columns, which follow from the test above it rather than from preference. Neither half of the `## Run now` test is checkable without the file set and the plan sitting beside the task. The blocker column under `## Up next` names whether a collision or a dependency holds the row. `## Needs a plan` states no file set at all, because a task with no plan has no bounded one to state. A group with no rows keeps its heading and its header row.
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
---
|
|
55
|
+
title: Priority
|
|
56
|
+
description: One line on what the board covers
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
# Priority
|
|
60
|
+
|
|
61
|
+
## Run now
|
|
62
|
+
|
|
63
|
+
| Task | Touches | Plan |
|
|
64
|
+
| ------------------------------- | ----------------------- | ------------------------------------ |
|
|
65
|
+
| [vXX.Y <slug>](vXX.Y-<slug>.md) | <what the task touches> | [<slug>](../plans/feature-<slug>.md) |
|
|
66
|
+
|
|
67
|
+
## Up next
|
|
68
|
+
|
|
69
|
+
| Task | Touches | Waiting on |
|
|
70
|
+
| ---- | ------- | ---------- |
|
|
71
|
+
|
|
72
|
+
## Needs a plan
|
|
73
|
+
|
|
74
|
+
| Task | Waiting on |
|
|
75
|
+
| ------------------------------- | --------------------------------------- |
|
|
76
|
+
| [vXX.Y <slug>](vXX.Y-<slug>.md) | <the collision or the task it waits on> |
|
|
77
|
+
```
|
|
52
78
|
|
|
53
79
|
The tests live here so the board does not carry them. Writing them as a sentence under each heading produces the paragraph the rule above deletes, and a criterion with no home gets restated from memory every time the board is touched.
|
|
54
80
|
|