@synoikia/create-plugin 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +3 -14
  3. package/dist/cli.js +0 -4
  4. package/dist/cli.js.map +1 -1
  5. package/dist/repo.d.ts +1 -1
  6. package/dist/scaffold.js +1 -6
  7. package/dist/scaffold.js.map +1 -1
  8. package/package.json +4 -4
  9. package/templates/repo/base/README.md +3 -3
  10. package/templates/repo/base/_github/workflows/ci.yml +12 -0
  11. package/templates/repo/base/_gitignore +1 -0
  12. package/templates/repo/base/package.json +2 -28
  13. package/templates/repo/claude/CLAUDE.md +3 -39
  14. package/templates/repo/claude/_claude/guard-paths.json +17 -0
  15. package/templates/repo/claude/_claude/hooks/check-plugins.mjs +39 -0
  16. package/templates/repo/claude/_claude/hooks/session-start.sh +8 -9
  17. package/templates/repo/claude/_claude/settings.json +17 -17
  18. package/dist/workflow/branch.d.ts +0 -2
  19. package/dist/workflow/branch.js +0 -31
  20. package/dist/workflow/branch.js.map +0 -1
  21. package/dist/workflow/config.d.ts +0 -24
  22. package/dist/workflow/config.js +0 -25
  23. package/dist/workflow/config.js.map +0 -1
  24. package/dist/workflow/features.d.ts +0 -20
  25. package/dist/workflow/features.js +0 -165
  26. package/dist/workflow/features.js.map +0 -1
  27. package/dist/workflow/git.d.ts +0 -12
  28. package/dist/workflow/git.js +0 -42
  29. package/dist/workflow/git.js.map +0 -1
  30. package/dist/workflow/glob.d.ts +0 -3
  31. package/dist/workflow/glob.js +0 -21
  32. package/dist/workflow/glob.js.map +0 -1
  33. package/dist/workflow/index.d.ts +0 -2
  34. package/dist/workflow/index.js +0 -162
  35. package/dist/workflow/index.js.map +0 -1
  36. package/dist/workflow/phases.d.ts +0 -22
  37. package/dist/workflow/phases.js +0 -50
  38. package/dist/workflow/phases.js.map +0 -1
  39. package/dist/workflow/prose.d.ts +0 -2
  40. package/dist/workflow/prose.js +0 -113
  41. package/dist/workflow/prose.js.map +0 -1
  42. package/dist/workflow/red.d.ts +0 -2
  43. package/dist/workflow/red.js +0 -36
  44. package/dist/workflow/red.js.map +0 -1
  45. package/dist/workflow/secrets.d.ts +0 -2
  46. package/dist/workflow/secrets.js +0 -5
  47. package/dist/workflow/secrets.js.map +0 -1
  48. package/dist/workflow/security-line.d.ts +0 -6
  49. package/dist/workflow/security-line.js +0 -14
  50. package/dist/workflow/security-line.js.map +0 -1
  51. package/dist/workflow/sync.d.ts +0 -4
  52. package/dist/workflow/sync.js +0 -47
  53. package/dist/workflow/sync.js.map +0 -1
  54. package/dist/workflow/tests.d.ts +0 -2
  55. package/dist/workflow/tests.js +0 -6
  56. package/dist/workflow/tests.js.map +0 -1
  57. package/templates/repo/claude/_claude/agents/security-reviewer.md +0 -70
  58. package/templates/repo/claude/_claude/hooks/format.mjs +0 -20
  59. package/templates/repo/claude/_claude/hooks/guard-paths.mjs +0 -43
  60. package/templates/repo/claude/_claude/skills/add-plugin/SKILL.md +0 -46
  61. package/templates/repo/claude/_claude/skills/plugin-development/SKILL.md +0 -64
  62. package/templates/repo/claude/_claude/skills/plugin-development/references/testing.md +0 -60
  63. package/templates/repo/claude/_claude/skills/plugin-development/references/typescript.md +0 -31
  64. package/templates/repo/claude/_claude/skills/release-plugin/SKILL.md +0 -42
  65. package/templates/workflow/base/_githooks/pre-commit +0 -3
  66. package/templates/workflow/base/_githooks/pre-push +0 -4
  67. package/templates/workflow/base/_github/workflows/workflow.yml +0 -45
  68. package/templates/workflow/base/docs/workflow.md +0 -100
  69. package/templates/workflow/claude/_claude/hooks/guard-branch.mjs +0 -73
  70. package/templates/workflow/claude/_claude/skills/architect/SKILL.md +0 -44
  71. package/templates/workflow/claude/_claude/skills/change-workflow/SKILL.md +0 -70
  72. package/templates/workflow/claude/_claude/skills/developer/SKILL.md +0 -57
  73. package/templates/workflow/claude/_claude/skills/requirements-engineer/SKILL.md +0 -59
  74. package/templates/workflow/claude/_claude/skills/technical-writing/SKILL.md +0 -35
