@joshuafolkken/kit 1.887.0 → 1.921.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/skills/workflow-commands/fullrun-steps.md +4 -2
- package/.claude/skills/workflow-commands/halfrun.md +3 -1
- package/.claude/skills/workflow-commands/kickoff.md +5 -3
- package/.claude/skills/workflow-commands/observation-filing.md +3 -1
- package/.claude/skills/workflow-commands/prerequisite.md +3 -1
- package/.claude/skills/workflow-commands/target-repository.md +1 -1
- package/.github/pull_request_template.md +12 -0
- package/.github/release.yml +3 -0
- package/.github/workflows/ci.yml +8 -0
- package/.github/workflows/production.yml +10 -1
- package/.github/workflows/publish.yml +72 -2
- package/CLAUDE.md +2 -0
- package/dist/CLAUDE.md +2 -0
- package/dist/CLAUDE.static.md +8 -0
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-36UE53LS.js → chunk-3HZ5MJIW.js} +2 -2
- package/dist/hooks/chunk-3V37IID6.js +82 -0
- package/dist/hooks/{chunk-FRJKVSK3.js → chunk-77RLKZ5V.js} +2 -2
- package/dist/hooks/{chunk-VGYSA2NT.js → chunk-LC765SUA.js} +16 -2
- package/dist/hooks/{chunk-ZBK4XRAS.js → chunk-NWD47MW3.js} +3 -3
- package/dist/hooks/{chunk-4OXFU3MK.js → chunk-O2FBZPSW.js} +619 -156
- package/dist/hooks/{chunk-6MQCXEEA.js → chunk-OLTAGGHH.js} +25 -88
- package/dist/hooks/{chunk-FNFOLFFV.js → chunk-OYU6KPRA.js} +1 -1
- package/dist/hooks/{chunk-PRDCNGA6.js → chunk-UANRLZV7.js} +4 -4
- package/dist/hooks/{chunk-264QY6KS.js → chunk-UULARQ5Q.js} +23 -1
- package/dist/hooks/{chunk-Y5OYCU2F.js → chunk-XMR3BS35.js} +3 -3
- package/dist/hooks/codex-hook-adapter.js +11 -10
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +3 -2
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +10 -9
- package/dist/hooks/stop-guard.js +3 -3
- package/dist/josh.js +155 -12
- package/package.json +68 -17
- package/prettier/index.js +3 -8
- package/prettier/static.d.ts +3 -0
- package/prettier/static.js +10 -0
- package/prompts/collaboration-workflow/issue-template.md +11 -4
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +2 -2
- package/prompts/review.md +2 -2
- package/prompts/testing-guide.md +1 -0
- package/scripts/build/build-claude-md.ts +6 -1
- package/scripts/ci/pr-classification.ts +114 -0
- package/scripts/document/document-byte-budget.ts +3 -2
- package/scripts/gate/gate-report.ts +2 -0
- package/scripts/gate/gate-steps.ts +50 -0
- package/scripts/gate/project-checks.ts +121 -0
- package/scripts/gate/verification-gate.ts +14 -43
- package/scripts/git/git-common-directory.ts +9 -1
- package/scripts/git/git-gh-pr-rollup.ts +29 -1
- package/scripts/git/git-gh-pr.ts +61 -1
- package/scripts/git/git-pr.ts +62 -13
- package/scripts/git/issue-labels.ts +9 -0
- package/scripts/init/distributed-paths.ts +9 -5
- package/scripts/init/hook-command-bootstrap.ts +40 -8
- package/scripts/init/hook-command-rewrite.ts +7 -3
- package/scripts/init/init-actions.ts +94 -7
- package/scripts/init/init-ai-copy.ts +104 -19
- package/scripts/init/init-static.ts +52 -0
- package/scripts/init/init.ts +97 -30
- package/scripts/init/project-profile-cli.ts +14 -0
- package/scripts/init/project-profile.ts +149 -0
- package/scripts/init/start.ts +30 -0
- package/scripts/issue/issue-bug-label.ts +13 -0
- package/scripts/issue/issue-classification.ts +74 -0
- package/scripts/issue/issue-lint-cli.ts +10 -3
- package/scripts/issue/markdown-section.ts +38 -4
- package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +27 -1
- package/scripts/josh/josh-command-map.ts +3 -0
- package/scripts/josh/josh-commands-development.ts +6 -0
- package/scripts/josh/josh-commands-project.ts +14 -1
- package/scripts/josh/josh-logic.ts +13 -0
- package/scripts/josh/run-github-prerequisite.ts +32 -0
- package/scripts/lane/lane-await.ts +8 -1
- package/scripts/lane/openai-lane-ship.ts +30 -0
- package/scripts/lane/openai-lane-supervisor.ts +35 -8
- package/scripts/lane/openai-review-broker.ts +260 -0
- package/scripts/lint/cspell-cached.ts +21 -0
- package/scripts/lint/lint-parallel.ts +44 -1
- package/scripts/observations/observations-flush.ts +1 -1
- package/scripts/package/production-dependency-graph.ts +68 -0
- package/scripts/package/verify-optional-eslint-install.ts +62 -0
- package/scripts/release/github-release-cli.ts +11 -0
- package/scripts/release/github-release.ts +220 -0
- package/scripts/release/publish-tag-cli.ts +8 -0
- package/scripts/release/publish-tag.ts +11 -0
- package/scripts/release/release-publish.ts +7 -2
- package/scripts/rules/delivered-rules.ts +2 -0
- package/scripts/rules/issue-bug-label.ts +85 -0
- package/scripts/rules/issue-filing-args.ts +50 -0
- package/scripts/run/run-merge-cli.ts +19 -0
- package/scripts/run/run-merge.ts +9 -1
- package/scripts/run/run-ship-cli.ts +20 -0
- package/scripts/run/run-ship-detach.ts +180 -14
- package/scripts/run/run-ship-review-steps.ts +45 -25
- package/scripts/run/run-wake-session.ts +3 -1
- package/scripts/test/pilot-files.ts +0 -2
- package/scripts/test/skip-marker.ts +3 -0
- package/scripts/test/test-declared-changed.ts +2 -1
- package/scripts/test/test-declared-logic.ts +15 -10
- package/scripts/test/test-declared.ts +20 -8
- package/scripts/test/test-red-logic.ts +3 -3
- package/scripts/test/test-unit-guard.ts +24 -12
- package/templates/CLAUDE.static.md +8 -0
- package/templates/cursorrules.static +1 -0
- package/templates/prettierignore.static +12 -0
- package/templates/workflows/ci.yml +5 -0
|
@@ -7,6 +7,8 @@ the run is at, and the sections below carry that step in full.
|
|
|
7
7
|
|
|
8
8
|
## The `fullrun #N` step list
|
|
9
9
|
|
|
10
|
+
Use `pnpm josh issue:lint` `labels:`; see `prompts/collaboration-workflow/issue-template.md`.
|
|
11
|
+
|
|
10
12
|
**Add `in-progress` the moment `run:hold` answered `hold`** (create if missing:
|
|
11
13
|
`gh api repos/{owner}/{repo}/labels -f name=in-progress -f color=0075ca -f description="Work is
|
|
12
14
|
actively in progress" --silent 2>/dev/null || true`, then `gh api
|
|
@@ -49,8 +51,8 @@ completion notification, then merges; if blockers are found it exits non-zero
|
|
|
49
51
|
`kickoff new` + `fullrun #N` in one run. Steps: (1) Derive an English title, or use the provided one.
|
|
50
52
|
**(1a) Run `pnpm josh issue:scout "<title>" [--body "<summary>"]` before creating the Issue** — a
|
|
51
53
|
candidate that covers the same work stops the run rather than filing a second Issue (`SKILL.md` → §2e).
|
|
52
|
-
(2) Create Issue: `gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:<n>' -
|
|
53
|
-
body
|
|
54
|
+
(2) Create Issue: `gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:<n>' -F
|
|
55
|
+
body=@<body-file>` (per `prompts/collaboration-workflow/issue-template.md`). Capture `<N>`. (3) Add
|
|
54
56
|
`in-progress` (as above). (4) Post the agreed plan in the session language: fill the body if blank,
|
|
55
57
|
otherwise add a comment. (5) If the working tree already has staged or modified files,
|
|
56
58
|
`git stash push -m "fullrun new: pre-existing changes"` first. (6) `git switch main && git pull`. (7)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# `halfrun` — the manifest (implement + verify, stop before commit)
|
|
2
2
|
|
|
3
|
+
When this run files a new Issue, run `pnpm josh issue:lint <body-file>` and apply every label in its `labels:` answer at creation; `prompts/collaboration-workflow/issue-template.md` is the single source for this classification. Keep the existing `depth` and `route` labels.
|
|
4
|
+
|
|
3
5
|
`halfrun` sits between `kickoff` (plan only) and `fullrun` (full execution with auto-merge). It
|
|
4
6
|
implements the change and runs the full verification gate, then **stops before commit** — nothing is
|
|
5
7
|
committed, pushed, or opened as a PR — so the user manually verifies the change (typically by exercising
|
|
@@ -52,7 +54,7 @@ back with fixes, treat each as a new round: implement, re-run `pnpm josh gate`,
|
|
|
52
54
|
`halfrun new` or `halfrun new "<title>"`: `kickoff new` + `halfrun #<N>` (no Issue exists yet). Steps
|
|
53
55
|
mirror `fullrun new` (1)–(8): derive an English title (or use the provided one) → **run `pnpm josh
|
|
54
56
|
issue:scout "<title>" [--body "<summary>"]` before creating the Issue** (`SKILL.md` → §2e) → create the
|
|
55
|
-
Issue (`gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:<n>' -
|
|
57
|
+
Issue (`gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:<n>' -F body=@<body-file>`,
|
|
56
58
|
body per `prompts/collaboration-workflow/issue-template.md`) → add `in-progress` → post the agreed plan → stash
|
|
57
59
|
any pre-existing changes with `git stash push -m "halfrun new: pre-existing changes"`, popped by
|
|
58
60
|
message with `pnpm josh stash:pop "halfrun new: pre-existing changes"`, never a positional `git stash pop` →
|
|
@@ -47,13 +47,13 @@ split is found.
|
|
|
47
47
|
title. **(1a) Run `pnpm josh issue:scout "<title>" [--body "<summary>"]` before creating the Issue** —
|
|
48
48
|
a candidate that covers the same work stops the run rather than filing a second Issue (`SKILL.md` →
|
|
49
49
|
§2e). (2) Create Issue: `gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:<n>'
|
|
50
|
-
-
|
|
50
|
+
-F body=@<body-file>` (body per `prompts/collaboration-workflow/issue-template.md`). Capture `<N>`. (3)
|
|
51
51
|
Post the plan in the session language, using the same body/comment logic as `kickoff #<N>`. (4) Send
|
|
52
52
|
Telegram notification. (5) **Stop** — do not implement. **Multi-issue split path**: (1) For each
|
|
53
53
|
independent deliverable, derive a focused English title, **run `pnpm josh issue:scout "<sub-title>"`
|
|
54
54
|
on it** (`SKILL.md` → §2e), and create a separate Issue with the `route:split` label: `gh api
|
|
55
55
|
repos/{owner}/{repo}/issues -f title="<sub-title>" -f 'labels[]=route:split' -f 'labels[]=depth:<n>'
|
|
56
|
-
-
|
|
56
|
+
-F body=@<body-file>`. Capture each Issue number. **When the split is filed into a repository other than
|
|
57
57
|
the one this session is running in**, every child body gets the `## Origin` backlink described in the
|
|
58
58
|
cross-package rule the AI documents keep resident, the epic body carries the same link as prose or a
|
|
59
59
|
plain bullet (never as a checkbox row, which would disable its auto-close), and the originating Issue
|
|
@@ -66,7 +66,7 @@ split is found.
|
|
|
66
66
|
josh epic:check <E>`. Only where `josh` is unavailable, fall back to the manual procedure: ensure the
|
|
67
67
|
label exists (`gh api repos/{owner}/{repo}/labels -f name=epic -f color=5319e7 -f description="Tracks
|
|
68
68
|
a batch of child issues from one split" --silent 2>/dev/null || true`), then create the epic with `gh
|
|
69
|
-
api repos/{owner}/{repo}/issues -f title="<epic-title>" -f 'labels[]=epic' -
|
|
69
|
+
api repos/{owner}/{repo}/issues -f title="<epic-title>" -f 'labels[]=epic' -F body=@<body-file>`. Its body
|
|
70
70
|
follows the epic format in `prompts/collaboration-workflow/issue-template.md` — split rationale,
|
|
71
71
|
dependencies, the `backlogrun` command, and a child task list in task-list syntax (`- [ ] #N`). The epic
|
|
72
72
|
exists as the **non-closing home for the split rationale**. When the children have no required order,
|
|
@@ -80,3 +80,5 @@ split is found.
|
|
|
80
80
|
**database id**, not its issue number; a failure here is non-fatal). Never fold the relation into the
|
|
81
81
|
creation call. (3) Send Telegram notification listing all created issues. (4) Present the command
|
|
82
82
|
`backlogrun #<E> --only`. (5) **Stop** — do not implement.
|
|
83
|
+
|
|
84
|
+
Before filing, run `pnpm josh issue:lint <body-file>` and apply every label in its `labels:` answer at creation, following `prompts/collaboration-workflow/issue-template.md` for classification.
|
|
@@ -29,6 +29,8 @@ backlog pool (`backlogrun-steps.md` → "What one invocation approves").
|
|
|
29
29
|
|
|
30
30
|
The detail below is read at the filing decision, and the marker suite pins the rules here.
|
|
31
31
|
|
|
32
|
+
Before filing an observation, run `pnpm josh issue:lint <body-file>` and apply every label in its `labels:` answer at creation; `prompts/collaboration-workflow/issue-template.md` is the single source. Keep the depth label.
|
|
33
|
+
|
|
32
34
|
### The depth test — a discretionary filing cites the product work it blocked
|
|
33
35
|
|
|
34
36
|
**A run that has just spent an hour inside the workflow tooling files findings about the workflow
|
|
@@ -55,7 +57,7 @@ cap's branch-2 filing all pass through a `gh api … issues` call, and the depth
|
|
|
55
57
|
beside whatever `route:` label that call already carries.
|
|
56
58
|
|
|
57
59
|
```bash
|
|
58
|
-
gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:1' -
|
|
60
|
+
gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=depth:1' -F body=@<body-file>
|
|
59
61
|
gh api repos/{owner}/{repo}/issues/<N>/labels -f 'labels[]=depth:1' # an Issue already filed
|
|
60
62
|
```
|
|
61
63
|
|
|
@@ -25,8 +25,10 @@ stays countable by filing route afterwards. **This paragraph belongs to the prer
|
|
|
25
25
|
the table** — the label means a filing the run is *blocked by*, so the observation row carries no
|
|
26
26
|
`route:` label of its own (§2i):
|
|
27
27
|
|
|
28
|
+
Before that call, run `pnpm josh issue:lint <body-file>` and apply every label in its `labels:` answer at creation; `prompts/collaboration-workflow/issue-template.md` is the single source. Keep `route:tier-a` and `depth`.
|
|
29
|
+
|
|
28
30
|
```bash
|
|
29
|
-
gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=route:tier-a' -f 'labels[]=depth:<n>' -
|
|
31
|
+
gh api repos/{owner}/{repo}/issues -f title="<title>" -f 'labels[]=route:tier-a' -f 'labels[]=depth:<n>' -F body=@<body-file>
|
|
30
32
|
```
|
|
31
33
|
|
|
32
34
|
Every "file the prerequisite" below means that labelled filing, and it always happens **first**: the
|
|
@@ -41,7 +41,7 @@ backlogrun joshuafolkken/kit#858 --only
|
|
|
41
41
|
never clone. The one exception is the split path's epic, since `pnpm josh epic` only writes the
|
|
42
42
|
repository it runs in — run it in that repository's checkout, or fall back to `gh api
|
|
43
43
|
repos/<owner/repo>/labels …` followed by `gh api repos/<owner/repo>/issues -f title="<epic-title>" -f
|
|
44
|
-
'labels[]=epic' -
|
|
44
|
+
'labels[]=epic' -F body=@<body-file>`, and report that `epic:check` could not be run. The promote arm has
|
|
45
45
|
no such fallback: with no checkout there, file the children and stop.
|
|
46
46
|
- **The implementing entries require a checkout and never create one — when the target is another
|
|
47
47
|
repository.** A prefix naming the session's own repository changes nothing (`fullrun kit#412` in the
|
|
@@ -1 +1,13 @@
|
|
|
1
1
|
closes #
|
|
2
|
+
|
|
3
|
+
## Release classification
|
|
4
|
+
|
|
5
|
+
Add exactly one label before merging:
|
|
6
|
+
|
|
7
|
+
- `breaking-change` — any incompatible change, even when it also adds a feature or fixes a bug
|
|
8
|
+
- `enhancement` — a compatible new feature or improvement
|
|
9
|
+
- `bugfix` — a compatible fix
|
|
10
|
+
- `other-change` — documentation, dependencies, or maintenance included in Other Changes
|
|
11
|
+
- `ignore-for-release` — omit this pull request from the changelog
|
|
12
|
+
|
|
13
|
+
Automated pull requests without a classification label are treated as Other Changes. If an automated pull request needs another classification or exclusion, add that one label.
|
package/.github/release.yml
CHANGED
package/.github/workflows/ci.yml
CHANGED
|
@@ -6,6 +6,7 @@ on:
|
|
|
6
6
|
|
|
7
7
|
pull_request:
|
|
8
8
|
branches: [main]
|
|
9
|
+
types: [opened, synchronize, reopened, labeled, unlabeled]
|
|
9
10
|
|
|
10
11
|
# A push run is grouped by the commit it carries, so a later push to main never cancels an earlier
|
|
11
12
|
# one. Without the sha every push to main shares one group — `github.ref` is `refs/heads/main` for
|
|
@@ -351,6 +352,10 @@ jobs:
|
|
|
351
352
|
- name: Run verification gate
|
|
352
353
|
run: pnpm josh gate --verbose --no-unit
|
|
353
354
|
|
|
355
|
+
- name: Check release classification
|
|
356
|
+
if: github.event_name == 'pull_request'
|
|
357
|
+
run: pnpm josh pr:classification
|
|
358
|
+
|
|
354
359
|
# The other half of the gate, on a runner of its own. It carries the same setup steps as
|
|
355
360
|
# `static-checks` rather than sharing them: a GitHub job is its own machine, so every job that
|
|
356
361
|
# needs Node sets Node up, and this workflow already writes that preamble once per job. The
|
|
@@ -425,6 +430,9 @@ jobs:
|
|
|
425
430
|
- name: Run unit tests
|
|
426
431
|
run: pnpm josh test:unit
|
|
427
432
|
|
|
433
|
+
- name: Verify optional ESLint consumer install
|
|
434
|
+
run: pnpm exec tsx scripts/package/verify-optional-eslint-install.ts
|
|
435
|
+
|
|
428
436
|
# **The required status check. `Checks` is a name the branch ruleset already requires, and this job
|
|
429
437
|
# is what keeps that name meaning what it meant** (joshuafolkken/kit#1226) — every check the single
|
|
430
438
|
# `Checks` job used to run has passed. It runs no checks itself; it reads the two halves' results.
|
|
@@ -2,9 +2,18 @@ name: Release to Production
|
|
|
2
2
|
on:
|
|
3
3
|
repository_dispatch:
|
|
4
4
|
types: [new-tag-created]
|
|
5
|
+
workflow_call:
|
|
6
|
+
inputs:
|
|
7
|
+
tag:
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
5
10
|
|
|
6
11
|
jobs:
|
|
7
12
|
update-branch:
|
|
13
|
+
if: github.repository != 'joshuafolkken/kit' || inputs.tag != ''
|
|
14
|
+
concurrency:
|
|
15
|
+
group: production-update
|
|
16
|
+
queue: max
|
|
8
17
|
runs-on: ubuntu-latest
|
|
9
18
|
permissions:
|
|
10
19
|
contents: write
|
|
@@ -24,7 +33,7 @@ jobs:
|
|
|
24
33
|
# repository_dispatch always runs on the default branch, so the event ref
|
|
25
34
|
# resolves to that branch, not the released tag. Use the tag carried in the
|
|
26
35
|
# dispatch payload (set by auto-tag.yml) as the merge source instead.
|
|
27
|
-
REF_NAME: ${{ github.event.client_payload.tag }}
|
|
36
|
+
REF_NAME: ${{ inputs.tag || github.event.client_payload.tag }}
|
|
28
37
|
run: |
|
|
29
38
|
if [ -z "$REF_NAME" ]; then
|
|
30
39
|
echo "::error::new-tag-created dispatch carried no tag payload; aborting." >&2
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
name: Publish
|
|
2
|
+
run-name: Publish ${{ github.event.client_payload.tag }}
|
|
2
3
|
|
|
3
4
|
on:
|
|
4
5
|
repository_dispatch:
|
|
@@ -6,6 +7,9 @@ on:
|
|
|
6
7
|
|
|
7
8
|
jobs:
|
|
8
9
|
publish-github:
|
|
10
|
+
concurrency:
|
|
11
|
+
group: package-publish
|
|
12
|
+
queue: max
|
|
9
13
|
runs-on: ubuntu-latest
|
|
10
14
|
timeout-minutes: 10
|
|
11
15
|
permissions:
|
|
@@ -36,11 +40,24 @@ jobs:
|
|
|
36
40
|
|
|
37
41
|
- run: pnpm install --frozen-lockfile --ignore-scripts
|
|
38
42
|
|
|
39
|
-
-
|
|
43
|
+
- name: Select GitHub Packages tag
|
|
44
|
+
id: publish-tag
|
|
45
|
+
run: |
|
|
46
|
+
version=$(node -p "require('./package.json').version")
|
|
47
|
+
latest=$(cd "$RUNNER_TEMP" && npm view @joshuafolkken/kit dist-tags.latest --registry https://npm.pkg.github.com)
|
|
48
|
+
tag=$(pnpm exec tsx scripts/release/publish-tag-cli.ts "$version" "$latest")
|
|
49
|
+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
|
50
|
+
env:
|
|
51
|
+
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
52
|
+
|
|
53
|
+
- run: pnpm publish --no-git-checks --tag ${{ steps.publish-tag.outputs.tag }} --registry https://npm.pkg.github.com
|
|
40
54
|
env:
|
|
41
55
|
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
42
56
|
|
|
43
57
|
publish-npm:
|
|
58
|
+
concurrency:
|
|
59
|
+
group: package-publish
|
|
60
|
+
queue: max
|
|
44
61
|
runs-on: ubuntu-latest
|
|
45
62
|
timeout-minutes: 10
|
|
46
63
|
permissions:
|
|
@@ -72,5 +89,58 @@ jobs:
|
|
|
72
89
|
|
|
73
90
|
- run: pnpm pack --out "$RUNNER_TEMP/kit.tgz"
|
|
74
91
|
|
|
92
|
+
- name: Select npm tag
|
|
93
|
+
id: publish-tag
|
|
94
|
+
run: |
|
|
95
|
+
version=$(node -p "require('./package.json').version")
|
|
96
|
+
latest=$(cd "$RUNNER_TEMP" && npm view @joshuafolkken/kit dist-tags.latest --registry https://registry.npmjs.org)
|
|
97
|
+
tag=$(pnpm exec tsx scripts/release/publish-tag-cli.ts "$version" "$latest")
|
|
98
|
+
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
|
99
|
+
|
|
75
100
|
- name: Publish to npm
|
|
76
|
-
run: cd "$RUNNER_TEMP" && npm publish kit.tgz --access public --tag
|
|
101
|
+
run: cd "$RUNNER_TEMP" && npm publish kit.tgz --access public --tag ${{ steps.publish-tag.outputs.tag }} --registry https://registry.npmjs.org --userconfig /dev/null
|
|
102
|
+
|
|
103
|
+
update-production:
|
|
104
|
+
needs: [publish-github, publish-npm]
|
|
105
|
+
permissions:
|
|
106
|
+
contents: write
|
|
107
|
+
uses: ./.github/workflows/production.yml
|
|
108
|
+
with:
|
|
109
|
+
tag: ${{ github.event.client_payload.tag }}
|
|
110
|
+
|
|
111
|
+
create-release:
|
|
112
|
+
needs: [publish-github, publish-npm, update-production]
|
|
113
|
+
runs-on: ubuntu-latest
|
|
114
|
+
timeout-minutes: 65
|
|
115
|
+
permissions:
|
|
116
|
+
actions: read
|
|
117
|
+
contents: write
|
|
118
|
+
steps:
|
|
119
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
120
|
+
with:
|
|
121
|
+
ref: ${{ github.event.client_payload.tag }}
|
|
122
|
+
fetch-depth: 0
|
|
123
|
+
|
|
124
|
+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
125
|
+
with:
|
|
126
|
+
node-version: 24
|
|
127
|
+
|
|
128
|
+
- name: Resolve pnpm version
|
|
129
|
+
id: pnpm-version
|
|
130
|
+
run: |
|
|
131
|
+
version=$(node -p "const m = require('./package.json'); m.packageManager?.match(/^pnpm@([^+]+)/)?.[1] ?? (m.devEngines?.packageManager?.name === 'pnpm' ? m.devEngines.packageManager.version?.split('+')[0] : 'latest') ?? 'latest'")
|
|
132
|
+
test -n "$version"
|
|
133
|
+
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
134
|
+
|
|
135
|
+
- uses: pnpm/setup@fbda4c85fc2e1e08721cd8763afea8f48d60f024 # v3.0.0
|
|
136
|
+
with:
|
|
137
|
+
version: ${{ steps.pnpm-version.outputs.version }}
|
|
138
|
+
install: false
|
|
139
|
+
|
|
140
|
+
- run: pnpm install --frozen-lockfile --ignore-scripts
|
|
141
|
+
|
|
142
|
+
- name: Publish GitHub Release
|
|
143
|
+
run: pnpm exec tsx scripts/release/github-release-cli.ts
|
|
144
|
+
env:
|
|
145
|
+
GH_TOKEN: ${{ github.token }}
|
|
146
|
+
RELEASE_TAG: ${{ github.event.client_payload.tag }}
|
package/CLAUDE.md
CHANGED
|
@@ -108,6 +108,7 @@ For every code modification, in order:
|
|
|
108
108
|
|
|
109
109
|
- **Tests are required for ALL code changes** (bug fixes, timing/animation fixes and refactors included): bug fix → regression test; UI/animation/timing → E2E for the observable change; logic/utility → unit; refactor → tests pinning existing behavior BEFORE the change (`prompts/refactoring.md`).
|
|
110
110
|
- **Non-runtime updates (pre-approved manual-only exception)**: a change touching no executable runtime code path may proceed with manual verification — declare it in Step 0 and state why. It covers docs, non-executable config, editor/IDE files, and cosmetic asset swaps with no selector/path change; the mechanically exempt (`*.md`, `.editorconfig`, `.idea/**`, `.vscode/**`, `prompts/**`) are recognized by the command below, and the rest stay the exemption a person declares. A test infeasible for a runtime change needs its reason stated and user approval.
|
|
111
|
+
- **static の HTML/CSS 例外:** `package.json` に `josh.profile: static` が記録され、変更が HTML/CSS だけなら自動テストの代わりにブラウザーで表示を確認する。対象ページを開き、想定する画面幅でレイアウト・リンク・HTML 内の操作を確認し、観察結果を報告する。HTML/CSS と同時に変更した場合も、JavaScript と TypeScript のファイルには自動テストが必要。`pnpm josh test:declared` はこの場合だけ理由を添えて `exempt` と表示する。
|
|
111
112
|
- **The commit stage answers this mechanically**: `pnpm josh test:declared` prints `required` / `exempt` / `satisfied` from the changed paths, and a runtime change with no test is refused at `pnpm josh git -y` on `required` — add the declared test or declare the non-runtime exception, then reissue (`prompts/collaboration-workflow/rule-delivery.md`).
|
|
112
113
|
- **Read a target's line headroom before editing: `pnpm josh lines <path>`** — near the limit, `Target` carries the splitting plan.
|
|
113
114
|
|
|
@@ -121,6 +122,7 @@ For every code modification, in order:
|
|
|
121
122
|
Run the full verification set **in order**; do not skip, reorder, or report completion on a failed or skipped step without the user agreeing. Inside a `fullrun` / `backlogrun` the gate runs beside the review and the merge chain (`workflow-commands` skill → §2, `prompts/review.md`).
|
|
122
123
|
|
|
123
124
|
0. **Test gate** — no tests added? Continue only under the non-runtime exception (Step 0) or explicit approval; otherwise stop and add tests.
|
|
125
|
+
static プロファイルの HTML/CSS だけの変更には、Step 0 の手動ブラウザー確認を適用できる。
|
|
124
126
|
1. **Refactor** — `prompts/refactoring.md`, until no high/medium items remain.
|
|
125
127
|
2. **`pnpm josh gate`** — lint, type check, spell check and unit tests concurrently. One gate per run; while implementing re-run a single check by name (`pnpm josh lint:related` / `pnpm josh cspell:dot` / `pnpm josh test:related`).
|
|
126
128
|
3. **Self-review** — a subagent runs `/code-review` per `prompts/review.md` (never a main-line `Skill` load); level from the changed paths, at most two rounds, high/medium findings resolved. `prompts/review.md` → "Review round cap".
|
package/dist/CLAUDE.md
CHANGED
|
@@ -108,6 +108,7 @@ For every code modification, in order:
|
|
|
108
108
|
|
|
109
109
|
- **Tests are required for ALL code changes** (bug fixes, timing/animation fixes and refactors included): bug fix → regression test; UI/animation/timing → E2E for the observable change; logic/utility → unit; refactor → tests pinning existing behavior BEFORE the change (`node_modules/@joshuafolkken/kit/prompts/refactoring.md`).
|
|
110
110
|
- **Non-runtime updates (pre-approved manual-only exception)**: a change touching no executable runtime code path may proceed with manual verification — declare it in Step 0 and state why. It covers docs, non-executable config, editor/IDE files, and cosmetic asset swaps with no selector/path change; the mechanically exempt (`*.md`, `.editorconfig`, `.idea/**`, `.vscode/**`, `prompts/**`) are recognized by the command below, and the rest stay the exemption a person declares. A test infeasible for a runtime change needs its reason stated and user approval.
|
|
111
|
+
- **static の HTML/CSS 例外:** `package.json` に `josh.profile: static` が記録され、変更が HTML/CSS だけなら自動テストの代わりにブラウザーで表示を確認する。対象ページを開き、想定する画面幅でレイアウト・リンク・HTML 内の操作を確認し、観察結果を報告する。HTML/CSS と同時に変更した場合も、JavaScript と TypeScript のファイルには自動テストが必要。`pnpm josh test:declared` はこの場合だけ理由を添えて `exempt` と表示する。
|
|
111
112
|
- **The commit stage answers this mechanically**: `pnpm josh test:declared` prints `required` / `exempt` / `satisfied` from the changed paths, and a runtime change with no test is refused at `pnpm josh git -y` on `required` — add the declared test or declare the non-runtime exception, then reissue (`node_modules/@joshuafolkken/kit/prompts/collaboration-workflow/rule-delivery.md`).
|
|
112
113
|
- **Read a target's line headroom before editing: `pnpm josh lines <path>`** — near the limit, `Target` carries the splitting plan.
|
|
113
114
|
|
|
@@ -121,6 +122,7 @@ For every code modification, in order:
|
|
|
121
122
|
Run the full verification set **in order**; do not skip, reorder, or report completion on a failed or skipped step without the user agreeing. Inside a `fullrun` / `backlogrun` the gate runs beside the review and the merge chain (`workflow-commands` skill → §2, `node_modules/@joshuafolkken/kit/prompts/review.md`).
|
|
122
123
|
|
|
123
124
|
0. **Test gate** — no tests added? Continue only under the non-runtime exception (Step 0) or explicit approval; otherwise stop and add tests.
|
|
125
|
+
static プロファイルの HTML/CSS だけの変更には、Step 0 の手動ブラウザー確認を適用できる。
|
|
124
126
|
1. **Refactor** — `node_modules/@joshuafolkken/kit/prompts/refactoring.md`, until no high/medium items remain.
|
|
125
127
|
2. **`pnpm josh gate`** — lint, type check, spell check and unit tests concurrently. One gate per run; while implementing re-run a single check by name (`pnpm josh lint:related` / `pnpm josh cspell:dot` / `pnpm josh test:related`).
|
|
126
128
|
3. **Self-review** — a subagent runs `/code-review` per `node_modules/@joshuafolkken/kit/prompts/review.md` (never a main-line `Skill` load); level from the changed paths, at most two rounds, high/medium findings resolved. `node_modules/@joshuafolkken/kit/prompts/review.md` → "Review round cap".
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Project instructions
|
|
2
|
+
|
|
3
|
+
- 既存のファイルと利用者の設定を尊重し、変更する前に内容を確認する。
|
|
4
|
+
- 変更には検証を付け、実行した結果を報告する。
|
|
5
|
+
- HTML、CSS、JavaScript のファイルがある場合は Prettier で整形する。
|
|
6
|
+
- 画面に見える変更をした場合はブラウザーで表示と操作を確認する。
|
|
7
|
+
- JavaScript または TypeScript の動作を変更した場合は、その動作を確認する自動テストを追加する。
|
|
8
|
+
- Git や GitHub を使う場合だけ、それぞれのワークフローを利用する。
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
load_environment_file,
|
|
10
10
|
notice_refusal_path,
|
|
11
11
|
refusal_path
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-77RLKZ5V.js";
|
|
13
|
+
import "./chunk-3HZ5MJIW.js";
|
|
14
|
+
import "./chunk-OYU6KPRA.js";
|
|
15
|
+
import "./chunk-UULARQ5Q.js";
|
|
16
16
|
import "./chunk-FXAKJKTB.js";
|
|
17
17
|
import "./chunk-SSX23SJ2.js";
|
|
18
18
|
export {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OYU6KPRA.js";
|
|
4
4
|
import {
|
|
5
5
|
time_bundle_call,
|
|
6
6
|
time_format,
|
|
7
7
|
time_round_trips,
|
|
8
8
|
time_spans,
|
|
9
9
|
time_transcript_line
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-UULARQ5Q.js";
|
|
11
11
|
|
|
12
12
|
// scripts/lane/lane-guard-policy.ts
|
|
13
13
|
var DEFAULT_MODE = "refuse";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// scripts/build/local-bin.ts
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
|
|
6
|
+
// scripts/lib/schemas.ts
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
var overrides_snapshot_schema = z.record(z.string(), z.string());
|
|
9
|
+
var package_version_schema = z.object({ version: z.string() });
|
|
10
|
+
var package_named_version_schema = z.looseObject({ name: z.string(), version: z.string() });
|
|
11
|
+
var package_with_version_schema = z.looseObject({ version: z.string() });
|
|
12
|
+
var ls_global_dependency_schema = z.looseObject({ version: z.string() });
|
|
13
|
+
var ls_global_dependencies_schema = z.record(z.string(), ls_global_dependency_schema).optional();
|
|
14
|
+
var pnpm_ls_global_schema = z.array(
|
|
15
|
+
z.looseObject({
|
|
16
|
+
dependencies: ls_global_dependencies_schema
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
var vscode_settings_schema = z.record(z.string(), z.unknown());
|
|
20
|
+
var with_scripts_schema = z.looseObject({
|
|
21
|
+
scripts: z.record(z.string(), z.string()).optional()
|
|
22
|
+
});
|
|
23
|
+
var with_development_deps_schema = z.looseObject({
|
|
24
|
+
devDependencies: z.record(z.string(), z.string()).optional()
|
|
25
|
+
});
|
|
26
|
+
var with_package_manager_schema = z.looseObject({
|
|
27
|
+
packageManager: z.string().optional()
|
|
28
|
+
});
|
|
29
|
+
var with_development_engine_schema = z.looseObject({
|
|
30
|
+
devEngines: z.record(z.string(), z.unknown()).optional()
|
|
31
|
+
});
|
|
32
|
+
var bin_entry_schema = z.union([z.string(), z.record(z.string(), z.string())]).optional();
|
|
33
|
+
var package_bin_schema = z.looseObject({ bin: bin_entry_schema });
|
|
34
|
+
var json_object_schema = z.record(z.string(), z.unknown());
|
|
35
|
+
var string_array_schema = z.array(z.string());
|
|
36
|
+
var string_record_schema = z.record(z.string(), z.string());
|
|
37
|
+
|
|
38
|
+
// scripts/build/local-bin.ts
|
|
39
|
+
var NODE_MODULES = "node_modules";
|
|
40
|
+
var BIN_DIR = ".bin";
|
|
41
|
+
var WINDOWS_PLATFORM = "win32";
|
|
42
|
+
var WINDOWS_SHIM_SUFFIX = ".cmd";
|
|
43
|
+
var PACKAGE_JSON = "package.json";
|
|
44
|
+
function resolve_local_bin(project_root, bin_name) {
|
|
45
|
+
const shim = process.platform === WINDOWS_PLATFORM ? `${bin_name}${WINDOWS_SHIM_SUFFIX}` : bin_name;
|
|
46
|
+
return path.join(project_root, NODE_MODULES, BIN_DIR, shim);
|
|
47
|
+
}
|
|
48
|
+
function ancestor_directories(start_directory) {
|
|
49
|
+
const directories = [];
|
|
50
|
+
let current = start_directory;
|
|
51
|
+
while (!directories.includes(current)) {
|
|
52
|
+
directories.push(current);
|
|
53
|
+
current = path.dirname(current);
|
|
54
|
+
}
|
|
55
|
+
return directories;
|
|
56
|
+
}
|
|
57
|
+
function find_local_bin_upwards(start_directory, bin_name) {
|
|
58
|
+
return ancestor_directories(start_directory).map((directory) => resolve_local_bin(directory, bin_name)).find((candidate) => existsSync(candidate));
|
|
59
|
+
}
|
|
60
|
+
function read_bin_entry(manifest_path, package_name, bin_name) {
|
|
61
|
+
const { bin } = package_bin_schema.parse(JSON.parse(readFileSync(manifest_path, "utf8")));
|
|
62
|
+
if (typeof bin === "string") return bin_name === path.basename(package_name) ? bin : void 0;
|
|
63
|
+
return bin?.[bin_name];
|
|
64
|
+
}
|
|
65
|
+
function resolve_package_bin(base_directory, package_name, bin_name) {
|
|
66
|
+
try {
|
|
67
|
+
const resolve_from = createRequire(path.join(base_directory, PACKAGE_JSON));
|
|
68
|
+
const manifest_path = resolve_from.resolve(`${package_name}/${PACKAGE_JSON}`);
|
|
69
|
+
const bin_entry = read_bin_entry(manifest_path, package_name, bin_name);
|
|
70
|
+
if (bin_entry === void 0) return void 0;
|
|
71
|
+
const cli_entry = path.join(path.dirname(manifest_path), bin_entry);
|
|
72
|
+
return existsSync(cli_entry) ? cli_entry : void 0;
|
|
73
|
+
} catch {
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export {
|
|
79
|
+
resolve_local_bin,
|
|
80
|
+
find_local_bin_upwards,
|
|
81
|
+
resolve_package_bin
|
|
82
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_guard_policy,
|
|
3
3
|
time_batch_guard
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3HZ5MJIW.js";
|
|
5
5
|
import {
|
|
6
6
|
hook_decision
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OYU6KPRA.js";
|
|
8
8
|
|
|
9
9
|
// scripts/hooks/batch-guard.ts
|
|
10
10
|
import { text } from "node:stream/consumers";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker,
|
|
3
3
|
run_issue_number
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OYU6KPRA.js";
|
|
5
5
|
import {
|
|
6
6
|
PLATFORM_TEMP_ROOT,
|
|
7
7
|
cost_blocks,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
time_density_hook,
|
|
12
12
|
time_shell,
|
|
13
13
|
time_transcript_line
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UULARQ5Q.js";
|
|
15
15
|
import {
|
|
16
16
|
ENV_FILE_NAME,
|
|
17
17
|
LANE_SEAT_KEY,
|
|
@@ -1512,6 +1512,9 @@ var run_cut = {
|
|
|
1512
1512
|
};
|
|
1513
1513
|
|
|
1514
1514
|
// scripts/git/issue-labels.ts
|
|
1515
|
+
var BUG_LABEL = "bug";
|
|
1516
|
+
var ENHANCEMENT_LABEL = "enhancement";
|
|
1517
|
+
var BREAKING_CHANGE_LABEL = "breaking-change";
|
|
1515
1518
|
var IN_PROGRESS_LABEL = "in-progress";
|
|
1516
1519
|
var NEEDS_DECISION_LABEL = "needs-decision";
|
|
1517
1520
|
var NEEDS_HUMAN_REVIEW_LABEL = "needs-human-review";
|
|
@@ -1519,6 +1522,13 @@ var ALREADY_DONE_LABEL = "already-done";
|
|
|
1519
1522
|
function has_any_label(labels, wanted) {
|
|
1520
1523
|
return (labels ?? []).some((label) => wanted.has(label.name.toLowerCase()));
|
|
1521
1524
|
}
|
|
1525
|
+
function label_name_of(labels, wanted) {
|
|
1526
|
+
const target = wanted.toLowerCase();
|
|
1527
|
+
return labels.find((label) => label.toLowerCase() === target);
|
|
1528
|
+
}
|
|
1529
|
+
function has_label_name(labels, wanted) {
|
|
1530
|
+
return label_name_of(labels, wanted) !== void 0;
|
|
1531
|
+
}
|
|
1522
1532
|
|
|
1523
1533
|
// scripts/rules/shell-segments.ts
|
|
1524
1534
|
var SEGMENT_SEPARATOR = /&&|\|\||;|\n/u;
|
|
@@ -3276,11 +3286,15 @@ export {
|
|
|
3276
3286
|
lane_child_invocation,
|
|
3277
3287
|
run_hold,
|
|
3278
3288
|
run_cut,
|
|
3289
|
+
BUG_LABEL,
|
|
3290
|
+
ENHANCEMENT_LABEL,
|
|
3291
|
+
BREAKING_CHANGE_LABEL,
|
|
3279
3292
|
IN_PROGRESS_LABEL,
|
|
3280
3293
|
NEEDS_DECISION_LABEL,
|
|
3281
3294
|
NEEDS_HUMAN_REVIEW_LABEL,
|
|
3282
3295
|
ALREADY_DONE_LABEL,
|
|
3283
3296
|
has_any_label,
|
|
3297
|
+
has_label_name,
|
|
3284
3298
|
lane_park,
|
|
3285
3299
|
repo_party,
|
|
3286
3300
|
FULL_PAGE_QUERY,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
investigation_reads
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XMR3BS35.js";
|
|
4
4
|
import {
|
|
5
5
|
lane_guard_policy
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3HZ5MJIW.js";
|
|
7
7
|
import {
|
|
8
8
|
hook_decision
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OYU6KPRA.js";
|
|
10
10
|
|
|
11
11
|
// scripts/delegation/investigation-guard.ts
|
|
12
12
|
import { text } from "node:stream/consumers";
|