Skip to content

Commit fffce89

Browse files
authored
chore: merge dev into main (#205)
2 parents 9c5fbb1 + 240f740 commit fffce89

86 files changed

Lines changed: 6408 additions & 865 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/plugin.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919
"./skills/repo/update-deps",
2020
"./skills/work/handoff",
2121
"./skills/work/issue",
22+
"./skills/work/refine-issue",
23+
"./skills/work/tldr",
2224
"./skills/work/work-implement",
2325
"./skills/work/work-implement-queue",
2426
"./skills/work/work-review",
2527
"./skills/work/work-review-queue",
2628
"./skills/docs/compact-readme",
2729
"./skills/docs/vhs-demo",
30+
"./skills/docs/write-contributing",
2831
"./skills/docs/write-docs",
2932
"./skills/docs/write-readme",
3033
"./skills/meta/tituskirch-skills-config",

.github/workflows/codeql.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ on:
77
branches: [main, dev]
88
pull_request:
99
branches: [main, dev]
10+
# ready_for_review is what makes the draft gate below reachable: the default
11+
# types are opened/synchronize/reopened, and a draft becoming ready is none of
12+
# them — so without this the analysis would never run on a PR that started as a
13+
# draft. The AI work loop opens every PR as one.
14+
types: [opened, synchronize, reopened, ready_for_review]
1015
schedule:
1116
- cron: '34 23 * * 0'
1217
workflow_dispatch:
@@ -19,6 +24,14 @@ jobs:
1924
analyze:
2025
name: Analyze (${{ matrix.language }})
2126
runs-on: ubuntu-latest
27+
# The same draft gate the other two PR workflows carry, so a draft costs nothing
28+
# here either. Written with the event-name guard rather than the bare
29+
# `draft == false` those two use, because this workflow also runs on push, on a
30+
# schedule and on dispatch — where there is no pull request to read a flag from.
31+
# Neither of those triggers is gated, so nothing on main/dev goes unanalysed.
32+
if: >-
33+
github.event_name != 'pull_request' ||
34+
github.event.pull_request.draft == false
2235
timeout-minutes: 20
2336
permissions:
2437
security-events: write

.tituskirch-skills.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/TitusKirch/skills/main/tituskirch-skills.schema.json",
33
"forge": "github",
4+
"grillWith": "grilling",
45
"language": "en",
56
"verify": "pnpm verify",
67
"trustedBots": [
@@ -25,15 +26,18 @@
2526
"prune-branches",
2627
"prune-comments",
2728
"pull-request",
29+
"refine-issue",
2830
"release",
2931
"tituskirch-skills-config",
32+
"tldr",
3033
"update-deps",
3134
"validate-skills",
3235
"vhs-demo",
3336
"work-implement",
3437
"work-implement-queue",
3538
"work-review",
3639
"work-review-queue",
40+
"write-contributing",
3741
"write-docs",
3842
"write-readme",
3943
"skills",
@@ -69,9 +73,6 @@
6973
},
7074
"labels": {
7175
"exclude": ["stack:*", "autorelease:*", "dependencies"]
72-
},
73-
"github": {
74-
"template": null
7576
}
7677
},
7778
"docs": {
@@ -92,7 +93,8 @@
9293
"needsHuman": "ai: needs human",
9394
"done": "ai: done",
9495
"blocked": "ai: blocked",
95-
"repo": false
96+
"repo": false,
97+
"needsTriage": "needs triage"
9698
},
9799
"review": {
98100
"maxRounds": 3

AGENTS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ Retyping a change is exactly how the two drift; one reflowed line or reworded cl
2424
| :------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
2525
| `pnpm verify` | **The repo's gate**`check` + `skills:check` + `typecheck` + `test`, in CI's order, and the root `verify` key. CI runs the same commands as one step each, so one run reports every failure; `test/ci-gate.test.ts` fails if the two lists drift. |
2626
| `pnpm check` | Lint + format check only — a subset of the gate, not the gate. `pnpm check:fix` applies both fixers. |
27-
| `pnpm skills:sync` | Regenerates nine artifacts from the skill folders. **Run after touching any skill.** |
27+
| `pnpm skills:sync` | Regenerates eleven artifacts from the skill folders. **Run after touching any skill.** |
2828
| `pnpm skills:check` | The CI guard for the above. Fails if any of them drifted. |
2929
| `pnpm typecheck` | `tsc --noEmit`. `erasableSyntaxOnly` is on, so an enum fails here, not at runtime. |
3030
| `pnpm test` | `node --test` over `test/` — the resolver, the schema, skill self-containment, the CI-gate guard, the conformance-gate guard, the link destinations, and the `CLAUDE.md`/`AGENTS.md` mirror. |
3131
| `pnpm skills:link` | Symlinks every skill into **both** `~/.claude/skills/` (Claude Code) and `~/.agents/skills/` (Codex, Cursor, OpenCode, Gemini CLI) for live local testing — whole-folder, except a skill carrying a dev-artifact dir (`evals/`) links entry by entry to leave the fixture out, per destination. `pnpm skills:unlink` clears both; the destination list lives once, in `scripts/skills-lib.sh` ([ADR-0016](docs/99.adr/0016-link-into-every-client-skills-path.md)). |
3232
| `pnpm skills:conformance` | Validates every skill against the Agent Skills spec with `skills-ref`, pinned and run in Docker. **Not in `verify`** — the gate stays pnpm-only; this needs Docker. Its own workflow. |
3333

34-
**Nine artifacts are generated — never hand-edit them:** the root `README.md` skills table, each `skills/<category>/README.md`, `.claude-plugin/plugin.json`, `skills.sh.json`'s groupings, the `<skills-config>` block plus `templates/resolve-config.sh` mirrored into each config-reading skill (source: `scripts/config-block.md` and `scripts/resolve-config.sh`), the `<skills-authority>` / `<skills-authority-reduced>` author-authority block mirrored into each skill that reads third-party text (source: `scripts/authority-block.md`), the `<skills-verify>` / `<skills-verify-isolated>` check-command block mirrored into each skill that runs the repo's gate (source: `scripts/verify-block.md`), the `<skills-worklock>` single-flight-lock spec mirrored into the four `work-*` skills (source: `scripts/worklock-block.md`), and the `<skills-plan>` plan-presentation rule mirrored into each skill that puts a plan in front of a human (source: `scripts/plan-block.md`, roster in `test/isolation.test.ts`). A new category also needs an entry in `CATEGORIES` in `scripts/gen-skills.ts`, or the sync fails loudly.
34+
**Eleven artifacts are generated — never hand-edit them:** the root `README.md` skills table, each `skills/<category>/README.md`, `.claude-plugin/plugin.json`, `skills.sh.json`'s groupings, the `<skills-config>` block mirrored into each skill that hosts it — with `templates/resolve-config.sh` copied into each skill that _names_ it, which is every host **plus** the two queue skills that delegate the prose and still run the script (source: `scripts/config-block.md` and `scripts/resolve-config.sh`), the `<skills-authority>` / `<skills-authority-reduced>` author-authority block mirrored into each skill that reads third-party text (source: `scripts/authority-block.md`), the `<skills-verify>` / `<skills-verify-isolated>` check-command block mirrored into each skill that runs the repo's gate (source: `scripts/verify-block.md`), the `<skills-worklock>` single-flight-lock spec mirrored into the two work-loop **unit** skills — the two `*-queue` skills name their worker's REFERENCE for it instead, which is what lets them skip both this block and the config one (source: `scripts/worklock-block.md`, roster in `test/isolation.test.ts`), the `<skills-plan>` plan-presentation rule mirrored into each skill that puts a plan in front of a human (source: `scripts/plan-block.md`, roster in `test/isolation.test.ts`), the `<skills-tldr>` report-lead rule mirrored into each skill whose run **ends** in a report — a strict subset of the plan roster, since a skill leads with a result only where it closes by reporting one (source: `scripts/tldr-block.md`, roster in `test/isolation.test.ts`), and the `<skills-forge>` forge/host resolution rule mirrored into each skill that drives a forge — the same two `*-queue` skills name their worker's REFERENCE for this one too (source: `scripts/forge-block.md`, roster in `test/isolation.test.ts`). A new category also needs an entry in `CATEGORIES` in `scripts/gen-skills.ts`, or the sync fails loudly.
3535

3636
## Non-obvious tooling
3737

@@ -49,8 +49,8 @@ Retyping a change is exactly how the two drift; one reflowed line or reworded cl
4949
`.github/workflows/` is authoritative. Four behaviours that mislead if unknown:
5050

5151
- **CI runs `on: pull_request` only, so a commit pushed straight to `dev` is never checked by CI.** The AI work loop is configured `branch:dev` — it commits to the shared branch with no PR — which makes `pnpm verify`, run locally before the push, the _only_ automated gate between such a change and the release branch. That is why the root `verify` key is the full gate and not just lint plus format: nothing downstream would catch a broken test, a type error, or a drifted generated artifact until the rollup PR.
52-
- **CI skips draft PRs** — a draft's empty check list is not a pass.
53-
- **CodeQL only fires on `**/*.{js,ts,mjs,cjs}` or workflow changes**it will not run on a markdown-only PR, which is most PRs here.
52+
- **Every PR workflow skips drafts, and that is now load-bearing rather than incidental** — a draft's check list is not a pass. `work-implement` opens its PRs as drafts on purpose and `work-review` marks one ready only once it would accept, so CI is spent once per _finished_ instead of once per push (**The draft gate** in `work-implement`'s REFERENCE). Each of the three therefore needs both halves: the draft gate _and_ `ready_for_review` in its trigger `types`, or the un-draft fires nothing. All three gate on the **job**, so a draft reports one `skipping` row per gated job rather than an empty list — which is why anything reading those checks must discard `skipping` outright instead of treating a non-failing list as green.
53+
- **CodeQL runs on every PR to `main`/`dev`, markdown-only ones included**`codeql.yml` carries no `paths:` filter, so both matrix legs (`actions`, `javascript-typescript`) analyse every pull request; only the draft gate above holds it back. It is not the cheap no-op a path-scoped workflow would be, and the work loop's CI read depends on knowing which workflows a head actually triggers, so this is worth having right.
5454
- **The skill conformance check is a separate workflow, scoped to `skills/**` and its own script** — so it does not run on a PR that touches neither, and, like everything else here, never on a push straight to `dev`. It re-tiers the deliberate `disallowed-tools` (ADR-0007) instead of failing on it; `test/conformance-gate.test.ts` pins that list to `validate-skills`' prose. Running it locally needs Docker, which is why `pnpm verify` does not.
5555

5656
## Adding a skill

0 commit comments

Comments
 (0)