@@ -1,31 +0,0 @@
1
- # TypeScript
2
-
3
- The compiler settings are in `tsconfig.base.json`: strict, `noUncheckedIndexedAccess`, `verbatimModuleSyntax`, `NodeNext` modules. Don't change them per plugin.
4
-
5
- ## Imports and modules
6
-
7
- - Use `import type` for anything used only as a type. Put a `.js` extension on every relative import.
8
- - Relative paths only, no path aliases. Node built-ins with the `node:` prefix.
9
- - A plugin's `src/` keeps the layout of the others: `index.ts` calls `runPlugin()`, `plugin.ts` builds the handlers with `definePlugin`, and `auth.ts` signs the requests. A `client.ts` talks to the upstream, and a `catalog.ts` turns discovery and `plugin.yaml` into operations. Add a file only when a second concern appears.
10
- - Plugin-facing types (`PluginHandlers`, `OperationDescriptor`, …) come from `@synoikia/plugin-sdk`. Don't redeclare them.
11
-
12
- ## Upstream data is `unknown`
13
-
14
- - Type responses, events and specs as `unknown` and narrow them with `isPlainObject`, `requireString`, `requireField` or a small type guard. No `any`.
15
- - Avoid `as`. When a cast is needed (a library gap, a record already checked), keep it next to the check that makes it true. `x!` is fine only right after a check or for a test fixture.
16
- - `satisfies` to check an object literal against a type without widening it.
17
- - With `noUncheckedIndexedAccess`, handle the `undefined` from `arr[i]` and `record[key]` (`?.`, `??`, an early return) rather than asserting it away.
18
- - A shape the code doesn't recognize fails closed: redact it or throw, don't pass it on.
19
-
20
- ## Errors
21
-
22
- - Throw `PluginError` with an `ErrorCodes` value for failures core should see. Use `upstreamError` and `errorMessage` to map upstream failures. Messages name the operation and the cause, never a secret or a raw upstream body.
23
- - Return a discriminated union (`{ ok: true; … } | { ok: false; reason: … }`) for an expected outcome the caller branches on. Don't add a generic `Result<T, E>` type or library.
24
- - `catch (err)` gives `unknown`: narrow with `instanceof` or use `errorMessage(err)`.
25
-
26
- ## Functions and data
27
-
28
- - Prefer plain functions and object literals. Use a class only for a client with state (a connection, a session, pending requests).
29
- - Small pure helpers over clever generics. Add a type parameter only when two real callers need it.
30
- - Fixed sets of values: an `as const` array and a union derived from it, never an `enum`.
31
- - Constants that are policy (limits, timeouts) live in `plugin.yaml` when they are plugin settings, else `UPPER_SNAKE` at the top of the module that owns them.
@@ -1,42 +0,0 @@
1
- ---
2
- name: release-plugin
3
- description: Prepare a plugin release by bumping its version in manifest.json and package.json together, and optionally its minimum Synoikia version. Use when asked to release, publish, ship or bump the version of a plugin.
4
- ---
5
-
6
- # Release a plugin
7
-
8
- A release is a version bump merged to `main`. The Release workflow (`.github/workflows/release.yml`) then packs, signs, verifies and publishes every plugin whose manifest version isn't in the published index yet (see `RELEASING.md`). Nothing is published from a branch, and nothing here needs the signing key.
9
-
10
- ## Steps
11
-
12
- 1. **Pick the version** with semver against the last release (`git log --oneline -- plugins/<id>` shows what changed):
13
- - patch: fixes, catalog corrections, wording.
14
- - minor: new operations, connection fields or capabilities, compatible with existing instances. Also any `plugin.yaml` change that unlocks an operation, drops a `sensitiveParams`/`sensitiveResult` rule or overrides a classification to read. Call it out in the PR.
15
- - major: a change that breaks existing instances, such as a renamed operation key, a removed connection field or a changed binding.
16
-
17
- Released versions are immutable, so never reuse one. If the published index already has the version, `synoikia-plugin repo pack` skips the plugin and nothing is released.
18
-
19
- 2. **Bump both files to the same version.** `synoikia-plugin check` (in the plugin's tests) and `repo pack` fail if they differ.
20
- - `plugins/<id>/manifest.json` → `version`
21
- - `plugins/<id>/package.json` → `version`
22
-
23
- 3. **Minimum Synoikia version.** Only when the change needs a core feature that older Synoikia releases lack, add it to `package.json`:
24
-
25
- ```json
26
- "synoikia": { "minCoreVersion": "x.y.z" }
27
- ```
28
-
29
- Otherwise the manifest's `sdk` range decides which Synoikia versions can install it. If the plugin now needs a newer SDK, bump these ranges together, then run `pnpm install`:
30
- - the `sdk` range in `manifest.json`
31
- - the `@synoikia/plugin-sdk`, `@synoikia/core` and `@synoikia/create-plugin` ranges in `package.json`
32
-
33
- 4. **Verify** that what will be packed builds and passes:
34
-
35
- ```sh
36
- pnpm --filter ./plugins/<id> test
37
- pnpm typecheck && pnpm lint && pnpm format:check
38
- ```
39
-
40
- 5. In the PR description, name the plugin, the version, the user-visible changes and any `minCoreVersion`. Merging it publishes the release.
41
-
42
- Never touch `minisign.pub`, the `MINISIGN_SECRET_KEY` steps in the workflow, or the `index` release.
@@ -1,3 +0,0 @@
1
- #!/bin/sh
2
- # Refuses credential files by name, then scans the staged changes with gitleaks when it is installed.
3
- exec pnpm run --silent workflow pre-commit
@@ -1,4 +0,0 @@
1
- #!/bin/sh
2
- # Runs the workflow checks that CI runs, except the red check. ALLOW_WORKFLOW=1 skips them once.
3
- [ "${ALLOW_WORKFLOW:-}" = "1" ] && exit 0
4
- exec pnpm run --silent workflow pre-push
@@ -1,45 +0,0 @@
1
- # Written by `synoikia-plugin workflow sync`. Edit the template in via-justa/synoikia-core instead.
2
- name: Workflow
3
-
4
- on:
5
- pull_request:
6
- types: [opened, edited, synchronize, reopened, ready_for_review, labeled, unlabeled]
7
-
8
- permissions:
9
- contents: read
10
-
11
- jobs:
12
- workflow:
13
- runs-on: ubuntu-latest
14
- env:
15
- BACKFILL: ${{ contains(github.event.pull_request.labels.*.name, 'backfill') && '--backfill' || '' }}
16
- BASE: ${{ github.event.pull_request.base.sha }}
17
- steps:
18
- - uses: actions/checkout@v4
19
- with:
20
- ref: ${{ github.event.pull_request.head.sha }}
21
- fetch-depth: 0
22
- persist-credentials: false
23
- - uses: pnpm/action-setup@v4
24
- - uses: actions/setup-node@v4
25
- with:
26
- node-version-file: .nvmrc
27
- cache: pnpm
28
- - run: pnpm install --frozen-lockfile
29
- - run: pnpm workflow check-branch
30
- - run: pnpm workflow check-features --base "$BASE" $BACKFILL
31
- - run: pnpm workflow check-prose --base "$BASE" --pr-body
32
- - run: pnpm workflow check-security-line --base "$BASE"
33
- - run: pnpm workflow check-phases --base "$BASE" --red-green $BACKFILL
34
-
35
- gitleaks:
36
- runs-on: ubuntu-latest
37
- steps:
38
- - uses: actions/checkout@v4
39
- with:
40
- fetch-depth: 0
41
- persist-credentials: false
42
- - uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7 # v2.3.9
43
- env:
44
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45
- GITLEAKS_ENABLE_COMMENTS: false
@@ -1,100 +0,0 @@
1
- # Workflow
2
-
3
- This repository builds every change spec first and test first. The rules below bind every contributor. CI checks them on each pull request. The git hooks run the same checks before a commit and a push.
4
-
5
- `synoikia-plugin workflow sync` writes this file from `@synoikia/create-plugin`. Do not edit it here. Change the template in `via-justa/synoikia-core` instead.
6
-
7
- ## Steps
8
-
9
- One change is one slice: one rule of one feature, with three scenarios at most. Each slice gets its own branch and pull request.
10
-
11
- 1. **Spec.** Write the scenarios in a feature file. Commit them as `spec: …`.
12
- 2. **Architecture and plan.** Write the build plan: the slices in order, and the existing code each one reuses. Put it in the pull request description. Place the slice in the model in `docs/architecture/` when it adds or moves a part. Commit as `arch: …`.
13
- 3. **Red.** Write the step definitions. Run the scenarios and see them fail because the behavior is missing. Commit as `test: …`.
14
- 4. **Green.** Write the least code that makes the scenarios pass. Use existing code that does the same work. Commit as `feat: …` or `fix: …`.
15
- 5. **Refactor.** Clean up with the scenarios green. Extract code that duplicates the same behavior into one shared function. Commit as `refactor: …`.
16
- 6. **Pull request.** Push and open the pull request. Fill in the template.
17
-
18
- ## Commits
19
-
20
- Each commit belongs to one phase. Its subject starts with the phase, and it changes only the files of that phase.
21
-
22
- | Prefix | Changes |
23
- | ---------------------- | ------------------------------------------------------------------ |
24
- | `spec:` | Feature files only |
25
- | `arch:` | The architecture model only |
26
- | `test:` | Step definitions, the World and unit tests only |
27
- | `feat:` `fix:` | Code. Not feature files and not the model |
28
- | `refactor:` | Code with the scenarios green. Not feature files and not the model |
29
- | `docs:` `chore:` `ci:` | Documents, tooling and CI. Not feature files and not the model |
30
-
31
- A `feat:` or `fix:` commit that changes product code needs a `test:` commit before it. CI checks out that `test:` commit and runs its feature files. They must fail there. CI then runs them at the head of the branch, where they must pass.
32
-
33
- A requirement that turns out wrong while you build is not worked around. Change it in its own `spec:` commit, where the reviewer sees it.
34
-
35
- Pull requests merge by rebase, so every commit lands on `main`. A `spec:` or `test:` commit is red by design. Skip it in `git bisect` with `git bisect skip`.
36
-
37
- ## Branches
38
-
39
- A branch name is `<component>/<summary>` in lowercase kebab-case. The summary is two to four words about the whole change: `core/auth-refactoring`.
40
-
41
- - The component is the package or plugin where the most important change lands, or `ci`, `docs`, `skills` or `deps`.
42
- - Do not use generated names, random words, session IDs or dates.
43
- - After a pull request merges, start follow-up work on a new branch.
44
-
45
- ## Feature files
46
-
47
- Feature files live in `features/<domain>/<feature>.feature` inside the package or plugin they specify. Steps and the World live next to them, in `features/**/*.ts`.
48
-
49
- - **One feature per file, with an `@id:<kebab-case>` tag.** Other files refer to the feature by this id. The id never changes after a push.
50
- - **Every scenario is in a `Rule:`.** A rule groups the scenarios that show one business rule.
51
- - **Write outcomes, not solutions.** Say what someone can do and what they see. Do not name screens, clicks, endpoints, status codes, wire formats or tables.
52
- - **Write short scenarios.** Use five steps at most, with one `When` and one `Then`. A `Background:` has four steps at most.
53
- - **Use real values from the World.** Name the World's things, not a category. Write `Given the instance "nas-01" has 3 pools`, not `Given an instance with pools`.
54
- - **Write what someone can see in a `Then`.** Name what the admin, the agent or the upstream service observes, not an internal verdict.
55
- - **Use the field's standard terms and the glossary's words.** Use each term with one meaning.
56
- - **Tags.** Use only `@id:<kebab-case>`, `@backlog`, `@long-running` and `@exclusive`. `@backlog` marks a scenario not built yet, `@long-running` a slow scenario, and `@exclusive` a scenario that must run alone in its test process.
57
- - **No comments.** Put an explanation in the feature narrative.
58
-
59
- Scenarios run in vitest through quickpickle. They drive the product through its real interface: the MCP endpoints, the Admin API, the plugin entry or the portal in a browser. They never call internal services and never mock internal modules.
60
-
61
- ## Tests
62
-
63
- Feature files are the only behavior tests. A new `*.test.ts` file must be a pure-function unit test in a `test/unit/` directory. Do not test libraries, frameworks or third-party APIs.
64
-
65
- ## Writing
66
-
67
- All prose follows ASD-STE100 Simplified Technical English. This includes documents, skills, feature files and pull request descriptions.
68
-
69
- - Write short sentences: 20 words at most for an instruction, 25 for a description.
70
- - Write one instruction per sentence. Use the active voice and approved plain words.
71
- - Do not use semicolons. Write two sentences.
72
- - Do not use em dashes.
73
- - Write one topic per paragraph.
74
- - Do not repeat a fact. Link to the place that states it.
75
- - Prefer tables and lists to long paragraphs.
76
-
77
- ## Security
78
-
79
- - Do not commit credential files. The pre-commit hook refuses `.env` files, private keys and secret files by name. CI runs gitleaks on every pull request.
80
- - A pull request that changes a security path needs a line of its own in its description: `Security audit: <boundary and findings>` or `Security audit: none. <why>`. The paths are in `synoikia.workflow.securityPaths` in the root `package.json`.
81
-
82
- ## Checks
83
-
84
- Install the git hooks once per clone:
85
-
86
- ```sh
87
- pnpm hooks:install
88
- ```
89
-
90
- The hooks run the `workflow` script of the branch that you have checked out. Before you check out a pull request from someone you do not trust, read its changes to `.githooks/` and `package.json`.
91
-
92
- | Command | Checks |
93
- | ------------------------------------------ | ------------------------------------------------------------ |
94
- | `pnpm workflow check-branch` | The branch name |
95
- | `pnpm workflow check-phases --base main` | Commit prefixes and phases. `--red-green` runs the red check |
96
- | `pnpm workflow check-features --base main` | Feature files, the slice size and new test files |
97
- | `pnpm workflow check-prose --base main` | The writing rules on added lines |
98
- | `pnpm workflow pre-push` | All of the above, as the pre-push hook runs them |
99
-
100
- A pull request labelled `backfill` specifies behavior that exists already. Its scenarios pass at once, so CI skips the red check and the slice size for it.
@@ -1,73 +0,0 @@
1
- // PreToolUse hook: denies git commands that create or push a branch whose name breaks docs/workflow.md › Branches.
2
- import { spawnSync } from 'node:child_process';
3
-
4
- let input = '';
5
- for await (const chunk of process.stdin) input += chunk;
6
- const { tool_input: toolInput = {}, cwd } = JSON.parse(input || '{}');
7
- const command = String(toolInput.command ?? '');
8
-
9
- const currentBranch = () =>
10
- spawnSync('git', ['symbolic-ref', '-q', '--short', 'HEAD'], {
11
- cwd: process.env.CLAUDE_PROJECT_DIR ?? cwd,
12
- encoding: 'utf8',
13
- }).stdout.trim();
14
- const names = new Set();
15
- for (const part of command.split(/&&|\|\|?|;|\n/)) {
16
- const words = part
17
- .trim()
18
- .split(/\s+/)
19
- .filter((w, i, all) => !/^\d*[<>]/.test(w) && !/^\d*[<>]+&?$/.test(all[i - 1] ?? ''));
20
- const at = words.findIndex((w) => !/^[A-Za-z_][A-Za-z0-9_]*=/.test(w));
21
- if (words[at] !== 'git') continue;
22
- const [sub, ...args] = words.slice(at + 1).filter((w, i, all) => !(i > 0 && all[i - 1] === '-C') && w !== '-C');
23
- const plain = args.filter((a) => !a.startsWith('-'));
24
- if ((sub === 'checkout' || sub === 'switch') && args.some((a) => /^-[bcBC]$/.test(a)))
25
- names.add(args[args.findIndex((a) => /^-[bcBC]$/.test(a)) + 1]);
26
- else if (
27
- sub === 'branch' &&
28
- plain.length &&
29
- !args.some((a) => /^-(?:d|D|l|a|r|v|vv|-list|-show-current|-delete)$/.test(a))
30
- )
31
- names.add(args.some((a) => /^-[mM]$/.test(a)) ? plain.at(-1) : plain[0]);
32
- else if (sub === 'push' && !args.some((a) => a === '-d' || a === '--delete')) {
33
- const refs = plain.slice(1).map((ref) => (ref.includes(':') ? ref.split(':').pop() : ref));
34
- for (const ref of refs.length ? refs : ['HEAD']) names.add(ref === 'HEAD' ? currentBranch() : ref);
35
- }
36
- }
37
-
38
- const clean = (n) =>
39
- n
40
- .replace(/^\+/, '')
41
- .replace(/^refs\/heads\//, '')
42
- .replace(/^['"]|['"]$/g, '');
43
- const denied = [];
44
- const unchecked = [];
45
- for (const name of [...names]
46
- .filter(Boolean)
47
- .map(clean)
48
- .filter((n) => n && n !== 'HEAD')) {
49
- if (!/^[A-Za-z0-9._/-]+$/.test(name)) {
50
- denied.push(`${name}: use letters, digits, ".", "_", "-" and "/" only`);
51
- continue;
52
- }
53
- const r = spawnSync('pnpm', ['run', '--silent', 'workflow', 'check-branch', name], {
54
- cwd: process.env.CLAUDE_PROJECT_DIR ?? cwd,
55
- encoding: 'utf8',
56
- });
57
- const out = `${r.stderr}${r.stdout}`.trim();
58
- if (r.status === 0) continue;
59
- if (out.startsWith('check-branch:')) denied.push(out.replace(/^check-branch: /gm, `${name}: `));
60
- else unchecked.push(`${name}: ${out.split('\n')[0] ?? 'the check did not run'}`);
61
- }
62
- const decide = (permissionDecision, permissionDecisionReason) =>
63
- console.log(
64
- JSON.stringify({
65
- hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision, permissionDecisionReason },
66
- }),
67
- );
68
- if (denied.length)
69
- decide(
70
- 'deny',
71
- `Branch name breaks docs/workflow.md › Branches. Use <component>/<two to four words>.\n${denied.join('\n')}`,
72
- );
73
- else if (unchecked.length) decide('ask', `Could not check the branch name:\n${unchecked.join('\n')}`);
@@ -1,44 +0,0 @@
1
- ---
2
- name: architect
3
- description: >-
4
- Plan the build and place it in the LikeC4 model in docs/architecture, by interviewing the user on each design
5
- decision, layer by layer in arc42's views. Use it after the spec and before code, for every task. It replaces
6
- plan mode: its build plan says which slices come in which order.
7
- ---
8
-
9
- # Architect
10
-
11
- **In:** the feature files of the task, with the first slice selected.
12
- **Out:** the build plan, and the task placed in the LikeC4 model in `docs/architecture/` with an `arch:` commit.
13
-
14
- Write only the model and the plan. Do not write code or diagram files.
15
-
16
- 1. **Read the model.** If there is no model, this slice starts it, with just enough to place the slice.
17
- 2. **Ask the design into the model, layer by layer.** Follow arc42's order: context and scope, then the building blocks level by level, then deployment. Ask in rounds, as `change-workflow` says. Write each answer into the model before the next round.
18
- 3. **Send behavior questions back.** A question about what the product does belongs to the spec. Return it to `requirements-engineer`. Do not settle it in the model.
19
- 4. **Write the build plan.** List the slices in order. For each slice, give its rule, the parts of the model it changes, and the slices it needs first. Name the existing code that each slice reuses or extracts. Ask the user about the order in one last round.
20
- 5. **Push.** When no question is open and the user agrees, commit the model as `arch: …` and push. Put the build plan in the pull request description. Later slices update the plan in their own pull requests.
21
-
22
- ## Rules for the model
23
-
24
- - Views follow arc42. Goals and quality live in the feature files.
25
- - A box with parts of its own gets a view at the next level.
26
- - A building-block view holds its subject's children and their direct neighbors. An element appears at one level only in a view.
27
- - Add a dynamic view only for a complex sequence: many elements, an order that matters, an asynchronous hand-off or a failure path. Never add one for each scenario.
28
- - **State a fact once.** A description says what an element is, in one sentence. What it does to another element is a relation. How a story runs is the feature file.
29
- - Applications share no storage. One application reaches another only through its API.
30
- - Model your own parts. A library you use is a technology line. A package you write is a `library` element.
31
- - Names come from the field's standard. Ask, as `change-workflow` says.
32
- - The design document links the views. It does not repeat them.
33
-
34
- ## Layout
35
-
36
- - `likec4.config.mjs`: the project and its summary.
37
- - `models/base-model.c4`: element kinds, people, external systems, the system and its applications.
38
- - `models/<part>.c4`: one file for each container or package. Each file extends its parent.
39
- - `models/deployment.c4`: where each part runs.
40
- - `views/views.c4`: every view.
41
-
42
- ## Done when
43
-
44
- No question is open, the user agrees the build plan, and the model places the next slice.
@@ -1,70 +0,0 @@
1
- ---
2
- name: change-workflow
3
- description: >-
4
- How to carry a change from request to merged PR: size it, plan it, then run one slice at a time through
5
- requirements, architecture and build, spec first and test first. Use it at the start of every task that will
6
- change code, config, CI, tests or docs in this repo, even when the request is a question, a bug report or
7
- "just do X", and before writing a plan. Examples: add a feature, an operation or an endpoint; fix a bug;
8
- refactor a module; migrate a library; change the schema, auth or the gate; bump versions; "can you clean up
9
- X". Not for questions that change nothing (explain, review, estimate), or for PR babysitting on a PR that
10
- already exists.
11
- ---
12
-
13
- # Change workflow
14
-
15
- **The user decides. You build what the user decided.** The rules for specs, commits, branches, tests and prose are in `docs/workflow.md`. Read it before the first step. This skill says how you run them.
16
-
17
- ## 1. Size the task
18
-
19
- | Small | Big |
20
- | -------------------------------------------------- | ------------------------------------------------------- |
21
- | One concern in one package or plugin | Several concerns, packages or plugins |
22
- | One rule, three scenarios at most | More than one slice |
23
- | No security path in `CLAUDE.md`, or a one-line fix | A security path, an API contract, the SDK or the schema |
24
-
25
- Check the request against the repo before you plan. If the work is done already or the premise is wrong, show the evidence and ask what the user meant. If you are not sure of the size, treat the task as big.
26
-
27
- Do not use plan mode. The requirements and architecture steps are the plan:
28
-
29
- - `requirements-engineer` specifies the whole task wide. Every scenario outside the first slice gets `@backlog`.
30
- - `architect` places the task in the model and writes the build plan: the slices in order, with what each one needs first.
31
- - The user agrees the spec and the plan before any code. Each slice is then one pull request into `main`.
32
-
33
- ## 2. Run one slice
34
-
35
- 1. **Branch.** Create a branch from `main` with a name that passes `pnpm workflow check-branch`. Do not use a session's generated branch name.
36
- 2. **Requirements.** Use `requirements-engineer`. Its output is the feature file and a `spec:` commit.
37
- 3. **Architecture.** Use `architect`. Its output is the build plan and, when the slice adds or moves a part, an `arch:` commit.
38
- 4. **Build.** Use `developer`. Its output is the `test:`, `feat:` or `fix:` and `refactor:` commits and a ready pull request.
39
-
40
- Move to the next step only when the user agrees that the current step is done. Skipping a step is the user's decision. Propose it and wait for a clear yes.
41
-
42
- ## 3. Ask in rounds
43
-
44
- **Facts are yours. Decisions are the user's.** Find what the code, the specs and the model can tell you. Ask about everything that someone could decide in a different way.
45
-
46
- - Ask with `AskUserQuestion`, four questions at most for each call. Put your recommendation first and mark it "(Recommended)".
47
- - Write each answer into the file before you ask the next round.
48
- - Names come from the field's standard. Offer two or three terms with their source and ask. Do not pick a name silently.
49
-
50
- ## 4. Subagents
51
-
52
- Subagents keep your context small. They do not change the structure of the work.
53
-
54
- - You own the slice, the branch, the commits and the pull request. Phases run in order, never in parallel.
55
- - You run the interviews and write the feature file yourself.
56
- - Give a subagent one bounded task with fixed inputs. Example: "Write the steps for `features/gate/deny.feature`. They must fail on a missing behavior, not on missing glue."
57
- - The subagent returns a short summary and its diff. You run the scenarios, check red or green, and make the commit.
58
- - The history must look the same as a run without subagents. CI checks the phases.
59
-
60
- ## 5. The pull request
61
-
62
- - Open the pull request as a draft after the `spec:` commit. Watch it with `subscribe_pr_activity` until it merges or closes.
63
- - Run the repo's checks (`CLAUDE.md` › Commands) and `pnpm workflow pre-push` before each push.
64
- - Run the `security-reviewer` subagent when the diff touches a security path. Put its `Security audit:` line in the pull request description.
65
- - Mark the pull request ready only when every scenario of the slice is green and CI is green on its head.
66
- - When the change touches a user interface, send screenshots of each changed page and state before the pull request goes ready. Cover light and dark mode, and desktop and mobile width when the layout changed.
67
-
68
- ## 6. Long tasks
69
-
70
- A task that runs for more than about an hour needs tool calls that run without approval. If the session is not in Auto mode, say so and suggest **Auto** in the mode menu next to the prompt box. Do not change the mode yourself.
@@ -1,57 +0,0 @@
1
- ---
2
- name: developer
3
- description: >-
4
- Build one slice test first: the Gherkin scenarios run as the tests through quickpickle in vitest, against the
5
- product's real interface, red then green then refactor. Audit a slice that crosses a trust boundary, then mark
6
- the PR ready. Use it once the user agreed the feature file and, when needed, the model.
7
- ---
8
-
9
- # Developer
10
-
11
- **In:** the feature file, the model in `docs/architecture/` and the design document.
12
- **Out:** working code for the slice, and its pull request marked ready.
13
-
14
- **Build only a small slice.** The slice is the scenarios that are not `@backlog` and not green yet: one rule, three scenarios at most. If there are more, or none, stop. Ask the user to select a slice with `requirements-engineer`.
15
-
16
- **The spec, the model and the design document win over the prompt.** If they are missing, contradict each other or say nothing about what you need, stop and ask the user.
17
-
18
- **The spec is read-only.** A scenario that is wrong or cannot be built goes back to `requirements-engineer`. Never change the feature file to make it pass.
19
-
20
- ## The World
21
-
22
- The feature files are what runs. Quickpickle runs them in vitest. The steps drive the product through its real interface:
23
-
24
- - the MCP endpoints and the Admin API over HTTP
25
- - a plugin through the core harness
26
- - the portal in a browser with Playwright
27
-
28
- Steps never call internal services and never mock internal modules.
29
-
30
- The World sets up what the scenarios name, from synthetic data. It uses the product's test entry points, such as `@synoikia/core/testing` and `startFakeHttp`. If the World needs a new entry point, add it to the product's testing API in its own `test:` commit. A fake identity provider is an example.
31
-
32
- ## Loop
33
-
34
- 1. **Run the slice. See it red.** The undefined steps are the work list.
35
- 2. **Write the next scenario's steps.** Keep them plain, specific to the scenario and with their values written out. Run them. They must fail because the behavior is missing, not because the glue is broken. Commit as `test: …`.
36
- 3. **Write the least code that makes the scenario pass.** Search first for code that does the same work: a helper, a service, a schema or a component. Use it. Commit as `feat: …` or `fix: …`.
37
- 4. **Refactor** with the scenario green. Find code that duplicates the same behavior, in this slice or in existing code. Extract it into one shared function and make each caller use it. Commit as `refactor: …`.
38
- 5. **Repeat** until every scenario of the slice is green.
39
-
40
- ## Unit tests
41
-
42
- Write a unit test only for a pure function that is worth a check of its own. Put it in `test/unit/`. Never test a library, a framework or a third-party API.
43
-
44
- ## Audit
45
-
46
- Run the `security-reviewer` subagent when the slice crosses a trust boundary. Examples are an entry point, auth, crypto, secrets, TLS, the sandbox, the permission gate, dependencies and CI. Untrusted input that reaches an interpreter is one too. Fix a confirmed finding test first. Put the result in the pull request description on a line of its own:
47
-
48
- - `Security audit: <the boundary and what the review found>`
49
- - `Security audit: none. <why the slice crosses no boundary>`
50
-
51
- ## Pull request
52
-
53
- Run `pnpm workflow pre-push` and the repo's checks. Push and mark the pull request ready. Its description names the scenarios it makes green.
54
-
55
- ## Done when
56
-
57
- Every scenario of the slice is green and the suite passes. There is no code that the scenarios do not need, and no code that does the same work twice. The audit ran if it was needed, and the pull request is ready.
@@ -1,59 +0,0 @@
1
- ---
2
- name: requirements-engineer
3
- description: >-
4
- Turn a rough idea, a bug report or existing behavior into a Gherkin feature file by interviewing the user one
5
- scenario at a time, and cut it into thin slices. Use it to specify what to build before any design or code,
6
- and to backfill a spec for behavior that exists already.
7
- ---
8
-
9
- # Requirements engineer
10
-
11
- **In:** a rough idea, a bug report, or a part of the design document to backfill.
12
- **Out:** a feature file in `features/<domain>/<feature>.feature` and a `spec:` commit.
13
-
14
- The feature file rules are in `docs/workflow.md` › Feature files. Read them first.
15
-
16
- ## Requirements come from the user
17
-
18
- Ask for the requirements. Do not invent them, and do not read them out of the code. Code shows what exists, not what should exist. A spec copied from code keeps its accidents.
19
-
20
- In **backfill** mode, the design document and the existing tests are the source. Turn each statement into a scenario and show it to the user. The user confirms, changes or removes it. Label the pull request `backfill`.
21
-
22
- ## Plan wide, build small
23
-
24
- Specify as much as the user wants. Before the push, the user selects the slice to build next: one rule, three scenarios at most. Tag every other scenario `@backlog`.
25
-
26
- Recommend the thinnest slice yourself, and say what you left out:
27
-
28
- - **The simplest case first.** One actor, one value, the case that ends well.
29
- - **One rule.** Include the case that it refuses, because that case states the rule.
30
- - **The extras last.** Speed, configuration and rare edges are slices of their own.
31
-
32
- Split further by SPIDR: spike, path, interface, data, rules.
33
-
34
- Put everything the slice does not need in a `@backlog` scenario. Nothing gets lost, and nothing rides along.
35
-
36
- ## One scenario at a time
37
-
38
- Never write a second scenario before the user agrees the first. A file with scenarios the user has not seen one by one is a guess.
39
-
40
- 1. **Find where it lives.** Read the `features/` folders first. If a feature covers the behavior already, extend that file.
41
- 2. **Get one example.** Ask what happened, or what would happen: who did what, to what, and what they saw. Write it with its values. Then find the wording that makes it general.
42
- 3. **Ask what else is true.** Ask for the case that is refused, the case where nothing arrives, and the case that goes the other way. A slice where every scenario ends well states no rule.
43
- 4. **Ask only what the product does.** The folders and the wording are yours. How it gets built is the architect's.
44
-
45
- ## The World
46
-
47
- The World is the set of synthetic things that the scenarios run in: instances, plugins, agents, roles and their values. Build it in the first slices and grow it slice by slice. People appear by role or by a made-up number, never by a real name. Later scenarios name the World's things, never placeholders.
48
-
49
- ## Changing a rule
50
-
51
- When you remove or loosen a rule, list every scenario, skill line and document that names it. Change them all in the same slice. Ask the user whether stored data breaks under the new rule.
52
-
53
- ## Push
54
-
55
- Read the file again against the rules and ask about what you find in one last round. When the user agrees, commit as `spec: …`, push and open a draft pull request.
56
-
57
- ## Done when
58
-
59
- No question is open, the user agrees the spec, and the user selected the slice to build.
@@ -1,35 +0,0 @@
1
- ---
2
- name: technical-writing
3
- description: >-
4
- How to write prose in this repo: ASD-STE100 Simplified Technical English, short sentences, no semicolons, no
5
- em dashes, one topic per paragraph, no repetition. Use it before you write or change any document, README,
6
- design section, skill, feature file, commit message body or pull request description.
7
- ---
8
-
9
- # Technical writing
10
-
11
- The rules are in `docs/workflow.md` › Writing. `pnpm workflow check-prose` checks the mechanical ones. This skill says how to apply them.
12
-
13
- ## Sentences
14
-
15
- - Write 20 words at most in an instruction and 25 at most in a description.
16
- - Write one instruction in each sentence. Start an instruction with a verb: "Run the checks", not "The checks should be run".
17
- - Use the active voice and simple tenses: present, past and future.
18
- - Use approved plain words. Write "use", not "utilize". Write "start", not "commence". Write "show", not "demonstrate".
19
- - Use a term with one meaning only. Use the glossary's terms where a glossary exists.
20
- - Do not use semicolons. Write two sentences.
21
- - Do not use em dashes. Write two sentences, or use a colon before a list or an example.
22
-
23
- ## Paragraphs and structure
24
-
25
- - Write one topic in each paragraph. Start the paragraph with its topic.
26
- - Use a table or a list when you compare items or give steps.
27
- - Give the steps of a procedure as a numbered list, one action for each step.
28
- - Do not repeat a fact. State it in one place and link to that place.
29
- - Describe what is true now. Put history in commit messages and pull requests.
30
-
31
- ## Check your text
32
-
33
- 1. Read each sentence. Cut each word that adds nothing.
34
- 2. Split each sentence that holds two statements.
35
- 3. Run `pnpm workflow check-prose --base main`.