@apptoolkit/harness 1.0.3 → 1.0.5

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 (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -47
  3. package/harness.js +123 -0
  4. package/package.json +85 -24
  5. package/payload/HARNESS.md +28 -0
  6. package/payload/author-style/README.md +58 -0
  7. package/payload/author-style/biome-core.json +57 -0
  8. package/payload/author-style/biome-react.json +9 -0
  9. package/payload/author-style/biome-sql.json +9 -0
  10. package/payload/author-style/bun.lock +37 -0
  11. package/payload/author-style/check.llm.md +17 -0
  12. package/payload/author-style/check.test.llm.md +17 -0
  13. package/payload/author-style/check.test.ts +264 -0
  14. package/payload/author-style/check.ts +200 -0
  15. package/payload/author-style/member-spacing.test.ts +172 -0
  16. package/payload/author-style/member-spacing.ts +106 -0
  17. package/payload/author-style/package.json +18 -0
  18. package/payload/author-style/plugins/class-member-order.grit +133 -0
  19. package/payload/author-style/plugins/event-handler-names.grit +110 -0
  20. package/payload/author-style/plugins/explicit-arrow-body.grit +15 -0
  21. package/payload/author-style/plugins/explicit-source-constructs.grit +10 -0
  22. package/payload/author-style/plugins/react-arrow-body.grit +85 -0
  23. package/payload/author-style/plugins/sql-style.grit +125 -0
  24. package/payload/author-style/react-module.llm.md +17 -0
  25. package/payload/author-style/react-module.test.ts +150 -0
  26. package/payload/author-style/react-module.ts +255 -0
  27. package/payload/author-style/source-policy.llm.md +17 -0
  28. package/payload/author-style/source-policy.test.ts +82 -0
  29. package/payload/author-style/source-policy.ts +238 -0
  30. package/payload/author-style/spacing.llm.md +17 -0
  31. package/payload/author-style/spacing.test.ts +174 -0
  32. package/payload/author-style/spacing.ts +211 -0
  33. package/payload/harness/LEARNING.md +18 -0
  34. package/payload/harness/POLICY.md +35 -0
  35. package/payload/harness/PROJECT.md +26 -0
  36. package/payload/harness/REVIEW.md +17 -0
  37. package/payload/harness/TEMPLATES.md +20 -0
  38. package/payload/harness/WORKFLOWS.md +65 -0
  39. package/payload/harness/runtime/ZOD-LICENSE +21 -0
  40. package/payload/harness/runtime/harness.mjs +123 -0
  41. package/payload/harness/services/README.md +26 -0
  42. package/payload/harness/services/penpot.json +7 -0
  43. package/payload/harness/services/plane.json +9 -0
  44. package/payload/harness/workflows/W01.md +13 -0
  45. package/payload/harness/workflows/W02.md +13 -0
  46. package/payload/harness/workflows/W03.md +13 -0
  47. package/payload/harness/workflows/W04.md +13 -0
  48. package/payload/harness/workflows/W05.md +13 -0
  49. package/payload/harness/workflows/W06.md +13 -0
  50. package/payload/harness/workflows/W07.md +13 -0
  51. package/payload/harness/workflows/W08.md +13 -0
  52. package/payload/harness/workflows/W09.md +13 -0
  53. package/payload/harness/workflows/W10.md +13 -0
  54. package/payload/harness/workflows/W11.md +13 -0
  55. package/payload/harness/workflows/W12.md +13 -0
  56. package/payload/harness/workflows/W13.md +13 -0
  57. package/payload/harness/workflows/W14.md +13 -0
  58. package/payload/harness/workflows/W15.md +13 -0
  59. package/payload/harness/workflows/W16.md +13 -0
  60. package/payload/harness/workflows/W17.md +13 -0
  61. package/payload/harness/workflows/W18.md +13 -0
  62. package/payload/harness/workflows/W19.md +13 -0
  63. package/payload/harness/workflows/W20.md +27 -0
  64. package/payload/harness/workflows/W21.md +19 -0
  65. package/payload/harness/workflows/W22.md +13 -0
  66. package/payload/harness/workflows/W23.md +21 -0
  67. package/payload/harness/workflows/W24.md +13 -0
  68. package/payload/harness/workflows/W25.md +13 -0
  69. package/payload/harness/workflows/W26.md +13 -0
  70. package/payload/harness/workflows/W27.md +13 -0
  71. package/payload/harness/workflows/W28.md +13 -0
  72. package/payload/harness/workflows/W29.md +13 -0
  73. package/payload/harness/workflows/W30.md +13 -0
  74. package/payload/harness/workflows/W31.md +13 -0
  75. package/payload/harness/workflows/W32.md +13 -0
  76. package/payload/harness/workflows/W33.md +13 -0
  77. package/payload/harness/workflows/W34.md +13 -0
  78. package/payload/harness/workflows/W35.md +13 -0
  79. package/payload/harness/workflows/W36.md +13 -0
  80. package/payload/harness/workflows/W37.md +13 -0
package/package.json CHANGED
@@ -1,37 +1,98 @@
1
1
  {
2
2
  "name": "@apptoolkit/harness",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A portable harness for configuring AI coding agents and engineering workflows.",
5
+ "license": "MIT",
5
6
  "type": "module",
7
+ "bin": {
8
+ "harness": "./harness.js"
9
+ },
10
+ "files": [
11
+ "harness.js",
12
+ "payload/HARNESS.md",
13
+ "payload/author-style/README.md",
14
+ "payload/author-style/biome-core.json",
15
+ "payload/author-style/biome-react.json",
16
+ "payload/author-style/biome-sql.json",
17
+ "payload/author-style/bun.lock",
18
+ "payload/author-style/check.llm.md",
19
+ "payload/author-style/check.test.llm.md",
20
+ "payload/author-style/check.test.ts",
21
+ "payload/author-style/check.ts",
22
+ "payload/author-style/member-spacing.test.ts",
23
+ "payload/author-style/member-spacing.ts",
24
+ "payload/author-style/package.json",
25
+ "payload/author-style/plugins/class-member-order.grit",
26
+ "payload/author-style/plugins/event-handler-names.grit",
27
+ "payload/author-style/plugins/explicit-arrow-body.grit",
28
+ "payload/author-style/plugins/explicit-source-constructs.grit",
29
+ "payload/author-style/plugins/react-arrow-body.grit",
30
+ "payload/author-style/plugins/sql-style.grit",
31
+ "payload/author-style/react-module.llm.md",
32
+ "payload/author-style/react-module.test.ts",
33
+ "payload/author-style/react-module.ts",
34
+ "payload/author-style/source-policy.llm.md",
35
+ "payload/author-style/source-policy.test.ts",
36
+ "payload/author-style/source-policy.ts",
37
+ "payload/author-style/spacing.llm.md",
38
+ "payload/author-style/spacing.test.ts",
39
+ "payload/author-style/spacing.ts",
40
+ "payload/harness/LEARNING.md",
41
+ "payload/harness/POLICY.md",
42
+ "payload/harness/PROJECT.md",
43
+ "payload/harness/REVIEW.md",
44
+ "payload/harness/TEMPLATES.md",
45
+ "payload/harness/WORKFLOWS.md",
46
+ "payload/harness/runtime/ZOD-LICENSE",
47
+ "payload/harness/runtime/harness.mjs",
48
+ "payload/harness/services/README.md",
49
+ "payload/harness/services/penpot.json",
50
+ "payload/harness/services/plane.json",
51
+ "payload/harness/workflows/W01.md",
52
+ "payload/harness/workflows/W02.md",
53
+ "payload/harness/workflows/W03.md",
54
+ "payload/harness/workflows/W04.md",
55
+ "payload/harness/workflows/W05.md",
56
+ "payload/harness/workflows/W06.md",
57
+ "payload/harness/workflows/W07.md",
58
+ "payload/harness/workflows/W08.md",
59
+ "payload/harness/workflows/W09.md",
60
+ "payload/harness/workflows/W10.md",
61
+ "payload/harness/workflows/W11.md",
62
+ "payload/harness/workflows/W12.md",
63
+ "payload/harness/workflows/W13.md",
64
+ "payload/harness/workflows/W14.md",
65
+ "payload/harness/workflows/W15.md",
66
+ "payload/harness/workflows/W16.md",
67
+ "payload/harness/workflows/W17.md",
68
+ "payload/harness/workflows/W18.md",
69
+ "payload/harness/workflows/W19.md",
70
+ "payload/harness/workflows/W20.md",
71
+ "payload/harness/workflows/W21.md",
72
+ "payload/harness/workflows/W22.md",
73
+ "payload/harness/workflows/W23.md",
74
+ "payload/harness/workflows/W24.md",
75
+ "payload/harness/workflows/W25.md",
76
+ "payload/harness/workflows/W26.md",
77
+ "payload/harness/workflows/W27.md",
78
+ "payload/harness/workflows/W28.md",
79
+ "payload/harness/workflows/W29.md",
80
+ "payload/harness/workflows/W30.md",
81
+ "payload/harness/workflows/W31.md",
82
+ "payload/harness/workflows/W32.md",
83
+ "payload/harness/workflows/W33.md",
84
+ "payload/harness/workflows/W34.md",
85
+ "payload/harness/workflows/W35.md",
86
+ "payload/harness/workflows/W36.md",
87
+ "payload/harness/workflows/W37.md"
88
+ ],
6
89
  "packageManager": "bun@1.4.2",
7
- "files": [],
8
90
  "publishConfig": {
9
91
  "access": "public",
10
92
  "registry": "https://registry.npmjs.org/"
11
93
  },
12
- "scripts": {
13
- "check:code": "bun --no-env-file llm/tools/check-code.ts",
14
- "acquire": "bun --no-env-file src/acquisition/acquire.ts",
15
- "build:harness": "bun --no-env-file src/harness/release/build.ts",
16
- "build:harness:native": "bun --no-env-file src/harness/release/build.ts --native",
17
- "pack:harness": "bun --no-env-file src/harness/release/build.ts --pack",
18
- "test": "bun test --no-env-file ./src/acquisition",
19
- "test:harness": "bun test --no-env-file ./src/harness",
20
- "test:all": "bun test --no-env-file --no-orphans --timeout 30000 --path-ignore-patterns '**/raw/**' --path-ignore-patterns '**/processing/**' --path-ignore-patterns '**/dist/**' ./src/acquisition ./src/harness ./src/author-style ./llm/tools/check-code.test.ts",
21
- "typecheck": "bun --no-env-file node_modules/typescript/bin/tsc --noEmit"
22
- },
23
94
  "dependencies": {
24
95
  "ink": "7.1.1",
25
- "react": "19.3.1",
26
- "zod": "4.6.7"
27
- },
28
- "devDependencies": {
29
- "@types/node": "24.10.0",
30
- "@types/react": "19.3.0",
31
- "react-devtools-core": "6.1.5",
32
- "typescript": "5.9.3"
33
- },
34
- "engines": {
35
- "bun": ">=1.4.2"
96
+ "react": "19.3.1"
36
97
  }
37
98
  }
@@ -0,0 +1,28 @@
1
+ # AppToolkit Harness
2
+
3
+ Use this index when adopting a project or opening a fresh agent session. Resolve the project, read its applicable rules, and open the smallest workflow that matches the request.
4
+
5
+ ## Every session
6
+
7
+ 1. Resolve the active repository and its rules with the [project guide](harness/PROJECT.md) and [operating policy](harness/POLICY.md). Use the workflow index for the task. The native setup command is for init and update.
8
+ 2. Look up relevant prior work in [project knowledge](harness-local/KNOWLEDGE.md). Use the matching record and bounded evidence. Prefer tested [project tools](harness-local/TOOLS.md) for deterministic work.
9
+ 3. At each decision, correction, useful discovery, repeated operation or handoff, follow the [learning and improvement procedure](harness/LEARNING.md). Maintain applicable sibling source maps after code changes and verify the latest links before handoff.
10
+
11
+ | Need | Start here |
12
+ | --- | --- |
13
+ | Find the procedure for a natural request | [Workflow index](harness/WORKFLOWS.md) |
14
+ | Start a new feature or an unresolved change | [W16 Feature definition](harness/workflows/W16.md) |
15
+ | Adopt, initialize or update this installation | [W20 Adoption](harness/workflows/W20.md) |
16
+ | Resolve repositories, services and project conventions | [Project guide](harness/PROJECT.md) |
17
+ | Check permissions, engineering rules and learning | [Operating policy](harness/POLICY.md) |
18
+ | Apply a lesson, preserve research or improve a check | [Learning and improvement](harness/LEARNING.md) |
19
+ | Audit a claim or independently review code | [Independent review](harness/REVIEW.md) |
20
+ | Prepare a decision, work unit or checkpoint | [Templates](harness/TEMPLATES.md) |
21
+ | Verify coverage against an explicit source inventory | [W23 Verification](harness/workflows/W23.md) |
22
+ | Verify authored TypeScript without a compatible project Biome configuration | [Style tools](author-style/README.md) |
23
+
24
+ Begin with the installed workspace and project records for the active root. Apply the nearest repository guidance as well as shared decisions relevant to that repository. Use source maps to locate the relevant sections. For a natural request such as “Give me my pending list” or “Dame mi lista de pendientes”, open only [W01](harness/workflows/W01.md), resolve its target and use the project's authorized sources.
25
+
26
+ Run `rtk proxy bun --no-env-file llm/harness/runtime/harness.mjs context llm/HARNESS.md` from the installation root to list heading locators without returning the body. If only Node.js is available, replace `bun --no-env-file` with `node` in installed runtime commands. Add `--section line:1` with the locator reported for the desired heading. An exact title or anchor also works when unique. Select a line locator for repeated titles. The reader opens regular project-relative Markdown files, rejects protected locations and symbolic links, and returns a bounded section with its source line range.
27
+
28
+ Open an indexed workflow directly with `rtk proxy bunx --bun @apptoolkit/harness workflow W01` or `rtk proxy npx @apptoolkit/harness workflow W01`. Use [W21](harness/workflows/W21.md) to plan local source-map protection and [W23](harness/workflows/W23.md) to check a fresh LCOV report.
@@ -0,0 +1,58 @@
1
+ # Personal code style
2
+
3
+ Use this profile whenever an agent writes or changes authored TypeScript in a project without an applicable Biome configuration. It supplies a pinned Biome dependency, configuration, structural lint rules and a small TypeScript parser supplement. The tool reads only the explicitly selected source files for its supplementary checks and never writes target files.
4
+
5
+ - [Writing rules](#writing-rules): Read before editing code.
6
+ - [Deterministic checks](#deterministic-checks): Select an appropriate profile.
7
+ - [Install and run](#install-and-run): Run after each code edit batch and before handoff. See the [checker map](check.llm.md) when maintaining the tool.
8
+ - [Evidence and precedence](#evidence-and-precedence): Apply the target project rules and verify changes.
9
+
10
+ ## Writing rules
11
+
12
+ 1. Write code in execution order. Name intermediate values when nesting hides decisions. Use explicit guards and braces, keep related steps together and separate preparation, reads, decisions, writes and returns when they serve different purposes. Keep a simple expression concise.
13
+ 2. Define domain contracts before behavior. Keep a schema and its inferred types together and validate untrusted data before it enters domain logic. Reuse the accepted validation contract. Ask before adding Zod to a target that does not have it. Use explicit projections at public boundaries.
14
+ 3. Keep transport and framework adapters focused. Separate domain decisions from persistence and wire explicit dependencies. Preserve the project's established class, module or functional organization. In classes, order static properties and methods before the constructor and instance properties and methods after it. Put private or protected members before public members in the corresponding group. Prefer constructor parameter properties for retained values and keep related operations in workflow order.
15
+ 4. Use descriptive names and structure to explain behavior. Preserve rationale in the project's decision, ticket or review record. Keep a cause and useful context when operations fail. Prove guards, recovery and failure behavior through focused tests. Do not copy historical workarounds or weaken types to make checks pass.
16
+ 5. Scope component rules to reusable React components. Prefer a named PascalCase `const`, explicit `FC` props and a default export when compatible with local rules. Keep props near their component and keep inline event callbacks to a single simple call. Use descriptive local `handle…` names. Treat framework entry points, generic components and library-owned wrappers according to their actual contract.
17
+
18
+ ## Deterministic checks
19
+
20
+ | Area | Enforcement |
21
+ | --- | --- |
22
+ | Format | Biome uses two spaces, LF, a 120-column line width, single quotes in TypeScript, double quotes in JSX, semicolons, trailing commas and parenthesized arrow parameters. |
23
+ | Structure | Biome and the bundled Grit plugins check braces, explicit class accessibility, supported member-order inversions, multiline or branching arrow bodies and increment/decrement operators. The TypeScript supplement checks statement phase boundaries and class member separation, keeping overloads grouped. |
24
+ | Types and source | Biome rejects explicit `any`, non-null assertions, selected suppression directives and configured unsafe type patterns. Grit rejects explicit `unknown` type nodes. The TypeScript supplement checks double assertions, explanatory comments and top-level inferred types derived directly from a same-file schema via a recognized Zod import. It preserves parsed TypeScript reference directives and exact SQL markers before supported tagged templates. |
25
+ | `react` | Includes the common checks plus selected JSX components, exports, `FC` typing, inline event call shape and local event names. It recognizes direct imported React `memo` and `forwardRef`. Select reusable component files. Other wrappers, arbitrary aliases and semantic event binding still need review. |
26
+ | `sql` | Includes the common checks plus a lexical check for supported templates with a direct `sql` tag. Select it only where the project's `sql` tag is PostgreSQL. It does not resolve aliases or parse the SQL dialect. Unsupported fragments remain outside the check. |
27
+
28
+ Keep the native type checker, focused behavior tests, independent technical audit and separate code review. Static checks do not prove meaningful names, correct schema ownership, safe public exposure, awaited authorization, rejection handling, transaction semantics or test adequacy. A successful check reports a result for the selected files and patterns. It does not establish whole-project coverage.
29
+
30
+ ## Install and run
31
+
32
+ Use the installed `llm/author-style/` directory in the adopting project. Keep its package manifest and `bun.lock` together. Run these commands from the adopting project's root with RTK and Bun 1.4.2 or later.
33
+
34
+ ```text
35
+ rtk proxy bun install --cwd llm/author-style --frozen-lockfile --ignore-scripts
36
+ rtk proxy bun run --cwd llm/author-style check --root /absolute/project path/to/changed.ts
37
+ ```
38
+
39
+ The Bun install command installs the isolated verifier and its platform binary inside `llm/author-style/`. Keep the application's own dependencies, lockfile and package manager. Use explicit paths under the actual project root. Quote paths containing spaces and pass `--` before paths beginning with a hyphen. Supported inputs are `.ts`, `.tsx`, `.mts` and `.cts`. A selection can include new and existing files. The verifier reads the whole selected file, so keep inherited violations separate and do not reformat unrelated code. The command rejects symlinks, known generated or dependency directories, generated headers and out-of-root paths.
40
+
41
+ ```text
42
+ rtk proxy bun run --cwd llm/author-style check --root /absolute/project --profile react src/Panel.tsx
43
+ rtk proxy bun run --cwd llm/author-style check --root /absolute/project --profile sql src/queries.ts
44
+ rtk proxy bun run --cwd llm/author-style check --root /absolute/project --lint-only src/service.ts
45
+ rtk proxy bun run --cwd llm/author-style test
46
+ ```
47
+
48
+ For an existing project, follow its own rules and tools first. The verifier refuses a selected file when it finds a native `biome.json` or `biome.jsonc` in its directory or an ancestor. If another formatter is authoritative and its lint policy is compatible, select `--lint-only` to omit personal formatting and spacing. If the existing lint policy conflicts, follow the project and record the difference. The verifier does not select or replace an ESLint, Prettier or other configuration on its own. Native Biome warnings, including an oversized selected file, cause a failed check. A native failure prevents the supplementary checks from running. Resolve the reported cause and rerun the same selection.
49
+
50
+ Record the selected paths and result in the normal verification evidence. Add this instruction to the adopting agent's entry point or shared verification instructions. Every agent should run the same command after a code edit batch and before delivery. The package installs no editor, Git, CI or model-specific hook.
51
+
52
+ For an agent-only rule confirmed by project review, keep its configuration in a project-owned path such as `llm/harness-local/biome-agent.json`. Set `linter.rules.recommended` to false and add the scoped rules and project-owned plugins. Run the same checker with `--project-config llm/harness-local/biome-agent.json` and explicit authored paths. The checker runs the pinned profile first, followed by a separate lint pass for the local configuration. Use the corresponding `--profile` when its supplementary checks apply. A project-wide Biome configuration keeps its native command.
53
+
54
+ > After each code edit batch and before handoff, run the project's applicable Biome checks. When no applicable Biome configuration exists, run the compatible profile in `llm/author-style/README.md` on the edited TypeScript files. Use the project's established formatter and lint policy first. Record the result with the other verification evidence.
55
+
56
+ ## Evidence and precedence
57
+
58
+ Use the target project rules where established. Document and test a mechanical correction before changing a shared rule.
@@ -0,0 +1,57 @@
1
+ {
2
+ "root": true,
3
+ "plugins": [
4
+ "./plugins/class-member-order.grit",
5
+ "./plugins/explicit-arrow-body.grit",
6
+ "./plugins/explicit-source-constructs.grit"
7
+ ],
8
+ "formatter": {
9
+ "indentStyle": "space",
10
+ "indentWidth": 2,
11
+ "lineEnding": "lf",
12
+ "lineWidth": 120
13
+ },
14
+ "javascript": {
15
+ "formatter": {
16
+ "quoteStyle": "single",
17
+ "jsxQuoteStyle": "double",
18
+ "quoteProperties": "asNeeded",
19
+ "trailingCommas": "all",
20
+ "semicolons": "always",
21
+ "arrowParentheses": "always",
22
+ "bracketSameLine": false,
23
+ "bracketSpacing": true
24
+ }
25
+ },
26
+ "assist": {
27
+ "enabled": false
28
+ },
29
+ "linter": {
30
+ "rules": {
31
+ "recommended": false,
32
+ "correctness": {
33
+ "noUnusedImports": "error",
34
+ "noUnusedPrivateClassMembers": "error",
35
+ "noUnusedVariables": "error"
36
+ },
37
+ "nursery": {
38
+ "noFloatingPromises": "error",
39
+ "noMisusedPromises": "error",
40
+ "noUnsafeTypeAssertion": "error"
41
+ },
42
+ "style": {
43
+ "noNonNullAssertion": "error",
44
+ "useBlockStatements": "error",
45
+ "useConsistentMemberAccessibility": {
46
+ "level": "error",
47
+ "options": { "accessibility": "explicit" }
48
+ },
49
+ "useImportType": "error"
50
+ },
51
+ "suspicious": {
52
+ "noExplicitAny": "error",
53
+ "noTsIgnore": "error"
54
+ }
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": ["./biome-core.json"],
3
+ "plugins": [
4
+ "./plugins/class-member-order.grit",
5
+ "./plugins/react-arrow-body.grit",
6
+ "./plugins/explicit-source-constructs.grit",
7
+ "./plugins/event-handler-names.grit"
8
+ ]
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": ["./biome-core.json"],
3
+ "plugins": [
4
+ "./plugins/class-member-order.grit",
5
+ "./plugins/explicit-arrow-body.grit",
6
+ "./plugins/explicit-source-constructs.grit",
7
+ "./plugins/sql-style.grit"
8
+ ]
9
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "lockfileVersion": 2,
3
+ "configVersion": 0,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "harness-author-style",
7
+ "devDependencies": {
8
+ "@biomejs/biome": "2.5.15",
9
+ "typescript": "5.9.3",
10
+ "zod": "4.6.7",
11
+ },
12
+ },
13
+ },
14
+ "packages": {
15
+ "@biomejs/biome": ["@biomejs/biome@2.5.15", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.5.15", "@biomejs/cli-darwin-x64": "2.5.15", "@biomejs/cli-linux-arm64": "2.5.15", "@biomejs/cli-linux-arm64-musl": "2.5.15", "@biomejs/cli-linux-x64": "2.5.15", "@biomejs/cli-linux-x64-musl": "2.5.15", "@biomejs/cli-win32-arm64": "2.5.15", "@biomejs/cli-win32-x64": "2.5.15" }, "bin": { "biome": "bin/biome" } }, "sha512-WZTW4slm/pdkh92K6t/3aEN++44JD1PQ7squ7RCMLI1flHGl43DVOIGXvCjHiZgBMO1V4uYxoFNtqrIA4qGuIQ=="],
16
+
17
+ "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.5.15", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BZVzFhJ/mUvTLMYbc9x6el0o2Uv5zP7bACYyhFb6fSc1giroXm7PL0a5KqMJ9F+/BnkYRjagD/ROSDVOZ6eapg=="],
18
+
19
+ "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.5.15", "", { "os": "darwin", "cpu": "x64" }, "sha512-V5Kw63V+fVGNFhFrizDxMbGXAzZCh8kYzJpy3GI6gTapWDg7bZK9oYC9CbVgQSEdTnupz0U5Efz8Ev+5vdBBXw=="],
20
+
21
+ "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.5.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-XaG7P7eeSLYETD3K9grfB0mQmpLQZjygdbsxekWBJAg4am79fGAtRpfRyNnTvXB2fZFNnJZG3nXm7HBat0+VUw=="],
22
+
23
+ "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.5.15", "", { "os": "linux", "cpu": "arm64" }, "sha512-tGzZUTcJCV7tj5Adh/Gn6nR4MycqA3iohq2LEcrarAgRBkU0h0OKd2UzCRkOsOYOuUGaUJb4YmqRqyy2feGGSw=="],
24
+
25
+ "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.5.15", "", { "os": "linux", "cpu": "x64" }, "sha512-xE4iEW/3LqlYj9GFgGrFsFSH51dEEpUbYWBfeOv0q87WkUDxK2o/HhreSb7qMJqck70RVM6Lg96hgedcAYcOkA=="],
26
+
27
+ "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.5.15", "", { "os": "linux", "cpu": "x64" }, "sha512-IlxUcyxilVGPsE008x13pWdkTbU3nQpP2i9b5UrbOYj6goBkKsRX1XB7yJLcV+O1H9LBchIIm4adOaVLZBX0ZQ=="],
28
+
29
+ "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.5.15", "", { "os": "win32", "cpu": "arm64" }, "sha512-2kPKzhNlm8C+Ru3GcO0Me2ODkCBLrVOUNuyi84RJyWDVKAA4+Kjj3jMjL938lF6BRfvltC4vB2nPY9SvN51Ovg=="],
30
+
31
+ "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.5.15", "", { "os": "win32", "cpu": "x64" }, "sha512-yAzh4UqEImV6Hcy0zjUqNfJAsUhoD64FBQCdTG8Md/Z2wQeVP/ZmJ3XRYAs1g8J9fjTFyl2fCtc5FB5til47+g=="],
32
+
33
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
34
+
35
+ "zod": ["zod@4.6.7", "", {}, "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg=="],
36
+ }
37
+ }
@@ -0,0 +1,17 @@
1
+ # Author style checker map
2
+
3
+ - [Inputs and project authority](#inputs-and-project-authority)
4
+ - [Native and parser checks](#native-and-parser-checks)
5
+ - [Verification and recovery](#verification-and-recovery)
6
+
7
+ ## Inputs and project authority
8
+
9
+ Start in `check.ts` at `checkFiles`. The request schema describes the project root, selected files, profile and mode. `targetRelativePath` establishes containment and `configuredBiome` detects local Biome configuration. See [install and run](README.md#install-and-run) for adoption, supported files and exclusions.
10
+
11
+ ## Native and parser checks
12
+
13
+ The `configurations` map selects the isolated Biome configuration. The checker uses the locked package, clears `BIOME_BINARY`, and starts Bun without dotenv loading or automatic installs. It propagates the native status. `findSourcePolicyIssues`, `findSpacingIssues`, `findMemberSpacingIssues` and `findReactModuleIssues` inspect the selected source without writing. The [check matrix](README.md#deterministic-checks) lists supported patterns and separate review boundaries.
14
+
15
+ ## Verification and recovery
16
+
17
+ `check.test.ts` covers installation layout, native and project authority checks, selected inputs and supplementary results. The individual parser test files cover exact constructs and boundaries. See [install and run](README.md#install-and-run) for the test command. Do not treat a skipped, failed or interrupted check as evidence that selected code passed.
@@ -0,0 +1,17 @@
1
+ # Checker integration test map
2
+
3
+ - [Installed layout and source selection](#installed-layout-and-source-selection)
4
+ - [Native profiles and policy](#native-profiles-and-policy)
5
+ - [Failure paths](#failure-paths)
6
+
7
+ ## Installed layout and source selection
8
+
9
+ `runs when the profile is installed under the adopting project llm directory` covers private configuration discovery. `uses the isolated formatter and linter on exact paths outside the harness without writing` covers exact file names, unselected files and byte preservation.
10
+
11
+ ## Native profiles and policy
12
+
13
+ `enforces core types, explicit updates, braces, branches and class layout` exercises the real engine and a rejected environment override. `uses the pinned Biome launcher when the target dotenv defines another binary` covers Bun subprocess isolation. `uses separately selected React and tagged SQL checks` distinguishes profile findings from the common configuration.
14
+
15
+ ## Failure paths
16
+
17
+ `fails a mixed selection when Biome cannot check an oversized file` protects against partial checks reported as success. `refuses existing configurations, generated files, symlinks and an empty file selection` checks scope and authority. Supplementary parser cases have their own focused test files.
@@ -0,0 +1,264 @@
1
+ import assert from 'node:assert/strict';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { cpSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { test } from 'node:test';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const checker = fileURLToPath(new URL('check.ts', import.meta.url));
10
+
11
+ function executeFrom(entry: string, root: string, args: string[], env = process.env) {
12
+ const result = spawnSync(process.execPath, [entry, '--root', root, ...args], { encoding: 'utf8', env });
13
+
14
+ if (result.error) {
15
+ throw result.error;
16
+ }
17
+
18
+ return result;
19
+ }
20
+
21
+ function execute(root: string, ...args: string[]) {
22
+ return executeFrom(checker, root, args);
23
+ }
24
+
25
+ test('runs when the profile is installed under the adopting project llm directory', (context) => {
26
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
27
+
28
+ context.after(() => rmSync(root, { recursive: true, force: true }));
29
+
30
+ const profile = join(root, 'llm', 'author-style');
31
+
32
+ mkdirSync(profile, { recursive: true });
33
+
34
+ const packageDirectory = fileURLToPath(new URL('.', import.meta.url));
35
+
36
+ for (const file of [
37
+ 'check.ts',
38
+ 'source-policy.ts',
39
+ 'spacing.ts',
40
+ 'member-spacing.ts',
41
+ 'react-module.ts',
42
+ 'package.json',
43
+ 'biome-core.json',
44
+ 'plugins',
45
+ ]) {
46
+ cpSync(join(packageDirectory, file), join(profile, file), { recursive: true });
47
+ }
48
+
49
+ symlinkSync(join(packageDirectory, 'node_modules'), join(profile, 'node_modules'), 'dir');
50
+ writeFileSync(join(root, 'entry.ts'), 'export const sample = true;\n');
51
+
52
+ const result = executeFrom(join(profile, 'check.ts'), root, ['entry.ts']);
53
+
54
+ assert.equal(result.status, 0, result.stderr);
55
+ assert.match(result.stdout, /Checked 1 file/);
56
+ });
57
+
58
+ test('uses the isolated formatter and linter on exact paths outside the harness without writing', (context) => {
59
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
60
+
61
+ context.after(() => rmSync(root, { recursive: true, force: true }));
62
+
63
+ const clean = join(root, 'has spaces.ts');
64
+ const poorlyFormatted = "export const label='one'\n";
65
+
66
+ writeFileSync(clean, poorlyFormatted);
67
+ writeFileSync(join(root, 'unselected.ts'), 'export const counter: any = 0;\n');
68
+
69
+ const failure = execute(root, 'has spaces.ts');
70
+
71
+ assert.equal(failure.status, 1);
72
+ assert.match(failure.stderr, /Formatter would have printed/);
73
+ assert.equal(readFileSync(clean, 'utf8'), poorlyFormatted);
74
+
75
+ const lintOnly = execute(root, '--lint-only', 'has spaces.ts');
76
+
77
+ assert.equal(lintOnly.status, 0, lintOnly.stderr);
78
+
79
+ writeFileSync(clean, 'export const label = `line\n// @generated\nline`;\n');
80
+
81
+ const success = execute(root, clean);
82
+
83
+ assert.equal(success.status, 0, success.stderr);
84
+ assert.match(success.stdout, /Checked 1 file/);
85
+ });
86
+
87
+ test('checks learned project rules in isolation and keeps adjacent unselected files out of scope', (context) => {
88
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
89
+ const directory = join(root, 'llm');
90
+ const profile = fileURLToPath(new URL('biome-core.json', import.meta.url));
91
+
92
+ context.after(() => rmSync(root, { recursive: true, force: true }));
93
+ mkdirSync(directory);
94
+ writeFileSync(
95
+ join(directory, 'review.json'),
96
+ JSON.stringify({ linter: { rules: { recommended: false, suspicious: { noConsole: 'error' } } } }),
97
+ );
98
+ writeFileSync(join(root, 'good.ts'), 'export const value = 1;\n');
99
+ writeFileSync(join(root, 'bad.ts'), "console.log('noise');\n");
100
+
101
+ const good = execute(root, '--project-config', 'llm/review.json', 'good.ts');
102
+ const bad = execute(root, '--project-config', 'llm/review.json', 'bad.ts');
103
+
104
+ assert.equal(good.status, 0, good.stderr);
105
+ assert.equal(bad.status, 1);
106
+ assert.match(bad.stderr, /noConsole/u);
107
+ assert.equal(execute(root, 'bad.ts').status, 0);
108
+ assert.match(execute(root, '--project-config', profile, 'good.ts').stderr, /inside/u);
109
+ symlinkSync('review.json', join(directory, 'alias.json'));
110
+ assert.match(execute(root, '--project-config', 'llm/alias.json', 'good.ts').stderr, /project-owned/u);
111
+ });
112
+
113
+ test('enforces core types, explicit updates, braces, branches and class layout', (context) => {
114
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
115
+
116
+ context.after(() => rmSync(root, { recursive: true, force: true }));
117
+
118
+ writeFileSync(
119
+ join(root, 'shape.ts'),
120
+ [
121
+ 'export class Selection {',
122
+ ' public choose(flag: boolean): number {',
123
+ ' let count = 1;',
124
+ ' if (flag) count++;',
125
+ ' return count;',
126
+ ' }',
127
+ ' public static create(): Selection {',
128
+ ' return new Selection();',
129
+ ' }',
130
+ '}',
131
+ 'export const resolve = (value: boolean): string => (value ? "a" : "b");',
132
+ 'export const loose: any = 1;',
133
+ 'export const ambiguous: unknown = 2;',
134
+ ].join('\n'),
135
+ );
136
+
137
+ const result = executeFrom(checker, root, ['--lint-only', 'shape.ts'], {
138
+ ...process.env,
139
+ BIOME_BINARY: process.execPath,
140
+ });
141
+
142
+ assert.equal(result.status, 1);
143
+ assert.match(result.stderr, /Use an explicit update/);
144
+ assert.match(result.stderr, /useBlockStatements/);
145
+ assert.match(result.stderr, /explicit return/);
146
+ assert.match(result.stderr, /class member order/i);
147
+ assert.match(result.stderr, /noExplicitAny/);
148
+ assert.match(result.stderr, /Use an explicit domain type/);
149
+ });
150
+
151
+ test('uses the pinned Biome launcher when the target dotenv defines another binary', (context) => {
152
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
153
+
154
+ context.after(() => rmSync(root, { recursive: true, force: true }));
155
+
156
+ writeFileSync(join(root, '.env'), `BIOME_BINARY=${process.execPath}\n`);
157
+ writeFileSync(join(root, 'entry.ts'), 'export const sample = true;\n');
158
+
159
+ const result = execute(root, 'entry.ts');
160
+
161
+ assert.equal(result.status, 0, result.stderr);
162
+ assert.match(result.stdout, /Checked 1 file/);
163
+ });
164
+
165
+ test('uses separately selected React and tagged SQL checks', (context) => {
166
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
167
+
168
+ context.after(() => rmSync(root, { recursive: true, force: true }));
169
+
170
+ writeFileSync(join(root, 'Panel.tsx'), 'export default function Panel() { return <p>Hello</p>; }\n');
171
+ writeFileSync(join(root, 'Card.tsx'), 'const Card = () => <p>Hello</p>;\nexport default Card;\n');
172
+ writeFileSync(join(root, 'helper.ts'), 'export const UppercaseHelper = () => 1;\n');
173
+ writeFileSync(
174
+ join(root, 'query.ts'),
175
+ 'export const find = (sql: (strings: TemplateStringsArray) => string) => sql`select id from records`;\n',
176
+ );
177
+
178
+ const core = execute(root, '--lint-only', 'Panel.tsx', 'query.ts');
179
+
180
+ assert.equal(core.status, 0, core.stderr);
181
+
182
+ const react = execute(root, '--profile', 'react', '--lint-only', 'Panel.tsx');
183
+
184
+ assert.equal(react.status, 1);
185
+ assert.match(react.stderr, /named const component/);
186
+
187
+ const arrow = execute(root, '--profile', 'react', '--lint-only', 'Card.tsx');
188
+
189
+ assert.equal(arrow.status, 1);
190
+ assert.match(arrow.stderr, /Annotate React arrow components/);
191
+
192
+ const helper = execute(root, '--profile', 'react', '--lint-only', 'helper.ts');
193
+
194
+ assert.equal(helper.status, 0, helper.stderr);
195
+
196
+ writeFileSync(
197
+ join(root, 'event.tsx'),
198
+ 'export const view = <button onClick={() => { console.log("clicked"); }}>Go</button>;\n',
199
+ );
200
+
201
+ const plainEvent = execute(root, '--lint-only', 'event.tsx');
202
+
203
+ assert.equal(plainEvent.status, 0, plainEvent.stderr);
204
+
205
+ const reactEvent = execute(root, '--profile', 'react', '--lint-only', 'event.tsx');
206
+
207
+ assert.equal(reactEvent.status, 1);
208
+ assert.match(reactEvent.stderr, /inline JSX handler as one call expression/);
209
+
210
+ const sql = execute(root, '--profile', 'sql', '--lint-only', 'query.ts');
211
+
212
+ assert.equal(sql.status, 1);
213
+ assert.match(sql.stderr, /SQL keywords/i);
214
+ });
215
+
216
+ test('fails a mixed selection when Biome cannot check an oversized file', (context) => {
217
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
218
+
219
+ context.after(() => rmSync(root, { recursive: true, force: true }));
220
+ writeFileSync(join(root, 'small.ts'), 'export const sample = true;\n');
221
+ writeFileSync(join(root, 'large.ts'), `export const sample = '${'a'.repeat(1024 * 1024)}';\n`);
222
+
223
+ const result = execute(root, '--lint-only', 'small.ts', 'large.ts');
224
+
225
+ assert.equal(result.status, 1);
226
+ assert.match(result.stderr, /exceeds the configured maximum/);
227
+ });
228
+
229
+ test('refuses existing configurations, generated files, symlinks and an empty file selection', (context) => {
230
+ const root = mkdtempSync(join(tmpdir(), 'harness-style-'));
231
+
232
+ context.after(() => rmSync(root, { recursive: true, force: true }));
233
+
234
+ mkdirSync(join(root, 'app'));
235
+ writeFileSync(join(root, 'app', 'biome.jsonc'), '{}\n');
236
+ writeFileSync(join(root, 'app', 'module.ts'), 'export const sample = true;\n');
237
+ writeFileSync(join(root, 'generated.ts'), '// @generated\nexport const sample = true;\n');
238
+ symlinkSync(join(root, 'generated.ts'), join(root, 'linked.ts'));
239
+
240
+ const expected = [
241
+ { files: ['app/module.ts'], message: /project's configured Biome checks/ },
242
+ { files: ['generated.ts'], message: /instead of a generated artifact/ },
243
+ { files: ['linked.ts'], message: /instead of a symbolic link/ },
244
+ { files: ['../outside.ts'], message: /inside/ },
245
+ { files: [], message: /Supply the files you changed/ },
246
+ ];
247
+
248
+ for (const { files, message } of expected) {
249
+ const result = execute(root, ...files);
250
+
251
+ assert.equal(result.status, 1);
252
+ assert.match(result.stderr, message);
253
+ }
254
+
255
+ const child = join(root, 'app', 'child');
256
+
257
+ mkdirSync(child);
258
+ writeFileSync(join(child, 'module.ts'), 'export const sample = true;\n');
259
+
260
+ const parentConfiguration = execute(child, 'module.ts');
261
+
262
+ assert.equal(parentConfiguration.status, 1);
263
+ assert.match(parentConfiguration.stderr, /project's configured Biome checks/);
264
+ });