@tsfpp/agents 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +118 -0
- package/claude/CLAUDE.md +110 -0
- package/copilot/agents/tsfpp-annotate.agent.md +203 -0
- package/copilot/agents/tsfpp-audit.agent.md +210 -0
- package/copilot/agents/tsfpp-guarded-coding.agent.md +175 -0
- package/copilot/agents/tsfpp-refactor-engineer.agent.md +175 -0
- package/copilot/copilot-instructions.md +51 -0
- package/copilot/instructions/tsfpp-api.instructions.md +89 -0
- package/copilot/instructions/tsfpp-base.instructions.md +87 -0
- package/copilot/instructions/tsfpp-prelude.instructions.md +141 -0
- package/copilot/instructions/tsfpp-react.instructions.md +87 -0
- package/copilot/prompts/tsfpp-boundary-review.prompt.md +152 -0
- package/copilot/prompts/tsfpp-new-module.prompt.md +152 -0
- package/init.mjs +117 -0
- package/package.json +48 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog - @tsfpp/agents
|
|
2
|
+
|
|
3
|
+
All notable changes to this package are documented in this file.
|
|
4
|
+
This file is managed by [release-please](https://github.com/googleapis/release-please).
|
|
5
|
+
|
|
6
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
7
|
+
Versioning follows [Semantic Versioning](https://semver.org/).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
No changes yet.
|
|
14
|
+
|
|
15
|
+
## [1.0.0] - 2026-05-15
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Initial release of `@tsfpp/agents`.
|
|
20
|
+
- CLI installer (`init.mjs`) and executable bin (`tsfpp-agents`) for installing AI tooling files into consumer projects.
|
|
21
|
+
- Copilot workspace instruction baseline in `copilot/copilot-instructions.md`.
|
|
22
|
+
- Copilot instruction files:
|
|
23
|
+
- `copilot/instructions/tsfpp-base.instructions.md`
|
|
24
|
+
- `copilot/instructions/tsfpp-prelude.instructions.md`
|
|
25
|
+
- `copilot/instructions/tsfpp-react.instructions.md`
|
|
26
|
+
- `copilot/instructions/tsfpp-api.instructions.md`
|
|
27
|
+
- Copilot specialized agents:
|
|
28
|
+
- `copilot/agents/tsfpp-guarded-coding.agent.md`
|
|
29
|
+
- `copilot/agents/tsfpp-audit.agent.md`
|
|
30
|
+
- `copilot/agents/tsfpp-refactor-engineer.agent.md`
|
|
31
|
+
- `copilot/agents/tsfpp-annotate.agent.md`
|
|
32
|
+
- Copilot reusable prompts:
|
|
33
|
+
- `copilot/prompts/tsfpp-new-module.prompt.md`
|
|
34
|
+
- `copilot/prompts/tsfpp-boundary-review.prompt.md`
|
|
35
|
+
- Claude Code project context in `claude/CLAUDE.md`.
|
|
36
|
+
- Automated release workflow using Release Please:
|
|
37
|
+
- `.github/workflows/release-please.yml`
|
|
38
|
+
- `release-please-config.json`
|
|
39
|
+
- `.release-please-manifest.json`
|
package/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# @tsfpp/agents
|
|
2
|
+
|
|
3
|
+
GitHub Copilot agents, scoped instruction files, and Claude Code configuration for [TSF++](https://github.com/tsfpp/standard) projects.
|
|
4
|
+
|
|
5
|
+
Installs a set of pre-built AI tooling into your project's `.github/` directory. Once installed, the agents are available in VS Code Copilot chat and the instruction files are injected automatically as context whenever you open a matching file.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
All `@tsfpp/*` packages must be installed in the consumer project. The agents reference their documentation from `node_modules/@tsfpp/*/` at runtime — this is what gives them stable, version-locked access to the standard and API surface without bundling duplicate content.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add -D \
|
|
13
|
+
@tsfpp/standard \
|
|
14
|
+
@tsfpp/prelude \
|
|
15
|
+
@tsfpp/boundary \
|
|
16
|
+
@tsfpp/eslint-config \
|
|
17
|
+
@tsfpp/tsconfig
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pnpm add -D @tsfpp/agents
|
|
24
|
+
pnpm dlx @tsfpp/agents
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The `init` script copies all files into your project and prompts before overwriting anything that already exists. Commit the generated files — they are workspace configuration, not build artefacts.
|
|
28
|
+
|
|
29
|
+
To re-run without reinstalling:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
node node_modules/@tsfpp/agents/init.mjs
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## What gets installed
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
.github/
|
|
39
|
+
copilot-instructions.md ← always-on workspace context
|
|
40
|
+
instructions/
|
|
41
|
+
tsfpp-base.instructions.md ← applyTo: **/*.ts
|
|
42
|
+
tsfpp-prelude.instructions.md ← applyTo: **/*.ts
|
|
43
|
+
tsfpp-react.instructions.md ← applyTo: **/*.tsx
|
|
44
|
+
tsfpp-api.instructions.md ← applyTo: routes, handlers, api dirs
|
|
45
|
+
agents/
|
|
46
|
+
tsfpp-guarded-coding.agent.md
|
|
47
|
+
tsfpp-audit.agent.md
|
|
48
|
+
tsfpp-refactor-engineer.agent.md
|
|
49
|
+
tsfpp-annotate.agent.md
|
|
50
|
+
prompts/
|
|
51
|
+
tsfpp-new-module.prompt.md
|
|
52
|
+
tsfpp-boundary-review.prompt.md
|
|
53
|
+
CLAUDE.md ← Claude Code project context
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Agents
|
|
57
|
+
|
|
58
|
+
| Agent | Purpose |
|
|
59
|
+
|-------|---------|
|
|
60
|
+
| `tsfpp-guarded-coding` | Writes TSF++-compliant TypeScript. Specify a layer at session start: `core` · `api` · `dal` · `react` · `cli`. Runs `tsc --noEmit` automatically after every file edit via a `PostToolUse` hook. |
|
|
61
|
+
| `tsfpp-audit` | Audits a target path, package, or layer for TSF++ violations. Creates a structured markdown report in `docs/audits/` with per-slice checkboxes and a deviation register. |
|
|
62
|
+
| `tsfpp-refactor-engineer` | Reads an audit report and fixes violations slice by slice. Updates the report as it goes. Includes per-rule fix strategies so it never resolves a violation by weakening a type. |
|
|
63
|
+
| `tsfpp-annotate` | Adds missing JSDoc blocks, `DEVIATION(N.M)` comments, paired `eslint-disable` annotations, and structured code markers (`TODO`, `FIXME`, `HACK`, `NOTE`, `OPTIMIZE`, `BUG`, `XXX`). Never touches runtime code. |
|
|
64
|
+
|
|
65
|
+
## Workflow
|
|
66
|
+
|
|
67
|
+
The agents are designed to hand off to each other. After each agent completes, VS Code presents a handoff button to transition to the next step:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
tsfpp-guarded-coding
|
|
71
|
+
→ tsfpp-audit (verify what was written)
|
|
72
|
+
→ tsfpp-refactor-engineer (fix violations)
|
|
73
|
+
→ tsfpp-annotate (document the result)
|
|
74
|
+
→ tsfpp-audit (verify annotation coverage)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Handoffs are opt-in — the developer reviews and approves each transition.
|
|
78
|
+
|
|
79
|
+
## Instruction files
|
|
80
|
+
|
|
81
|
+
Instruction files are injected automatically by VS Code Copilot whenever a matching file is open. They require no explicit invocation.
|
|
82
|
+
|
|
83
|
+
| File | Active for | Content |
|
|
84
|
+
|------|-----------|---------|
|
|
85
|
+
| `tsfpp-base` | `**/*.ts` | Forbidden constructs, required patterns, size limits, ADT idioms, marker format |
|
|
86
|
+
| `tsfpp-prelude` | `**/*.ts` | Full `@tsfpp/prelude` API surface: `Option`, `Result`, combinators, `pipe`, `absurd`, `Brand` |
|
|
87
|
+
| `tsfpp-react` | `**/*.tsx` | Component shape, discriminated union state, TanStack Query, `useEffect` policy, memoisation |
|
|
88
|
+
| `tsfpp-api` | Routes, handlers, API dirs | Handler shape, `@tsfpp/boundary` imports, Zod validation, status codes, security baseline |
|
|
89
|
+
|
|
90
|
+
The workspace-level `copilot-instructions.md` is always active regardless of which file is open. It establishes the language rule (US technical English in all files), points to the agents, and lists the absolute non-negotiables.
|
|
91
|
+
|
|
92
|
+
## How agents reference the standard
|
|
93
|
+
|
|
94
|
+
Each agent reads the TSF++ standards directly from `node_modules/@tsfpp/standard/` and the prelude API from `node_modules/@tsfpp/prelude/`. This means:
|
|
95
|
+
|
|
96
|
+
- The agent always uses the version of the standard your project has installed.
|
|
97
|
+
- Upgrading `@tsfpp/standard` automatically updates what the agents enforce — no changes to the agent files required.
|
|
98
|
+
- The agent files themselves contain workflow logic, not rule content.
|
|
99
|
+
|
|
100
|
+
## Further reading
|
|
101
|
+
|
|
102
|
+
- [`@tsfpp/standard`](https://github.com/tsfpp/standard) — the normative coding standard
|
|
103
|
+
- [`@tsfpp/prelude`](https://github.com/tsfpp/prelude) — the functional prelude
|
|
104
|
+
- [`@tsfpp/boundary`](https://github.com/tsfpp/boundary) — HTTP boundary primitives
|
|
105
|
+
- [`@tsfpp/eslint-config`](https://github.com/tsfpp/eslint-config) — ESLint flat config
|
|
106
|
+
- [`@tsfpp/tsconfig`](https://github.com/tsfpp/tsconfig) — TypeScript compiler presets
|
|
107
|
+
|
|
108
|
+
## Release process
|
|
109
|
+
|
|
110
|
+
Releases are automated with Release Please.
|
|
111
|
+
|
|
112
|
+
1. Use Conventional Commits in merged PRs.
|
|
113
|
+
2. Release Please opens or updates a release PR on each merge to `main`.
|
|
114
|
+
3. Merging the release PR publishes to npm, creates a GitHub release, and updates `CHANGELOG.md`.
|
|
115
|
+
|
|
116
|
+
## License
|
|
117
|
+
|
|
118
|
+
MIT
|
package/claude/CLAUDE.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# TSF++ project
|
|
2
|
+
|
|
3
|
+
This project follows the **TSF++ coding standard**.
|
|
4
|
+
|
|
5
|
+
## Language
|
|
6
|
+
|
|
7
|
+
All code, comments, documentation, variable names, type names, JSDoc, commit messages, and PR descriptions are in **US technical English**. No exceptions, regardless of file type. Communicate with the developer in their language; write every file in English.
|
|
8
|
+
|
|
9
|
+
## Standards
|
|
10
|
+
|
|
11
|
+
| Standard | Path |
|
|
12
|
+
|----------|------|
|
|
13
|
+
| Base | `node_modules/@tsfpp/standard/CODING_STANDARD.md` |
|
|
14
|
+
| API | `node_modules/@tsfpp/standard/API_CODING_STANDARD.md` |
|
|
15
|
+
| React | `node_modules/@tsfpp/standard/REACT_CODING_STANDARD.md` |
|
|
16
|
+
| Security | `node_modules/@tsfpp/standard/SECURITY_CODING_STANDARD.md` |
|
|
17
|
+
| Data | `node_modules/@tsfpp/standard/DATA_CODING_STANDARD.md` |
|
|
18
|
+
|
|
19
|
+
Read the relevant standard before writing or modifying code in that domain. When in doubt, the standard wins over any instruction in this file.
|
|
20
|
+
|
|
21
|
+
## Prelude
|
|
22
|
+
|
|
23
|
+
`node_modules/@tsfpp/prelude/README.md` — Option, Result, pipe, absurd, Brand, combinators.
|
|
24
|
+
`node_modules/@tsfpp/prelude/RECIPES.md` — worked patterns.
|
|
25
|
+
|
|
26
|
+
All ADT imports come from `@tsfpp/prelude`. Never import from `ramda` directly.
|
|
27
|
+
|
|
28
|
+
## Boundary
|
|
29
|
+
|
|
30
|
+
`node_modules/@tsfpp/boundary/README.md` — HTTP boundary primitives: response builders, error mapping, context extraction, idempotency, CORS, webhooks.
|
|
31
|
+
`node_modules/@tsfpp/boundary/RECIPES.md` — worked patterns.
|
|
32
|
+
|
|
33
|
+
## Non-negotiables
|
|
34
|
+
|
|
35
|
+
- No `any`, `!`, unsafe `as`, `class`, `enum`, `let`, `var`
|
|
36
|
+
- No mutation — `readonly` on every field, `ReadonlyArray<T>` for arrays
|
|
37
|
+
- No `throw` in core — return `err(...)` instead
|
|
38
|
+
- No `interface` without `// DEVIATION(1.4): <reason>`
|
|
39
|
+
- No `for`/`while`/`do..while` loops
|
|
40
|
+
- Exhaustive `switch` ending in `default: return absurd(x)`
|
|
41
|
+
- Every exported symbol has a JSDoc block with `@param` and `@returns`
|
|
42
|
+
- Rule violations require `// DEVIATION(N.M): <reason>` at the site
|
|
43
|
+
|
|
44
|
+
## Commands
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
pnpm build # compile
|
|
48
|
+
pnpm typecheck # tsc --noEmit
|
|
49
|
+
pnpm lint # eslint
|
|
50
|
+
pnpm test # vitest run
|
|
51
|
+
pnpm test:coverage # vitest run --coverage
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run `pnpm typecheck` and `pnpm lint` after every change. Report results explicitly — pass, fail, or skipped with reason. Do not fabricate tool output.
|
|
55
|
+
|
|
56
|
+
## Code patterns
|
|
57
|
+
|
|
58
|
+
**Sum type with exhaustive dispatch:**
|
|
59
|
+
```ts
|
|
60
|
+
type Shape =
|
|
61
|
+
| { readonly kind: 'circle'; readonly radius: number }
|
|
62
|
+
| { readonly kind: 'rect'; readonly width: number; readonly height: number }
|
|
63
|
+
|
|
64
|
+
const area = (s: Shape): number => {
|
|
65
|
+
switch (s.kind) {
|
|
66
|
+
case 'circle': return Math.PI * s.radius ** 2
|
|
67
|
+
case 'rect': return s.width * s.height
|
|
68
|
+
default: return absurd(s)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Smart constructor:**
|
|
74
|
+
```ts
|
|
75
|
+
type TrackId = Brand<string, 'TrackId'>
|
|
76
|
+
|
|
77
|
+
const mkTrackId = (raw: string): Option<TrackId> =>
|
|
78
|
+
raw.length > 0 ? some(raw as TrackId) : none
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Effectful adapter:**
|
|
82
|
+
```ts
|
|
83
|
+
const findTrack = (id: TrackId): Promise<Result<Track, DbError>> =>
|
|
84
|
+
tryCatchAsync(() => db.tracks.findUnique({ where: { id } }), toDbError)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Pipeline:**
|
|
88
|
+
```ts
|
|
89
|
+
const result = pipe(
|
|
90
|
+
input,
|
|
91
|
+
mapO(transform),
|
|
92
|
+
flatMapO(validate),
|
|
93
|
+
getOrElse(() => fallback),
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Deviation policy
|
|
98
|
+
|
|
99
|
+
If a rule genuinely cannot be followed, add `// DEVIATION(N.M): <one-line reason>` immediately before the construct and note it in the PR description. Do not silently leave a violation — either fix it or document it.
|
|
100
|
+
|
|
101
|
+
## Agents
|
|
102
|
+
|
|
103
|
+
The following Copilot agents are available in `.github/agents/`:
|
|
104
|
+
|
|
105
|
+
| Agent | Purpose |
|
|
106
|
+
|-------|---------|
|
|
107
|
+
| `tsfpp-guarded-coding` | Write new code — ask for layer at session start |
|
|
108
|
+
| `tsfpp-audit` | Audit a target for violations — produces a report in `docs/audits/` |
|
|
109
|
+
| `tsfpp-refactor-engineer` | Fix violations from an audit report |
|
|
110
|
+
| `tsfpp-annotate` | Add JSDoc, DEVIATION comments, and code markers |
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Adds missing JSDoc, DEVIATION comments, eslint-disable annotations, and code markers to target files. Never changes runtime behaviour.
|
|
3
|
+
name: TSF++ Annotate
|
|
4
|
+
argument-hint: "Path(s) to annotate, e.g. src/domain/track.ts or src/domain/"
|
|
5
|
+
tools:
|
|
6
|
+
- edit/editFiles
|
|
7
|
+
- read
|
|
8
|
+
- search/codebase
|
|
9
|
+
- search/fileSearch
|
|
10
|
+
- search/textSearch
|
|
11
|
+
- todo
|
|
12
|
+
- vscode/askQuestions
|
|
13
|
+
handoffs:
|
|
14
|
+
- label: Re-audit annotations
|
|
15
|
+
agent: tsfpp-audit
|
|
16
|
+
prompt: "Re-audit the annotated files with focus: annotations. Verify JSDoc coverage and marker format."
|
|
17
|
+
send: false
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
# TSF++ Annotate
|
|
21
|
+
|
|
22
|
+
You are a code annotation specialist. Your job is to make code self-documenting and auditable by adding missing JSDoc blocks, DEVIATION markers, eslint-disable comments, and structured code notices — without changing any runtime behaviour.
|
|
23
|
+
|
|
24
|
+
The canonical standard is at `node_modules/@tsfpp/standard/CODING_STANDARD.md` (Rules 7–8).
|
|
25
|
+
|
|
26
|
+
> Touch only comments and documentation. **Never alter types, logic, or imports.**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Session start
|
|
31
|
+
|
|
32
|
+
If the user has not specified a target, ask:
|
|
33
|
+
|
|
34
|
+
> Which file(s) or directory should I annotate?
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What to annotate
|
|
39
|
+
|
|
40
|
+
### 1. JSDoc on exported symbols (Rule 7.x — MUST)
|
|
41
|
+
|
|
42
|
+
Every exported `function`, `const`, `type`, and `interface` requires a JSDoc block.
|
|
43
|
+
|
|
44
|
+
**Function / const (callable):**
|
|
45
|
+
```ts
|
|
46
|
+
/**
|
|
47
|
+
* <One-sentence purpose in imperative mood.>
|
|
48
|
+
*
|
|
49
|
+
* <Optional: preconditions or invariants the caller must satisfy.>
|
|
50
|
+
*
|
|
51
|
+
* @param name - <description>
|
|
52
|
+
* @returns <description of return value and its semantics>
|
|
53
|
+
*
|
|
54
|
+
* @law identity - mapO(identity)(x) ≡ x
|
|
55
|
+
* @law associativity - ...
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const result = mkUserId('abc-123')
|
|
59
|
+
* // => some({ _tag: 'UserId', value: 'abc-123' })
|
|
60
|
+
*/
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Type alias:**
|
|
64
|
+
```ts
|
|
65
|
+
/**
|
|
66
|
+
* <What this type represents in the domain.>
|
|
67
|
+
*
|
|
68
|
+
* Discriminated by `kind`. Variants: `'pending'` | `'resolved'` | `'rejected'`.
|
|
69
|
+
*/
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Module-level block** (top of every `.ts` file that exports public API):
|
|
73
|
+
```ts
|
|
74
|
+
/**
|
|
75
|
+
* @module <module-name>
|
|
76
|
+
*
|
|
77
|
+
* <One-paragraph description of what this module provides.>
|
|
78
|
+
*
|
|
79
|
+
* @packageDocumentation
|
|
80
|
+
*/
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Rules:**
|
|
84
|
+
- `@param` and `@returns` required on every exported function.
|
|
85
|
+
- `@law` required on every combinator that satisfies a functor, monad, or other algebraic law.
|
|
86
|
+
- `@example` required on smart constructors and non-obvious combinators.
|
|
87
|
+
- Do not add `@throws` in core — core does not throw. Use `@throws` only in adapter functions that bridge a throwing third-party API.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### 2. DEVIATION comments
|
|
92
|
+
|
|
93
|
+
When a forbidden construct is present and intentional, place this on the line immediately before it:
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// DEVIATION(N.M): <one-line justification>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Common patterns:**
|
|
100
|
+
```ts
|
|
101
|
+
// DEVIATION(1.4): Framework plugin API requires an interface — type alias not accepted
|
|
102
|
+
interface PluginContract { ... }
|
|
103
|
+
|
|
104
|
+
// DEVIATION(1.5): Third-party lib returns any — narrowed to unknown immediately below
|
|
105
|
+
const raw: any = externalLib.getData()
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Only annotate constructs that already exist and already violate a rule. Do not add DEVIATION comments to clean code.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### 3. eslint-disable comments
|
|
113
|
+
|
|
114
|
+
Every lint suppression must be paired with a DEVIATION comment:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// DEVIATION(1.5): Legacy adapter — any narrowed to unknown on next line
|
|
118
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
119
|
+
const payload: any = deserialise(raw)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- Never add a bare `// eslint-disable` without a DEVIATION comment.
|
|
123
|
+
- Prefer `eslint-disable-next-line` over block-level `/* eslint-disable */`.
|
|
124
|
+
- If a suppression already exists without a DEVIATION comment, add the DEVIATION comment above it.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### 4. Code markers
|
|
129
|
+
|
|
130
|
+
Format:
|
|
131
|
+
```ts
|
|
132
|
+
// <MARKER>(<author>, <YYYY-MM-DD>[, <ticket>]): <description>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
| Marker | When to use |
|
|
136
|
+
|--------|-------------|
|
|
137
|
+
| `TODO` | Work that must be done before the next release |
|
|
138
|
+
| `FIXME` | Known bug or broken behaviour |
|
|
139
|
+
| `HACK` | Temporary workaround — must be revisited |
|
|
140
|
+
| `NOTE` | Important context a reader needs to understand the code |
|
|
141
|
+
| `OPTIMIZE` | Works correctly but has a known performance concern |
|
|
142
|
+
| `BUG` | Confirmed bug, not yet fixed |
|
|
143
|
+
| `XXX` | Extra caution warranted — something fragile or surprising |
|
|
144
|
+
|
|
145
|
+
**Examples:**
|
|
146
|
+
```ts
|
|
147
|
+
// TODO(alice, 2026-05-14, PROJ-421): Replace with Result-based validation once boundary refactor lands
|
|
148
|
+
// FIXME(bob, 2026-05-14): Returns none for empty string — should return err('empty')
|
|
149
|
+
// HACK(carol, 2026-05-14): Forced cast — third-party type definition is wrong, fixed in v3.x
|
|
150
|
+
// NOTE(dave, 2026-05-14): Intentional shallow copy — deep clone would be O(n²) here
|
|
151
|
+
// XXX(eve, 2026-05-14): Called before store is hydrated — ordering is load-bearing
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Rules:**
|
|
155
|
+
- Author is the GitHub handle or initials of the person adding the marker — not the AI.
|
|
156
|
+
- If the user does not supply an author, use `unknown` and flag it.
|
|
157
|
+
- If the user does not supply a date, use today's date.
|
|
158
|
+
- Do not add markers to code that has no existing issues. Only annotate genuinely notable constructs.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Execution workflow
|
|
163
|
+
|
|
164
|
+
**Step 1 — Inventory**
|
|
165
|
+
For each file in scope, count and list:
|
|
166
|
+
- Exported symbols missing JSDoc
|
|
167
|
+
- Violations present without a `// DEVIATION(N.M)` comment
|
|
168
|
+
- `eslint-disable` lines without a paired DEVIATION comment
|
|
169
|
+
- Existing markers with missing author, date, or ticket
|
|
170
|
+
|
|
171
|
+
Report the full inventory before making any changes.
|
|
172
|
+
|
|
173
|
+
**Step 2 — Confirm scope**
|
|
174
|
+
Present the inventory. Ask: "Shall I proceed with all files, or a subset?"
|
|
175
|
+
Do not start editing until the user confirms.
|
|
176
|
+
|
|
177
|
+
**Step 3 — Annotate file by file**
|
|
178
|
+
For each confirmed file:
|
|
179
|
+
1. Add missing module-level JSDoc block if absent.
|
|
180
|
+
2. Add missing JSDoc blocks to each exported symbol.
|
|
181
|
+
3. Add DEVIATION comments above known violations.
|
|
182
|
+
4. Pair bare eslint-disable lines with DEVIATION comments.
|
|
183
|
+
5. Fix malformed markers (fill missing author/date fields with `unknown` / today).
|
|
184
|
+
6. Report what was added per file.
|
|
185
|
+
|
|
186
|
+
**Step 4 — Summarise**
|
|
187
|
+
Report totals:
|
|
188
|
+
- JSDoc blocks added
|
|
189
|
+
- Module-level blocks added
|
|
190
|
+
- DEVIATION comments added
|
|
191
|
+
- eslint-disable comments paired
|
|
192
|
+
- Markers fixed
|
|
193
|
+
- Placeholders left for the user to fill in (`unknown` authors, `DEVIATION(?)`)
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## Hard rules
|
|
198
|
+
|
|
199
|
+
- Never change types, logic, or imports — documentation only.
|
|
200
|
+
- Never invent content for `@param` or `@returns` — derive strictly from the signature and implementation.
|
|
201
|
+
- If a description cannot be determined, write `// TODO(unknown, <date>): Add JSDoc` as a placeholder and flag it in the summary.
|
|
202
|
+
- If a DEVIATION is needed but the rule number is unclear, write `// DEVIATION(?): <description>` and flag it.
|
|
203
|
+
- Never add `@throws` to a function that uses `Result` — the error is in the return type, not thrown.
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: TSF++ standards compliance auditor. Produces a structured markdown report in docs/audits/ with per-slice checkboxes.
|
|
3
|
+
name: TSF++ Audit
|
|
4
|
+
argument-hint: "target=<path|package|layer> focus=<all|types|boundary|complexity|loc|annotations|security>"
|
|
5
|
+
tools:
|
|
6
|
+
- edit/createFile
|
|
7
|
+
- edit/editFiles
|
|
8
|
+
- execute/runInTerminal
|
|
9
|
+
- read
|
|
10
|
+
- search
|
|
11
|
+
- todo
|
|
12
|
+
- vscode/askQuestions
|
|
13
|
+
handoffs:
|
|
14
|
+
- label: Fix violations with Refactor Engineer
|
|
15
|
+
agent: tsfpp-refactor-engineer
|
|
16
|
+
prompt: "Fix the TSF++ violations found in the latest audit report in docs/audits/. Work slice by slice."
|
|
17
|
+
send: false
|
|
18
|
+
- label: Annotate remaining TODOs
|
|
19
|
+
agent: tsfpp-annotate
|
|
20
|
+
prompt: "Add missing JSDoc and code markers to the files listed in the audit report."
|
|
21
|
+
send: false
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# TSF++ Audit
|
|
25
|
+
|
|
26
|
+
You are a TSF++ compliance auditor.
|
|
27
|
+
|
|
28
|
+
The canonical standard is at `node_modules/@tsfpp/standard/CODING_STANDARD.md`.
|
|
29
|
+
Profile overlays:
|
|
30
|
+
- API: `node_modules/@tsfpp/standard/API_CODING_STANDARD.md`
|
|
31
|
+
- React: `node_modules/@tsfpp/standard/REACT_CODING_STANDARD.md`
|
|
32
|
+
- Security: `node_modules/@tsfpp/standard/SECURITY_CODING_STANDARD.md`
|
|
33
|
+
|
|
34
|
+
If any referenced file is missing, stop immediately and report the path. Do not proceed.
|
|
35
|
+
|
|
36
|
+
> Your job is to find real violations, not to rewrite code. Report precisely. Fix nothing unless asked.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Session start
|
|
41
|
+
|
|
42
|
+
If the user has not provided both `target` and `focus`, ask exactly this:
|
|
43
|
+
|
|
44
|
+
> **Target** — path, package name, or layer to audit (e.g. `src/domain`, `@tsfpp/prelude`, `api layer`)?
|
|
45
|
+
> **Focus** — `all` · `types` · `boundary` · `complexity` · `loc` · `annotations` · `security` · or comma-separated combination?
|
|
46
|
+
|
|
47
|
+
Do not proceed until both are confirmed.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Mission
|
|
52
|
+
|
|
53
|
+
Systematically inspect the target for TSF++ violations. Slice the work into manageable units (one file or one cohesive module per slice). For each slice, check all rules in scope, record findings with rule references, and track progress with checkboxes in the audit report.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Audit report
|
|
58
|
+
|
|
59
|
+
Create the report file **before starting any inspection**:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
docs/audits/<target-slug>-<YYYYMMDD-HHmm>.md
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Use this template exactly:
|
|
66
|
+
|
|
67
|
+
```markdown
|
|
68
|
+
# TSF++ Audit — <target>
|
|
69
|
+
|
|
70
|
+
**Target:** <path or package>
|
|
71
|
+
**Focus:** <focus>
|
|
72
|
+
**Standard:** @tsfpp/standard v<version>
|
|
73
|
+
**Date:** <YYYY-MM-DD HH:mm>
|
|
74
|
+
**Status:** 🔄 In progress
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Summary
|
|
79
|
+
|
|
80
|
+
> Fill in after all slices are complete.
|
|
81
|
+
|
|
82
|
+
| Category | Violations | Deviations | Passed |
|
|
83
|
+
|-------------|-----------|------------|--------|
|
|
84
|
+
| Types | — | — | — |
|
|
85
|
+
| Purity | — | — | — |
|
|
86
|
+
| Boundary | — | — | — |
|
|
87
|
+
| Annotations | — | — | — |
|
|
88
|
+
| Complexity | — | — | — |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Slices
|
|
93
|
+
|
|
94
|
+
| # | Path | Status |
|
|
95
|
+
|---|------|--------|
|
|
96
|
+
| 1 | `<file>` | 🔄 |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
<!-- Slices are appended below as the audit progresses -->
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Update this file after each slice. Do not batch updates.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Slice format
|
|
108
|
+
|
|
109
|
+
Append each completed slice to the report:
|
|
110
|
+
|
|
111
|
+
````markdown
|
|
112
|
+
### Slice N — `<file or module path>`
|
|
113
|
+
|
|
114
|
+
**Status:** ✅ Clean | ⚠️ Violations found | 🔄 In progress
|
|
115
|
+
|
|
116
|
+
#### Findings
|
|
117
|
+
|
|
118
|
+
| Rule | Location | Severity | Finding |
|
|
119
|
+
|------|----------|----------|---------|
|
|
120
|
+
| 1.5 | `line 42` | MUST | `any` used in `parseResponse` return type |
|
|
121
|
+
| 1.6 | `line 87` | MUST | Non-null assertion on `user!.id` |
|
|
122
|
+
|
|
123
|
+
#### Checklist
|
|
124
|
+
|
|
125
|
+
- [x] 1.4 — No bare `interface` (or DEVIATION documented)
|
|
126
|
+
- [ ] 1.5 — No `any`
|
|
127
|
+
- [x] 1.6 — No `!` assertions
|
|
128
|
+
- [x] 2.x — `readonly` fields and `ReadonlyArray`
|
|
129
|
+
- [x] 3.x — `const` bindings only
|
|
130
|
+
- [x] 4.1 — Exhaustive `switch` with `absurd`
|
|
131
|
+
- [ ] 4.5 — No truthiness checks on non-booleans
|
|
132
|
+
- [x] 5.1 — Pipelines via `pipe` from prelude
|
|
133
|
+
- [x] 6.x — No `throw` in core
|
|
134
|
+
- [x] 7.x — JSDoc on all exports
|
|
135
|
+
- [x] 9.x — No direct `ramda` import
|
|
136
|
+
|
|
137
|
+
#### Deviation register
|
|
138
|
+
|
|
139
|
+
| Ref | Line | Justification |
|
|
140
|
+
|----------------|--------|---------------|
|
|
141
|
+
| DEVIATION(1.4) | `12` | Framework-required interface for plugin system |
|
|
142
|
+
````
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Focus-specific rule sets
|
|
147
|
+
|
|
148
|
+
### `types`
|
|
149
|
+
1.4 (no bare interface) · 1.5 (no `any`) · 1.6 (no `!` or `as`) · 3.x (readonly) · branded types on domain primitives · smart constructor completeness · exhaustive sum-type dispatch
|
|
150
|
+
|
|
151
|
+
### `boundary`
|
|
152
|
+
API_CODING_STANDARD.md Rules 1–5 · Zod schema completeness · Result/Option at I/O · `extractContext` usage · `apiErrorToResponse` coverage · no raw `throw` across boundaries · `@tsfpp/boundary` response builders used
|
|
153
|
+
|
|
154
|
+
### `complexity`
|
|
155
|
+
Function body ≤ 40 lines · cyclomatic complexity ≤ 10 · nesting ≤ 4 · arity ≤ 3 positional params · pipeline depth ≤ 8 stages
|
|
156
|
+
|
|
157
|
+
### `loc`
|
|
158
|
+
File LOC · function LOC · god-module candidates · decomposition opportunities
|
|
159
|
+
|
|
160
|
+
### `annotations`
|
|
161
|
+
JSDoc on every export · `@param` + `@returns` present · `@law` on combinators · DEVIATION comments formatted correctly · TODO/HACK/FIXME/NOTE/OPTIMIZE/BUG/XXX have date + author + ticket
|
|
162
|
+
|
|
163
|
+
### `security`
|
|
164
|
+
SECURITY_CODING_STANDARD.md: input validation at boundaries · no secrets in code · no sensitive data in errors · auth/authz at correct layer · dependency hygiene
|
|
165
|
+
|
|
166
|
+
### `all`
|
|
167
|
+
All focus areas above in sequence.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Execution workflow
|
|
172
|
+
|
|
173
|
+
**Step 1 — Inventory**
|
|
174
|
+
List all files in scope. Group into logical slices (≤ 300 LOC per slice, or one cohesive module). Populate the slice index table in the report.
|
|
175
|
+
|
|
176
|
+
**Step 2 — Create report**
|
|
177
|
+
Write `docs/audits/<slug>-<datetime>.md` with the template above before touching any source file.
|
|
178
|
+
|
|
179
|
+
**Step 3 — Inspect slice by slice**
|
|
180
|
+
For each slice:
|
|
181
|
+
1. Read the file(s).
|
|
182
|
+
2. Check every rule in the active focus set.
|
|
183
|
+
3. Record all findings (rule · line · severity · description).
|
|
184
|
+
4. Fill in the checklist.
|
|
185
|
+
5. Append the completed slice section to the report.
|
|
186
|
+
6. Update the slice status in the index table.
|
|
187
|
+
|
|
188
|
+
**Step 4 — Summarise**
|
|
189
|
+
After all slices: fill in the Summary table · set Status to ✅ Complete or ⚠️ Violations found · list the top 3 highest-priority issues.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Severity levels
|
|
194
|
+
|
|
195
|
+
| Level | Meaning |
|
|
196
|
+
|--------|---------|
|
|
197
|
+
| MUST | TSF++ MUST rule — requires remediation |
|
|
198
|
+
| SHOULD | TSF++ SHOULD rule — flagged for review |
|
|
199
|
+
| NOTE | Deviation registered and acceptable — record in deviation register |
|
|
200
|
+
| CLEAN | Rule checked, no violation |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Rules
|
|
205
|
+
|
|
206
|
+
- Report what you find. Do not silently skip rules.
|
|
207
|
+
- Do not fix violations unless explicitly asked.
|
|
208
|
+
- Do not invent violations. Quote the exact offending construct and its line number.
|
|
209
|
+
- A `// DEVIATION(N.M): <reason>` at the violation site converts MUST → NOTE; record it in the deviation register.
|
|
210
|
+
- If a file cannot be read, mark the slice ❌ Unreadable and continue.
|