janissary 0.5.1 → 0.5.2

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 (69) hide show
  1. package/ai/guidelines/architecture-principles.md +75 -0
  2. package/ai/guidelines/code-guidelines.md +17 -0
  3. package/ai/guidelines/conventional-commits.md +192 -0
  4. package/ai/guidelines/developer-documentation.md +124 -0
  5. package/ai/guidelines/documentation.md +80 -0
  6. package/ai/guidelines/human-writing-guidelines.md +42 -0
  7. package/ai/guidelines/imports-and-barrel-files.md +49 -0
  8. package/ai/guidelines/pull-request-automation.md +98 -0
  9. package/ai/guidelines/strategies-for-readable-summaries.md +27 -0
  10. package/ai/guidelines/user-documentation.md +177 -0
  11. package/ai/personas/algorithm.md +14 -0
  12. package/ai/personas/assistant.md +25 -0
  13. package/ai/personas/link-scout.md +16 -0
  14. package/ai/personas/researcher.md +12 -0
  15. package/ai/personas/security.md +12 -0
  16. package/ai/personas/summarizer.md +11 -0
  17. package/ai/tasks/build-a-feature.md +133 -0
  18. package/ai/tasks/fix-a-small-issue.md +138 -0
  19. package/ai/tasks/improve-codebase.md +187 -0
  20. package/ai/tasks/improve-modularity.md +188 -0
  21. package/ai/tasks/improve-namespacing.md +253 -0
  22. package/ai/tasks/improve-plan.md +121 -0
  23. package/ai/tasks/improve-security.md +144 -0
  24. package/ai/tasks/improve-style.md +147 -0
  25. package/ai/tasks/improve-test-coverage.md +178 -0
  26. package/ai/tasks/merge-change-to-master.md +144 -0
  27. package/ai/tasks/open-feature-pull-request.md +161 -0
  28. package/ai/tasks/plan-ready-features.md +154 -0
  29. package/ai/tasks/prepare-workspace.md +35 -0
  30. package/ai/tasks/quick-commit.md +82 -0
  31. package/ai/tasks/reduce-complexity.md +185 -0
  32. package/ai/tasks/remove-deadcode.md +206 -0
  33. package/ai/tasks/remove-duplication.md +202 -0
  34. package/ai/tasks/update-package.md +137 -0
  35. package/package.json +4 -2
  36. package/scripts/changed-files.mjs +22 -0
  37. package/scripts/check-diff.mjs +100 -0
  38. package/scripts/coverage-file.mjs +85 -0
  39. package/scripts/docs-screenshots/capture.mjs +82 -0
  40. package/scripts/docs-screenshots/fixtures/docs/api.md +3 -0
  41. package/scripts/docs-screenshots/fixtures/docs/guide.md +3 -0
  42. package/scripts/docs-screenshots/fixtures/page.html +31 -0
  43. package/scripts/docs-screenshots/fixtures/profiles/demo/editor.json +1 -0
  44. package/scripts/docs-screenshots/fixtures/profiles/demo/writer.json +1 -0
  45. package/scripts/docs-screenshots/fixtures/sample.md +26 -0
  46. package/scripts/docs-screenshots/fixtures/sample.png +0 -0
  47. package/scripts/docs-screenshots/fixtures/sample.ts +25 -0
  48. package/scripts/docs-screenshots/fixtures/src/app.ts +2 -0
  49. package/scripts/docs-screenshots/fixtures/src/tides.ts +2 -0
  50. package/scripts/docs-screenshots/janus.mjs +51 -0
  51. package/scripts/docs-screenshots/manifest.mjs +122 -0
  52. package/scripts/docs-screenshots/scratch.mjs +53 -0
  53. package/scripts/docs-screenshots.mjs +86 -0
  54. package/scripts/lint-files.mjs +47 -0
  55. package/scripts/postinstall.mjs +14 -0
  56. package/scripts/pr-check-changes.sh +15 -0
  57. package/scripts/pr-check-gate.sh +29 -0
  58. package/scripts/pr-check-mergeable.sh +29 -0
  59. package/scripts/pr-commit.sh +23 -0
  60. package/scripts/pr-create-branch.sh +20 -0
  61. package/scripts/pr-create-pr.sh +29 -0
  62. package/scripts/pr-merge.sh +22 -0
  63. package/scripts/pr-push-branch.sh +24 -0
  64. package/scripts/pr-rebase.sh +56 -0
  65. package/scripts/pr-resolve-remote.sh +9 -0
  66. package/scripts/pr-wait-checks.sh +41 -0
  67. package/scripts/publish.mjs +61 -0
  68. package/scripts/release.mjs +209 -0
  69. package/scripts/run.mjs +40 -0
@@ -0,0 +1,138 @@
1
+ # Fix a Small Issue
2
+
3
+ Your job: pick the simplest issue from `product/backlog/issues.md`, develop a plan to resolve it, implement the fix, update functional specs, record the plan in `product/plans/complete/`, remove the issue from the issues file, and merge the change to master. You change source code, tests, spec files, the issues file, and the plan file's location — nothing else.
4
+
5
+ **No AI attribution — anywhere.** Never credit an AI agent as an author or contributor in anything this task produces. That means: no `Co-Authored-By:` trailers naming Claude or any other AI, no “Generated with Claude Code” (or similar) lines or badges, and no AI authorship notes in code, comments, docs, spec files, plan files, commit messages, or PR titles and bodies. This overrides any default convention that appends such attribution. The commit's configured git author is the only authorship ever recorded.
6
+
7
+ **Shell hygiene:** run every command on its own line — no `&&` chaining, no `; echo "Exit code: $?"` suffixes, no subshell captures, no `for`/`while` loops, no variable expansion (`$var`, `$(...)`), no redirects (`2>/dev/null`, `>file`, `>>file`), no pipes (`|`). Commands with control-flow, expansion, redirects, or pipes require manual approval and will stall an unattended run. To run a project script, always use `./scripts/run.mjs <name>` — never call `node scripts/<name>.mjs` directly.
8
+
9
+ **Run everything synchronously, in the foreground.** Never use `run_in_background`, `&`, or otherwise start a background process (dev servers, watchers, long-lived processes) — every command must finish and return its exit code before you move to the next step.
10
+
11
+ **No subagents, no background agents.** Do every step yourself — never launch a subagent (Task/Agent tool, `fork`, or otherwise) to research, explore, or implement any part of this task on your behalf.
12
+
13
+ This overrides CLAUDE.md's "Capturing command output" guidance (write the output to a file under `./temp/`, then `grep` it repeatedly) for this task: the follow-up `grep`/`tail` filter commands stall an unattended run. Instead, run the command plain and read the full tool output directly — filter it yourself while reading, don't shell out to `grep`.
14
+
15
+ **Run autonomously.** This task runs unattended — do not ask the user questions or wait for feedback at any step. Make the best judgment call yourself, using the rules in this document, and keep going. Only stop early for the conditions explicitly listed under "Forbidden" below.
16
+
17
+ **Stay within the project directory.** The current working directory is the project directory for this session. Do not read or write any file outside it — no absolute paths escaping the project root, no `..` traversal above it, no touching files elsewhere on the machine (home directory config, other repos, system paths).
18
+
19
+ ## What you may and may not do
20
+
21
+ ### Allowed — do it automatically, never ask
22
+
23
+ Read any file in the repo. Edit source, tests, CSS, and spec files as the fix requires. Write a plan file to `product/plans/complete/`. Remove the fixed issue from `product/backlog/issues.md`. Run `./scripts/run.mjs check-diff` after each change. Execute the full merge workflow via `ai/tasks/merge-change-to-master.md` when implementation is done.
24
+
25
+ ### Forbidden — no exceptions
26
+
27
+ 1. **Editing files the fix does not touch.** Stay in scope. If you discover a fix requires changes beyond what you planned, update the plan first — do not silently expand scope.
28
+ 2. **Running `npm run check`.** That is the human's end-of-work gate. Use `./scripts/run.mjs check-diff` during development.
29
+ 3. **Skipping tests.** Every fix needs tests that cover the changed behavior. Verify with `./scripts/run.mjs check-diff`.
30
+ 4. **Choosing an issue that requires significant new architecture.** If an issue would require high complexity error or prone work, pick a simpler issue instead and report why.
31
+ 5. **Editing `product/backlog/issues.md` beyond removing the fixed entry.** Only remove the line for the issue you fixed — do not reorder, rephrase, or otherwise modify the remaining entries.
32
+ 6. **Merging before all checks pass.** The `ai/tasks/merge-change-to-master.md` workflow handles merge; do not bypass it.
33
+
34
+ ---
35
+
36
+ ## Step 0 — Prepare the workspace
37
+
38
+ Execute `ai/tasks/prepare-workspace.md` in full before doing anything else.
39
+
40
+ ---
41
+
42
+ ## Step 1 — List small fixes and pick the first available
43
+
44
+ 1. Read `product/backlog/issues.md` and list every issue.
45
+ 2. For each issue, assess the complexity by reviewing the codebase to understand what areas it touches. Do not use a shell loop for this.
46
+ 3. If no issues exist, report "No issues in `product/backlog/issues.md`" and stop.
47
+ 4. If every issue requires significant new architecture (rating 7+), report the list with assessments and stop — do not pick one.
48
+ 5. Otherwise, pick the **first** issue listed in the file (top of the list). State your pick and why.
49
+
50
+ ---
51
+
52
+ ## Step 2 — Develop a plan
53
+
54
+ 1. Read the project constraints in [`CLAUDE.md`](../../CLAUDE.md): ESLint rules (200-line `max-lines`, `.js` import extensions in `src/`, type-aware rules), test conventions (`src/**/*.test.ts`, `web/src/**/*.test.tsx`).
55
+ 2. Read every file relevant to the fix to understand the code involved.
56
+ 3. Write a plan file following the format of existing plans in `product/plans/complete/` — include a complexity rating, goal, approach, implementation steps, tests, and out-of-scope items. Write it to `product/plans/draft/<fix-name>.md`.
57
+ 4. After the plan is written, move it from `product/plans/draft/` to `product/plans/ready/`:
58
+ ```bash
59
+ git mv product/plans/draft/<fix-name>.md product/plans/ready/<fix-name>.md
60
+ ```
61
+
62
+ ---
63
+
64
+ ## Step 3 — Implement the fix
65
+
66
+ Follow the plan's implementation steps **in order**. After each step:
67
+
68
+ 1. Run `./scripts/run.mjs check-diff` to catch lint, typecheck, and test failures immediately.
69
+ 2. Fix any failures before moving to the next step.
70
+ 3. If a step produces a file over the 200-line limit, extract into a new module per `ai/guidelines/code-guidelines.md` — do not compact code, strip comments, or delete spacing.
71
+
72
+ Key rules during implementation:
73
+
74
+ - **Match existing conventions.** Use the same libraries, patterns, and naming the surrounding code uses. Check `package.json` or the file's existing imports before assuming a library is available.
75
+ - **Import extensions.** Relative imports in `src/` must carry `.js` (NodeNext). Relative imports in `web/src/` stay extensionless.
76
+ - **No comments unless the plan specifies them.** Write clean code; let it speak for itself.
77
+
78
+ ---
79
+
80
+ ## Step 4 — Write the tests
81
+
82
+ If the plan has a Tests section, implement every test case listed. Mirror the test style of the referenced test files (imports, helper patterns, assertion style).
83
+
84
+ Run `./scripts/run.mjs check-diff` after writing tests. All tests must pass.
85
+
86
+ ---
87
+
88
+ ## Step 5 — Update or create spec files
89
+
90
+ Every fix must be reflected in the functional specs under `product/specs/`. After implementation and tests:
91
+
92
+ 1. **Check the plan.** If the plan names specific spec files to update or create, do exactly that.
93
+ 2. **Otherwise, find the right spec.** Read the existing specs in `product/specs/` and identify which one(s) the fix relates to. Most fixes extend an existing spec. If no existing spec covers the area, create a new one.
94
+ 3. **Write or update the spec.** Follow the existing conventions: `# Title` at the top, `### Subsection` for each aspect, prose describing user-visible behavior only — no code, no implementation details, no file paths. The spec is what the fix *does*, not how it is built. Keep additions concise and factual.
95
+
96
+ Spec files are markdown and do not affect `check-diff`, so no verification run is needed after this step.
97
+
98
+ ---
99
+
100
+ ## Step 6 — Promote the plan and remove the issue
101
+
102
+ 1. Move the plan file from `product/plans/ready/` to `product/plans/complete/`:
103
+ ```bash
104
+ git mv product/plans/ready/<fix-name>.md product/plans/complete/<fix-name>.md
105
+ ```
106
+ 2. Remove the fixed issue's line from `product/backlog/issues.md`. Only remove that single line — do not modify any other content in the file.
107
+
108
+ ---
109
+
110
+ ## Step 7 — Final verification
111
+
112
+ 1. Run `./scripts/run.mjs check-diff` one last time. It must pass clean.
113
+ 2. Manually verify the behavior if the plan's Verification section describes manual steps. If manual verification is not possible in this environment, note that in the report.
114
+
115
+ ---
116
+
117
+ ## Step 8 — Merge the change to master
118
+
119
+ Execute `ai/tasks/merge-change-to-master.md` in full. That document owns the merge workflow — follow its steps without deviation.
120
+
121
+ ---
122
+
123
+ ## Step 9 — Report
124
+
125
+ Give the user a short report in this exact shape:
126
+
127
+ ```
128
+ Issue: <the issue text from product/backlog/issues.md>
129
+ Plan: product/plans/ready/<file> → product/plans/complete/<file>
130
+ Complexity: N/10
131
+ Implementation: <one-line summary of the fix>
132
+ Tests: <count> new tests across <files>
133
+ Spec: <spec file(s) created or updated, with one-line description of change>
134
+ PR: <url> (#<number>)
135
+ Status: merged
136
+ ```
137
+
138
+ Keep it brief. Done.
@@ -0,0 +1,187 @@
1
+ # Improve code base
2
+
3
+ Your job: act as a **supervisor** that continuously improves this codebase by running a loop, entirely by yourself — no subagents, no background agents. Each cycle you **inspect** the code, **select** the single most valuable improvement, **execute** the matching task playbook yourself, **verify** the result, **ship it to `master` through a full pull request**, and then **start the next cycle**. You own the judgment around it: what to work on, whether the result is genuinely good, and when to stop.
4
+
5
+ The improvement work itself follows one of these existing single-purpose task playbooks — you pick the right one each cycle and execute it yourself, inline, in this same session:
6
+
7
+ | Signal you see when inspecting | Task to execute |
8
+ | --- | --- |
9
+ | A `max-lines` error, or a high FTA score on a long file | [`improve-modularity.md`](improve-modularity.md) |
10
+ | A `sonarjs/cognitive-complexity` warning on a function | [`reduce-complexity.md`](reduce-complexity.md) |
11
+ | A flat cluster of files sharing a naming prefix (`src/acp-*`, `src/agent-*`, …) | [`improve-namespacing.md`](improve-namespacing.md) |
12
+ | Knip reports unused files / exports / dependencies | [`remove-deadcode.md`](remove-deadcode.md) |
13
+ | jscpd reports a duplicated block | [`remove-duplication.md`](remove-duplication.md) |
14
+ | Coverage is below threshold on a testable file | [`improve-test-coverage.md`](improve-test-coverage.md) |
15
+ | `npm audit` / security tooling reports a patchable advisory | [`improve-security.md`](improve-security.md) |
16
+ | stylelint reports a CSS issue | [`improve-style.md`](improve-style.md) |
17
+ | `npm outdated` lists a safe-looking package update | [`update-package.md`](update-package.md) |
18
+
19
+ **No AI attribution — anywhere.** Never credit an AI agent as an author or contributor in anything this task produces. That means: no `Co-Authored-By:` trailers naming Claude or any other AI, no “Generated with Claude Code” (or similar) lines or badges, and no AI authorship notes in code, comments, docs, spec files, plan files, commit messages, or PR titles and bodies. This overrides any default convention that appends such attribution. The commit's configured git author is the only authorship ever recorded.
20
+
21
+ **Run autonomously.** This task runs unattended — do not ask the user questions or wait for feedback at any step. Make the best judgment call yourself, using the rules in this document, and keep going. The only reasons to stop are the ones listed in "When to stop the loop" below.
22
+
23
+ **No subagents, no background agents.** Do every step yourself, in this session — never launch a subagent (Task/Agent tool) to execute a playbook or any part of one, and never hand work off to a background agent. The playbooks referenced below are instructions for *you* to follow directly, not prompts to delegate.
24
+
25
+ **Shell hygiene:** run every command on its own line — no `&&` chaining, no `; echo "Exit code: $?"` suffixes, no subshell captures. The exit code and output are visible in the tool result. To run a project script, always use `./scripts/run.mjs <name>` — never call `node scripts/<name>.mjs` directly.
26
+
27
+ **Run everything synchronously, in the foreground.** Never use `run_in_background`, `&`, or otherwise start a background process (dev servers, watchers, long-lived processes) — every command must finish and return its exit code before you move to the next step.
28
+
29
+ **Ship every verified change to `master`.** After you verify a cycle's improvement (Step 4), you do not stop at a local commit — you hand the change off to [`merge-change-to-master.md`](merge-change-to-master.md), which commits it as a single-author Conventional Commits commit, opens a pull request against `master`, resolves any conflicts, waits for required checks, and squash-merges it into `master` on GitHub. Each cycle therefore lands as its own isolated, reviewed PR. If that task cannot land the change — conflicts it can't resolve after its retries, or a failing required check — it leaves the PR **open** for a human; treat that cycle as **not merged**, record it, and move on. Never force the merge or hand-edit `master` yourself.
30
+
31
+ ---
32
+
33
+ ## Step 0 — Prepare the workspace (once, before the loop)
34
+
35
+ Execute [`prepare-workspace.md`](prepare-workspace.md) in full before doing anything else. Do this **once** to set up the workspace; the loop then reuses it. Because each cycle merges its change to `master` on GitHub (Step 5) and resyncs the workspace to the updated `master` (Step 6), re-pulling between cycles is safe and expected — there are no unmerged local commits to clobber.
36
+
37
+ Then establish a clean starting point:
38
+
39
+ ```bash
40
+ git status
41
+ ```
42
+
43
+ The working tree **must be clean** before you start. If it is not, STOP and report — do not start a supervised loop on top of uncommitted changes you did not make.
44
+
45
+ Decide how many cycles to run. If the user gave a number, use it. Otherwise default to **5 cycles**, and always honor the stopping conditions below — a smaller effective number is fine.
46
+
47
+ ---
48
+
49
+ ## The loop
50
+
51
+ Repeat Steps 1–6 until a stopping condition is met. Keep a running **ledger** (a short table you maintain in your head and print in the final report): cycle number, task executed, target, before→after metric, PR number/URL, outcome.
52
+
53
+ ### Step 1 — Inspect the code (take a fresh snapshot)
54
+
55
+ Run the diagnostics fresh every cycle — never trust numbers from an earlier cycle, since the previous commit changed the tree:
56
+
57
+ ```bash
58
+ npm run typecheck 2>&1
59
+ npm run lint 2>&1
60
+ npm run quality 2>&1
61
+ npm run duplication 2>&1
62
+ npm run knip 2>&1
63
+ npm run lint:css 2>&1
64
+ npm outdated 2>&1
65
+ ```
66
+
67
+ - **TypeScript / tests must be green to begin a cycle.** If `npm run typecheck` errors, STOP the loop and report — the tree is broken and no improvement should be layered on top. (Tests are validated per-task as you follow the chosen playbook, and re-checked in Step 4.)
68
+ - Read the signals into the selection table at the top of this file: FTA scores and `max-lines` from `quality`/`lint`, `cognitive-complexity` warnings from `lint`, clones from `duplication`, unused code from `knip`, coverage gaps (run `npm run coverage 2>&1` when test-coverage is a candidate), CSS issues from `lint:css`, prefix clusters from the file layout under `src/`, and outdated packages from `npm outdated` (`npm outdated` exits non-zero when it lists anything — that's expected, not a broken tree).
69
+
70
+ Record the specific number for whatever you're about to target (the FTA score, the complexity value, the clone count, etc.) — this is the **before** value you will compare against in Step 4.
71
+
72
+ ### Step 2 — Select exactly one improvement
73
+
74
+ Choose the **single** highest-value improvement for this cycle:
75
+
76
+ 1. Rank the live signals by impact. A `max-lines` **error** (blocks the build gate) outranks a mere warning; a high-severity `npm audit` advisory outranks a cosmetic CSS nit; a large clone or a badly over-limit complexity function outranks a marginal one.
77
+ 2. **Skip anything a prior cycle already failed on.** If cycle N tried task T on target X and you had to revert it (Step 4), do not pick the same (task, target) again — pick the next-best signal.
78
+ 3. **Rotate to avoid starvation.** All else roughly equal, prefer a task type you have not run recently this session, so the codebase improves broadly rather than grinding one dimension.
79
+ 4. If **no** signal points to a worthwhile, safe improvement — every candidate is blocked, trivial, or already-failed — **stop the loop** (see "When to stop").
80
+
81
+ State your pick in one sentence: the task playbook, the target file/function, and the before-number. Add a new row to your ledger.
82
+
83
+ ### Step 3 — Execute the chosen playbook yourself
84
+
85
+ Follow [`ai/tasks/<task>.md`](.) for the task you picked in Step 2, in full, in this same session — you are the one carrying out every step of it, not a subagent. A few adjustments to how you run it here:
86
+
87
+ 1. **Skip that playbook's "Step 0 — Prepare the workspace"** — the workspace is already prepared and synced to `master`, and you must not run `git checkout`/`git pull` here (that would discard the working-tree change you're about to make this cycle). Start at the playbook's Step 1.
88
+ 2. **Stop after that playbook's own verification step — do not commit, push, or open a PR from within it.** Leave the single change sitting in the working tree. Committing and shipping is Step 5 below, handled once for the whole cycle.
89
+ 3. Keep honoring the **No AI attribution** and **Run autonomously** rules throughout (never pause to ask a question). For the playbooks that would otherwise ask a human or defer findings — [`improve-style.md`](improve-style.md) and [`improve-security.md`](improve-security.md) — apply **only** the safe, mechanical change yourself, and note anything requiring human judgment for the final report instead of blocking.
90
+ 4. Stay narrowed to the target you selected in Step 2 — don't re-derive a different pick mid-playbook.
91
+
92
+ Track your own before→after numbers and which file(s) you touched as you go — you'll need them for the ledger and for Step 4.
93
+
94
+ ### Step 4 — Verify the result independently
95
+
96
+ Even though you just made this change yourself, re-check it with fresh commands rather than trusting your own running impression — it's easy to miss a regression while focused on the one metric you were improving. Confirm the change is real, correct, and scoped:
97
+
98
+ ```bash
99
+ git status
100
+ git diff --stat
101
+ npm run typecheck:diff 2>&1
102
+ npm run test:diff 2>&1
103
+ npm run lint:diff 2>&1
104
+ npm run quality 2>&1
105
+ ```
106
+
107
+ Check, in order — **any** failure means the change is rejected:
108
+
109
+ 1. **Scope is legal.** `git diff --stat` touches only files the chosen playbook permits. Reject if it touched a forbidden file (`src/controller.ts`, `src/main.ts`, PTY/shell/network/crypto files, `*.test.ts` where the task forbids it), a config file (`fta.json`, `eslint.config.mjs`, `package.json`, `tsconfig.json`) it shouldn't, or far more files than the task's cap allows.
110
+ 2. **No AI attribution** slipped into any changed file, comment, or (later) commit message.
111
+ 3. **TypeScript is clean** (`typecheck:diff` — no errors).
112
+ 4. **Tests pass** (`test:diff`).
113
+ 5. **Lint is no worse** — the `✖ … problems (errors, warnings)` line has **0 errors** and warnings **≤** your Step 1 snapshot.
114
+ 6. **The target metric actually improved** versus the before-number you recorded: the FTA score dropped, the complexity warning cleared, the clone is gone, the coverage rose, the knip finding disappeared, etc. A change that is green but did not move the metric is not worth keeping.
115
+
116
+ **If all checks pass →** go to Step 5.
117
+
118
+ **If any check fails →** revert this cycle's change so the tree returns to the last good commit, and record the cycle as **reverted** in the ledger:
119
+
120
+ ```bash
121
+ git checkout -- .
122
+ git clean -fd
123
+ ```
124
+
125
+ (Use `git clean -fd` to also drop any new files you created.) Then continue to Step 6 — the loop goes on, but Step 2 will not re-pick this (task, target).
126
+
127
+ ### Step 5 — Ship this cycle to master
128
+
129
+ The change is verified and sitting uncommitted in the working tree. **Ship it by executing [`merge-change-to-master.md`](merge-change-to-master.md) in full, yourself** — follow every step of that playbook in order, same as you did for the improvement playbook in Step 3; do not delegate this either. It commits the change as a single-author Conventional Commits commit — pick the type that fits the task (`refactor` for modularity/complexity/namespacing/duplication, `test` for coverage, `chore`/`fix` for deadcode, `fix`/`build` for security, `style` for CSS, `build` for a package update) — opens a PR against `master`, resolves any conflicts, waits for required checks, and squash-merges it. Do **not** hand-commit first: the merge task's own Step 0 picks up the working-tree change itself.
130
+
131
+ Keep honoring the **No AI attribution** rule as you go — the commit, PR title, and PR body must carry no AI authorship — and the **Run autonomously** rule (never pause to ask a question).
132
+
133
+ Follow the merge task through to its own final report shape, then fold the outcome into your ledger:
134
+
135
+ - **Merged** → mark the cycle **merged** and capture the PR number/URL into the ledger row. Write a two-line summary of what this cycle achieved.
136
+ - **Left open** (conflicts unresolved after its retries, or a required check failed) → the change did not land on `master`. Mark the cycle **open (not merged)** with the PR URL and the reason. Do not retry the merge. This counts the same as a non-successful cycle for the "two in a row" stopping condition in Step 6.
137
+
138
+ ### Step 6 — Resync master and decide whether to continue
139
+
140
+ First return the workspace to a clean, up-to-date `master` so the next cycle inspects the true merged state rather than a leftover feature branch:
141
+
142
+ ```bash
143
+ git checkout master
144
+ git pull origin master
145
+ ```
146
+
147
+ If this cycle was **reverted** in Step 4 you never left `master`, and if its PR was **left open** the change is not on `master` — in both cases the working tree is (or becomes) clean here, which is correct; an open PR lives on for a human. A **merged** cycle's change arrives on `master` via this pull.
148
+
149
+ Then decide:
150
+
151
+ - If you have completed the planned number of cycles → stop and go to the final report.
152
+ - If a stopping condition below is met → stop and go to the final report.
153
+ - Otherwise → return to **Step 1** for the next cycle. The tree is clean and `master` is current, so the next inspection sees an accurate picture.
154
+
155
+ ---
156
+
157
+ ## When to stop the loop
158
+
159
+ Stop the loop (and write the final report) as soon as **any** of these is true:
160
+
161
+ - You've run the planned number of cycles (default 5).
162
+ - **No worthwhile, safe improvement remains** — Step 2 finds every candidate blocked, trivial, or already-failed this session.
163
+ - The tree is **broken and you can't recover it** — a cycle left typecheck or tests red and reverting did not restore green. Report loudly; do not keep layering cycles on a broken tree.
164
+ - **Two cycles in a row did not land** — reverted in Step 4, or their PR was left open (unresolved conflicts / failing check) in Step 5. The signals aren't yielding shippable wins right now; stop rather than spin.
165
+
166
+ ---
167
+
168
+ ## Final report
169
+
170
+ Print the ledger and a short summary:
171
+
172
+ ```
173
+ Supervised improvement run — <N> cycles
174
+
175
+ Cycle Task Target Metric (before -> after) Outcome PR
176
+ 1 reduce-complexity src/foo.ts parseConfig() cc 30 -> 12 merged #123
177
+ 2 remove-duplication src/bar.ts / src/baz.ts 1 clone -> 0 merged #124
178
+ 3 improve-modularity src/qux.ts score 78 -> 61, 243->150 reverted —
179
+ 4 improve-security npm advisory GHSA-xxxx high -> patched open #125
180
+ ...
181
+
182
+ Merged this run: <count> Reverted: <count> Open (not merged): <count>
183
+ Net effect: <one or two sentences on what got better overall>
184
+ Next: <anything a human should look at — PRs left open on a failing check or unresolved conflicts, deferred security/style findings, a target that keeps failing, or "all cycles merged, master is clean">
185
+ ```
186
+
187
+ Merged cycles are already on `master`. Note in "Next" any PR that was **left open** (failing required check or unresolved conflicts) so a human can finish it. Keep the report brief. Done.
@@ -0,0 +1,188 @@
1
+ # Improve Code Modularity (one safe extraction per run)
2
+
3
+ Your job: make **one** small, safe change that lowers the complexity of **one** high-complexity file by **moving a cohesive group of its code out into a new, focused module file** — then prove you did not break anything. Do exactly one extraction, then verify.
4
+
5
+ **No AI attribution — anywhere.** Never credit an AI agent as an author or contributor in anything this task produces. That means: no `Co-Authored-By:` trailers naming Claude or any other AI, no “Generated with Claude Code” (or similar) lines or badges, and no AI authorship notes in code, comments, docs, spec files, plan files, commit messages, or PR titles and bodies. This overrides any default convention that appends such attribution. The commit's configured git author is the only authorship ever recorded.
6
+
7
+ **Run everything synchronously, in the foreground.** Never use `run_in_background`, `&`, or otherwise start a background process (dev servers, watchers, long-lived processes) — every command must finish and return its exit code before you move to the next step.
8
+
9
+ **No subagents, no background agents.** Do every step yourself — never launch a subagent (Task/Agent tool, `fork`, or otherwise) to research, explore, or implement any part of this task on your behalf.
10
+
11
+ This is the **only** way we reduce a file's size and complexity here: extract a cohesive group of related code into a new file and import it back. Never compact code, strip comments, or delete blank lines to shrink a file — that hurts readability without improving the design (see [`code-guidelines.md`](../guidelines/code-guidelines.md)).
12
+
13
+ Refactoring edits real code, so the rule is simple: **the tests must pass before you start and still pass after. If you cannot keep them passing, put the code back the way it was.**
14
+
15
+ Do the steps below **in order**. Do not skip steps. Do not invent your own process.
16
+
17
+ **Shell hygiene:** run every command on its own line — no `&&` chaining, no `; echo "Exit code: $?"` suffixes, no subshell captures. The exit code and output are visible in the tool result. To run a project script, always use `./scripts/run.mjs <name>` — never call `node scripts/<name>.mjs` directly.
18
+
19
+ **Run autonomously.** This task runs unattended — do not ask the user questions or wait for feedback at any step. Make the best judgment call yourself, using the rules in this document, and keep going. Only stop early if the project isn't green before you start (Step 1), or if every remaining candidate file is blocked (see "Blocked work" below).
20
+
21
+ ## What you may and may not do
22
+
23
+ ### Safe work — DO IT AUTOMATICALLY, never ask
24
+
25
+ When your plan is **only** safe work, you **must carry it out yourself, start to finish, without stopping.** Do **not** ask "Do you want me to proceed?". Do **not** pause to show the plan for approval. Do **not** wait for confirmation. Just make the change and verify it.
26
+
27
+ Safe work is exactly this: **extract one cohesive group of code from a high-complexity source file into one (or more) new module files you create, and import it back** — done by the Recipe in Step 5, and nothing else.
28
+
29
+ ### Blocked work — skip and pick a different file
30
+
31
+ If doing the extraction would require any of the following, **go back to Step 3** and pick the next-best file instead. Never ask the user — just skip and move on.
32
+
33
+ 1. Changing the **public API** of a file other files depend on — i.e. you cannot keep every existing `import` working. (If you move an `export`ed symbol but **re-export it from the original file** so no other file changes, that is still safe.)
34
+ 2. Editing **more than 1 existing source file**, or changing import paths in more than 3 files (the new module file(s) you create do not count).
35
+ 3. Touching **`src/controller.ts`** (the biggest, riskiest file) — even though it has the highest score.
36
+ 4. Editing **any test file** (`*.test.ts`, `*.test.tsx`).
37
+ 5. Touching **security, password/crypto, shell-execution, PTY/terminal, or network** code.
38
+
39
+ If every remaining candidate is blocked, report which files you considered and why each was blocked, and stop without changing any code.
40
+
41
+ > You may edit **only** the one existing source file you picked, plus the **new module file(s)** you create to receive the extracted code. Never edit `fta.json`, `eslint.config.mjs`, `package.json`, `tsconfig.json`, or any other config or test file. Leave the `score_cap` in `fta.json` alone.
42
+
43
+ ---
44
+
45
+ ## Step 0 — Prepare the workspace
46
+
47
+ Execute `ai/tasks/prepare-workspace.md` in full before doing anything else.
48
+
49
+ ---
50
+
51
+ ## Step 1 — See the starting state (run these, write the numbers down)
52
+
53
+ Run all four and read the output:
54
+
55
+ ```bash
56
+ npm run typecheck 2>&1
57
+ npm run lint 2>&1
58
+ npm run test 2>&1
59
+ npm run quality 2>&1
60
+ ```
61
+
62
+ Then record these starting numbers — you will compare against them at the end. Put them straight into your report draft (Step 7):
63
+
64
+ - **TypeScript:** `npm run typecheck` must finish with **no errors**. If it errors before you touch anything, STOP and tell the user.
65
+ - **Lint:** near the end of `npm run lint` there is a summary line like `✖ 16 problems (0 errors, 16 warnings)`. Write down the **errors** count and the **warnings** count. Note especially any `max-lines` (file over 200 lines) and `sonarjs/cognitive-complexity` warnings — these point straight at extraction targets.
66
+ - **Tests:** they must be **green** (all passing). If any test is already failing **before** you touch anything, STOP and tell the user — do not start a refactor on a broken suite.
67
+ - **Quality (FTA):** `npm run quality` prints a table per area, sorted worst-first, with each file's **line count** and **FTA score** (lower = better). This is your **primary** signal for what to extract from. Write down the score and line count of the file you end up picking.
68
+
69
+ Always run these fresh. Do not trust earlier output in the conversation.
70
+
71
+ ---
72
+
73
+ ## Step 2 — Read the signals
74
+
75
+ You are looking for the file that most needs code moved out of it. Two places tell you:
76
+
77
+ - The **FTA table** (`npm run quality`): the top rows are the worst files. A high score usually means the file is both long and complex — a prime candidate to split.
78
+ - The **lint warnings** (`npm run lint`): a `max-lines` error means the file is over the 200-line limit and *must* shed code into a new module; a `sonarjs/cognitive-complexity` warning marks a function that has grown too tangled and often signals a cluster worth lifting out whole.
79
+
80
+ A `max-lines` or `cognitive-complexity` finding looks like this in the lint output:
81
+
82
+ ```
83
+ src/foo.ts
84
+ 1:1 error File has too many lines (243). Maximum allowed is 200 max-lines
85
+ 42:11 warning Refactor this function to reduce its Cognitive Complexity
86
+ from 30 to the 15 allowed sonarjs/cognitive-complexity
87
+ ```
88
+
89
+ It tells you the **file** (and, for complexity, the **function line**) that is carrying too much.
90
+
91
+ ---
92
+
93
+ ## Step 3 — Pick exactly one file to extract from
94
+
95
+ 1. From the FTA table, list the worst `src/` files together with any that carry a `max-lines` or `cognitive-complexity` warning.
96
+ 2. **Cross out** any file that is:
97
+ - a `*.test.ts` / `*.test.tsx` file,
98
+ - `src/main.ts`,
99
+ - `src/controller.ts` (needs-permission — only with the user's go-ahead),
100
+ - `src/pty.ts`, `src/shell.ts`, or any file whose main job is spawning processes, running a terminal, doing network
101
+ - under `web/src/` (only consider these if no `src/` candidate is left),
102
+ - already small and simple (low score, comfortably under 200 lines).
103
+ 3. From what remains, pick the **one** file with the **highest FTA score** — that is the one most worth splitting. Prefer a file that is over (or near) the 200-line limit, since extraction there also clears a `max-lines` error.
104
+
105
+ State your pick in one short sentence: the file, its current FTA score and line count, and the warning(s) it carries. Write those numbers into your report draft.
106
+
107
+ ---
108
+
109
+ ## Step 4 — Plan the extraction (a quick note to yourself, then keep going)
110
+
111
+ Find **one cohesive group of code** to lift out whole — code that belongs together and reads naturally as its own module. Good clusters:
112
+
113
+ - a set of related pure helpers (e.g. all the parsing/formatting functions for one concern),
114
+ - the body and helpers of one over-complex function flagged by `cognitive-complexity`,
115
+ - a group of related types/constants plus the small functions that operate on them.
116
+
117
+ Jot a one- or two-line plan: **which** group of code you will move, the **name of the new file** (`kebab-case.ts`, focused on that concern), and **what the original file will import back** from it. This is a note for **you**, not a message to send — do **not** post it and wait for a reply.
118
+
119
+ Check the plan against **What you may and may not do**:
120
+
121
+ - If any of points 1–5 applies → go back to Step 3 and pick a different file.
122
+ - Otherwise (all safe work) → go straight to Step 5 and make the change **now, on your own, without asking.**
123
+
124
+ ---
125
+
126
+ ## Step 5 — Make the change
127
+
128
+ **First, back up the existing file you are about to edit**, so you can restore it exactly if anything goes wrong:
129
+
130
+ ```bash
131
+ cp src/foo.ts src/foo.ts.bak
132
+ ```
133
+
134
+ Then perform the extraction. Keep the diff focused — move the chosen group of code, and do not reformat or "tidy" unrelated lines.
135
+
136
+ ### Recipe — extract a cohesive group into a new module file
137
+
138
+ 1. **Create the new module file** next to the original, with a focused `kebab-case` name describing the concern (e.g. `src/foo-parsing.ts`). Keep it under 200 lines too — if the group you want to move is itself huge, move a smaller cohesive subset.
139
+ 2. **Move the chosen code** (functions, and the types/constants only they use) into the new file. Add whatever `import`s that code needs at the top of the new file.
140
+ 3. **Export** from the new file exactly the symbols the original file still needs.
141
+ 4. **In the original file**, delete the moved code and add an `import { … } from './foo-parsing.js';` for the symbols you now call.
142
+ 5. **Preserve the public API.** If any moved symbol was `export`ed and is imported by *other* files, **re-export it from the original file** (`export { thing } from './foo-parsing.js';`) so no other file has to change. If you cannot keep every existing import working without editing other files → STOP and ask (rule 1).
143
+ 6. Do **not** change behavior, call signatures, or what anything returns. Do **not** move code in a way that breaks ordering of side effects or shared module state.
144
+ 7. If you cannot find a clean, self-contained group to move like this, do **not** force it — restore your backup, go back to Step 3, and pick a different file (or report that no safe extraction was available).
145
+
146
+ ### Style
147
+
148
+ - Match nearby naming: `camelCase` functions, `PascalCase` types, `kebab-case` filenames.
149
+ - Relative imports use a **`.js`** extension even though the source is `.ts` (e.g. `import { x } from './foo.js'`). The new module file and the import that points to it must both follow this.
150
+ - Add a comment only if the *why* is non-obvious; never a comment that just restates *what* the code does.
151
+
152
+ ---
153
+
154
+ ## Step 6 — Verify (run in this order; fix or put it back)
155
+
156
+ ```bash
157
+ npm run typecheck:diff 2>&1
158
+ npm run test:diff 2>&1
159
+ npm run lint:diff 2>&1
160
+ npm run quality 2>&1
161
+ ```
162
+
163
+ Check each, in order:
164
+
165
+ 1. **TypeScript is clean.** `npm run typecheck:diff` must have no errors. A type error here almost always means a moved symbol's type is missing an import in the new file, or a re-export was forgotten — fix it in your source files. If you cannot make it clean quickly, restore your backup and report.
166
+ 2. **Tests pass.** If a test now fails: try a quick, obvious fix in your source files (do **not** edit the test). If it does not pass quickly, **restore your backup** (`cp src/foo.ts.bak src/foo.ts`, and delete the new module file(s) you added) and report what blocked you. Never edit a test to make it pass.
167
+ 3. **Lint is no worse.** Look at the `✖ … problems (… errors, … warnings)` line again. **Errors must be 0** (if you were clearing a `max-lines` error, it should now be gone). **Warnings must be the same or fewer** than Step 1, never higher. If a new warning or error appeared — often a missing `.js` import extension, a now-unused import, or complexity that rode along into the new file — fix it in your source files. Never silence a warning with an `eslint-disable` comment.
168
+ 4. **Quality improved.** The original file's FTA score and line count should be **lower** than Step 1. The new module file should land at a reasonable score and stay under 200 lines. If the original's score did not drop, the extraction was too small to matter — restore the backup and pick a more substantial group (or a different file).
169
+
170
+ When all three pass, **delete the backup file**: `rm src/foo.ts.bak`.
171
+
172
+ ---
173
+
174
+ ## Step 7 — Report
175
+
176
+ Give the user a short report in this exact shape:
177
+
178
+ ```
179
+ Target file: <path>
180
+ New module: <path of the file you created>
181
+ Extraction: <one sentence — e.g. "moved the 4 query-parsing helpers out of database.ts into database-parsing.ts">
182
+ FTA score: <before> -> <after> (lines: <before> -> <after>)
183
+ Lint problems: <before> -> <after> (errors: <before> -> <after>)
184
+ TypeScript: clean / <errors, if any>
185
+ Tests: all pass / <what failed>
186
+ ```
187
+
188
+ Keep it brief. Done.