feat: 1995
This commit is contained in:
commit
fb89263930
69 changed files with 3359 additions and 0 deletions
14
.agents/commands/sketch.md
Normal file
14
.agents/commands/sketch.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
Execute an approved OpenSpec change.
|
||||
|
||||
Arguments:
|
||||
- `$1` = OpenSpec change id.
|
||||
- `--sync` = use Forgejo sync mode.
|
||||
- `--status` = summarize state only; do not edit files.
|
||||
|
||||
Load and follow the OpenSpec apply workflow and the `forge-sync` skill.
|
||||
|
||||
Rules:
|
||||
- Treat mode as explicit. Do not ask whether git workflow should be agent-managed.
|
||||
- Apply tasks from `openspec/changes/<change-id>/tasks.md`.
|
||||
- After each completed numbered task section, run a `forge-sync` checkpoint.
|
||||
- Do not archive the OpenSpec change.
|
||||
214
.agents/resources/commitlint.md
Normal file
214
.agents/resources/commitlint.md
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
@commitlint/config-conventional
|
||||
===============================
|
||||
|
||||
Lint your conventional commits
|
||||
|
||||
Shareable `commitlint` config enforcing [conventional commits](https://conventionalcommits.org/). Use with [@commitlint/cli](https://npm.im/@commitlint/cli) and [@commitlint/prompt-cli](https://npm.im/@commitlint/prompt-cli).
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
```
|
||||
npm install --save-dev @commitlint/config-conventional @commitlint/cli
|
||||
echo "export default {extends: \['@commitlint/config-conventional'\]};" \> commitlint.config.js
|
||||
```
|
||||
|
||||
Rules
|
||||
-----
|
||||
|
||||
### Problems
|
||||
|
||||
The following rules are considered problems for `@commitlint/config-conventional` and will yield a non-zero exit code when not met.
|
||||
|
||||
Consult [Rules reference](https://commitlint.js.org/reference/rules) for a list of available rules.
|
||||
|
||||
#### type-enum
|
||||
|
||||
- **condition**: `type` is found in value
|
||||
|
||||
- **rule**: `always`
|
||||
|
||||
- **level**: `error`
|
||||
|
||||
- **value**
|
||||
|
||||
```
|
||||
[
|
||||
'build',
|
||||
'chore',
|
||||
'ci',
|
||||
'docs',
|
||||
'feat',
|
||||
'fix',
|
||||
'perf',
|
||||
'refactor',
|
||||
'revert',
|
||||
'style',
|
||||
'test'
|
||||
];
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
echo "foo: some message" # fails
|
||||
echo "fix: some message" # passes
|
||||
```
|
||||
|
||||
#### type-case
|
||||
|
||||
- **description**: `type` is in case `value`
|
||||
- **rule**: `always`
|
||||
- **level**: `error`
|
||||
- **value**
|
||||
```
|
||||
'lowerCase'
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
echo "FIX: some message" # fails
|
||||
echo "fix: some message" # passes
|
||||
```
|
||||
|
||||
#### type-empty
|
||||
|
||||
- **condition**: `type` is empty
|
||||
- **rule**: `never`
|
||||
- **level**: `error`
|
||||
|
||||
```
|
||||
echo ": some message" # fails
|
||||
echo "fix: some message" # passes
|
||||
```
|
||||
|
||||
#### subject-case
|
||||
|
||||
- **condition**: `subject` is in one of the cases `['sentence-case', 'start-case', 'pascal-case', 'upper-case']`
|
||||
- **rule**: `never`
|
||||
- **level**: `error`
|
||||
|
||||
```
|
||||
echo "fix(SCOPE): Some message" # fails
|
||||
echo "fix(SCOPE): Some Message" # fails
|
||||
echo "fix(SCOPE): SomeMessage" # fails
|
||||
echo "fix(SCOPE): SOMEMESSAGE" # fails
|
||||
echo "fix(scope): some message" # passes
|
||||
echo "fix(scope): some Message" # passes
|
||||
```
|
||||
|
||||
#### subject-empty
|
||||
|
||||
- **condition**: `subject` is empty
|
||||
- **rule**: `never`
|
||||
- **level**: `error`
|
||||
|
||||
```
|
||||
echo "fix:" # fails
|
||||
echo "fix: some message" # passes
|
||||
```
|
||||
|
||||
#### subject-full-stop
|
||||
|
||||
- **condition**: `subject` ends with `value`
|
||||
- **rule**: `never`
|
||||
- **level**: `error`
|
||||
- **value**
|
||||
|
||||
```
|
||||
'.'
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
echo "fix: some message." # fails
|
||||
echo "fix: some message" # passes
|
||||
```
|
||||
|
||||
#### header-max-length
|
||||
|
||||
- **condition**: `header` has `value` or less characters
|
||||
- **rule**: `always`
|
||||
- **level**: `error`
|
||||
- **value**
|
||||
|
||||
```
|
||||
100
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
echo "fix: some message that is way too long and breaks the line max-length by several characters" # fails
|
||||
echo "fix: some message" # passes
|
||||
```
|
||||
|
||||
#### footer-leading-blank
|
||||
|
||||
- **condition**: `footer` should have a leading blank line
|
||||
- **rule**: `always`
|
||||
- **level**: `warning`
|
||||
|
||||
```
|
||||
echo "fix: some message
|
||||
BREAKING CHANGE: It will be significant" # warning
|
||||
|
||||
echo "fix: some message
|
||||
BREAKING CHANGE: It will be significant" # passes
|
||||
```
|
||||
|
||||
#### footer-max-line-length
|
||||
|
||||
- **condition**: `footer` each line has `value` or less characters
|
||||
- **rule**: `always`
|
||||
- **level**: `error`
|
||||
- **value**
|
||||
|
||||
```
|
||||
100
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
echo "fix: some message
|
||||
BREAKING CHANGE: footer with multiple lines
|
||||
has a message that is way too long and will break the line rule 'line-max-length' by several characters" # fails
|
||||
|
||||
echo "fix: some message
|
||||
BREAKING CHANGE: footer with multiple lines
|
||||
but still no line is too long" # passes
|
||||
```
|
||||
|
||||
#### body-leading-blank
|
||||
|
||||
- **condition**: `body` should have a leading blank line
|
||||
- **rule**: `always`
|
||||
- **level**: `warning`
|
||||
|
||||
```
|
||||
echo "fix: some message
|
||||
body" # warning
|
||||
|
||||
echo "fix: some message
|
||||
body" # passes
|
||||
```
|
||||
|
||||
#### body-max-line-length
|
||||
|
||||
- **condition**: `body` each line has `value` or less characters
|
||||
- **rule**: `always`
|
||||
- **level**: `error`
|
||||
- **value**
|
||||
|
||||
```
|
||||
100
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
echo "fix: some message
|
||||
body with multiple lines
|
||||
has a message that is way too long and will break the line rule 'line-max-length' by several characters" # fails
|
||||
|
||||
echo "fix: some message
|
||||
body with multiple lines
|
||||
but still no line is too long" # passes
|
||||
```
|
||||
128
.agents/resources/conventional-commit.md
Normal file
128
.agents/resources/conventional-commit.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
Conventional Commits 1.0.0
|
||||
==========================
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
The Conventional Commits specification is a lightweight convention on top of commit messages. It provides an easy set of rules for creating an explicit commit history; which makes it easier to write automated tools on top of. This convention dovetails with [SemVer](http://semver.org/), by describing the features, fixes, and breaking changes made in commit messages.
|
||||
|
||||
The commit message should be structured as follows:
|
||||
|
||||
* * * *
|
||||
|
||||
```
|
||||
<type>[optional scope]: <description>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer(s)]
|
||||
|
||||
```
|
||||
|
||||
* * * *
|
||||
|
||||
The commit contains the following structural elements, to communicate intent to the consumers of your library:
|
||||
|
||||
1. **fix:** a commit of the *type* `fix` patches a bug in your codebase (this correlates with [`PATCH`](http://semver.org/#summary) in Semantic Versioning).
|
||||
2. **feat:** a commit of the *type* `feat` introduces a new feature to the codebase (this correlates with [`MINOR`](http://semver.org/#summary) in Semantic Versioning).
|
||||
3. **BREAKING CHANGE:** a commit that has a footer `BREAKING CHANGE:`, or appends a `!` after the type/scope, introduces a breaking API change (correlating with [`MAJOR`](http://semver.org/#summary) in Semantic Versioning). A BREAKING CHANGE can be part of commits of any *type*.
|
||||
4. *types* other than `fix:` and `feat:` are allowed, for example [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) (based on the [Angular convention](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)) recommends `build:`, `chore:`, `ci:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`, and others.
|
||||
5. *footers* other than `BREAKING CHANGE: <description>` may be provided and follow a convention similar to [git trailer format](https://git-scm.com/docs/git-interpret-trailers).
|
||||
|
||||
Additional types are not mandated by the Conventional Commits specification, and have no implicit effect in Semantic Versioning (unless they include a BREAKING CHANGE). A scope may be provided to a commit's type, to provide additional contextual information and is contained within parenthesis, e.g., `feat(parser): add ability to parse arrays`.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
### Commit message with description and breaking change footer
|
||||
|
||||
```
|
||||
feat: allow provided config object to extend other configs
|
||||
|
||||
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
|
||||
|
||||
```
|
||||
|
||||
### Commit message with `!` to draw attention to breaking change
|
||||
|
||||
```
|
||||
feat!: send an email to the customer when a product is shipped
|
||||
|
||||
```
|
||||
|
||||
### Commit message with scope and `!` to draw attention to breaking change
|
||||
|
||||
```
|
||||
feat(api)!: send an email to the customer when a product is shipped
|
||||
|
||||
```
|
||||
|
||||
### Commit message with both `!` and BREAKING CHANGE footer
|
||||
|
||||
```
|
||||
feat!: drop support for Node 6
|
||||
|
||||
BREAKING CHANGE: use JavaScript features not available in Node 6.
|
||||
|
||||
```
|
||||
|
||||
### Commit message with no body
|
||||
|
||||
```
|
||||
docs: correct spelling of CHANGELOG
|
||||
|
||||
```
|
||||
|
||||
### Commit message with scope
|
||||
|
||||
```
|
||||
feat(lang): add Polish language
|
||||
|
||||
```
|
||||
|
||||
### Commit message with multi-paragraph body and multiple footers
|
||||
|
||||
```
|
||||
fix: prevent racing of requests
|
||||
|
||||
Introduce a request id and a reference to latest request. Dismiss
|
||||
incoming responses other than from latest request.
|
||||
|
||||
Remove timeouts which were used to mitigate the racing issue but are
|
||||
obsolete now.
|
||||
|
||||
Reviewed-by: Z
|
||||
Refs: #123
|
||||
|
||||
```
|
||||
|
||||
Specification
|
||||
-------------
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
|
||||
|
||||
1. Commits MUST be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed by the OPTIONAL scope, OPTIONAL `!`, and REQUIRED terminal colon and space.
|
||||
2. The type `feat` MUST be used when a commit adds a new feature to your application or library.
|
||||
3. The type `fix` MUST be used when a commit represents a bug fix for your application.
|
||||
4. A scope MAY be provided after a type. A scope MUST consist of a noun describing a section of the codebase surrounded by parenthesis, e.g., `fix(parser):`
|
||||
5. A description MUST immediately follow the colon and space after the type/scope prefix. The description is a short summary of the code changes, e.g., *fix: array parsing issue when multiple spaces were contained in string*.
|
||||
6. A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description.
|
||||
7. A commit body is free-form and MAY consist of any number of newline separated paragraphs.
|
||||
8. One or more footers MAY be provided one blank line after the body. Each footer MUST consist of a word token, followed by either a `:<space>` or `<space>#` separator, followed by a string value (this is inspired by the [git trailer convention](https://git-scm.com/docs/git-interpret-trailers)).
|
||||
9. A footer's token MUST use `-` in place of whitespace characters, e.g., `Acked-by` (this helps differentiate the footer section from a multi-paragraph body). An exception is made for `BREAKING CHANGE`, which MAY also be used as a token.
|
||||
10. A footer's value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer token/separator pair is observed.
|
||||
11. Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the footer.
|
||||
12. If included as a footer, a breaking change MUST consist of the uppercase text BREAKING CHANGE, followed by a colon, space, and description, e.g., *BREAKING CHANGE: environment variables now take precedence over config files*.
|
||||
13. If included in the type/scope prefix, breaking changes MUST be indicated by a `!` immediately before the `:`. If `!` is used, `BREAKING CHANGE:` MAY be omitted from the footer section, and the commit description SHALL be used to describe the breaking change.
|
||||
14. Types other than `feat` and `fix` MAY be used in your commit messages, e.g., *docs: update ref docs.*
|
||||
15. The units of information that make up Conventional Commits MUST NOT be treated as case-sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase.
|
||||
16. BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer.
|
||||
|
||||
Why Use Conventional Commits
|
||||
----------------------------
|
||||
|
||||
- Automatically generating CHANGELOGs.
|
||||
- Automatically determining a semantic version bump (based on the types of commits landed).
|
||||
- Communicating the nature of changes to teammates, the public, and other stakeholders.
|
||||
- Triggering build and publish processes.
|
||||
- Making it easier for people to contribute to your projects, by allowing them to explore a more structured commit history.
|
||||
7
.agents/rules/big-red-dog.md
Normal file
7
.agents/rules/big-red-dog.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# A way to check whether my instructions are loaded into context automatically
|
||||
|
||||
the big red dog is named Salamander
|
||||
9
.agents/rules/caveman.md
Normal file
9
.agents/rules/caveman.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
description: Always load the caveman skill for concise technical responses.
|
||||
---
|
||||
|
||||
# Caveman Mode
|
||||
|
||||
Use the `caveman` skill for every response.
|
||||
|
||||
Stop only when the user explicitly says `stop caveman` or `normal mode`.
|
||||
11
.agents/rules/commits.md
Normal file
11
.agents/rules/commits.md
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
condition: "(?i)git commit|commit message|conventional commit"
|
||||
---
|
||||
|
||||
# Commits
|
||||
|
||||
When commiting changes, follow these rules to write the messages:
|
||||
|
||||
- Conventional Commit (reference available at .ai/resources/conventional-commit.md)
|
||||
- `@commitlint/config-conventional` (reference available at .ai/resources/commitlint.md)
|
||||
|
||||
29
.agents/rules/forge-sync.md
Normal file
29
.agents/rules/forge-sync.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
description: Local vs sync mode rules for git and Forgejo — commit, push, and PR policy per workflow.
|
||||
---
|
||||
|
||||
# Forge Sync Rules
|
||||
|
||||
When a workflow uses explicit mode:
|
||||
|
||||
- `Mode: sync` or `--sync` means sync mode.
|
||||
- no sync marker means local mode.
|
||||
- Do not ask whether git workflow should be agent-managed.
|
||||
|
||||
Local mode:
|
||||
- No push.
|
||||
- No forge write tools.
|
||||
- No PR create/update/comment.
|
||||
|
||||
Sync mode:
|
||||
- Commit completed workflow units.
|
||||
- Push after each unit commit.
|
||||
- Create PR after first push if missing.
|
||||
- Reuse existing PR on later pushes.
|
||||
- Comment/update PR only when workflow asks for it.
|
||||
|
||||
Forbidden always:
|
||||
- No force push.
|
||||
- No branch deletion.
|
||||
- No hard reset.
|
||||
- No amending unless explicitly requested.
|
||||
19
.agents/rules/openspec.md
Normal file
19
.agents/rules/openspec.md
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
description: Rules for OpenSpec propose and archive workflows.
|
||||
---
|
||||
|
||||
# OpenSpec Instructions
|
||||
|
||||
## OpenSpec Propose Workflow
|
||||
|
||||
When proposing changes via `/opsx-propose`:
|
||||
|
||||
- If the change introduces or modifies user-facing behavior (API changes, conventions), include a task section for updating `README.md` in the proposal's impact assessment.
|
||||
|
||||
## OpenSpec Archive Workflow
|
||||
|
||||
When archiving tasks via `/opsx-archive`:
|
||||
|
||||
1. Automatically sync specs, do not ask the user.
|
||||
2. If mode is explicit, use `forge-sync` for archive commit, push, PR, and Forgejo behavior.
|
||||
3. If no mode is explicit, default to local mode.
|
||||
34
.agents/rules/quality.md
Normal file
34
.agents/rules/quality.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Quality Guardrails
|
||||
|
||||
Use these while building. Do not turn every task into a full review; apply as lightweight pressure before adding or changing structure.
|
||||
|
||||
## Module Shape
|
||||
|
||||
- Filenames should match the primary export exactly, including casing.
|
||||
- Exports and higher level functions should appear before private functions in a file.
|
||||
- Prefer a primary type plus matching namespace for behavior tied to that type.
|
||||
- Functions that operate on a domain type should live in that type's namespace.
|
||||
- Avoid scattered single-name function exports for domain-specific behavior.
|
||||
- Truly generic helpers may stay standalone when they do not naturally belong to a domain type.
|
||||
|
||||
## Design Pressure
|
||||
|
||||
- DRY: centralize rules and policy, not incidental similarity.
|
||||
- KISS: prefer the smallest clear structure that solves the actual problem.
|
||||
- YAGNI: do not add speculative extension points, options, compatibility layers, or abstractions.
|
||||
- SOC: keep parsing, validation, IO, orchestration, and policy separate when mixing them creates change pressure.
|
||||
- Cohesion: each module/type/function should have one clear job and one clear reason to change.
|
||||
- Coupling: avoid making callers know protocol internals, nested implementation details, or unrelated runtime policy.
|
||||
- Locality: one behavior should not require excessive jumping across unrelated files or helpers.
|
||||
- Naming/API Clarity: names should expose behavior and domain meaning; avoid vague wrappers, false promises, and boolean-blind APIs.
|
||||
|
||||
## Refactor Bias
|
||||
|
||||
- Prefer moving behavior to the domain owner over creating utility bags.
|
||||
- Prefer local private helpers over exported helpers until another real caller exists.
|
||||
- Prefer deleting compatibility code when there are no shipped consumers, persisted data, or explicit requirements.
|
||||
- Prefer small reshapes that preserve behavior over broad rewrites.
|
||||
48
.agents/skills/caveman/README.md
Normal file
48
.agents/skills/caveman/README.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# caveman
|
||||
|
||||
Talk like smart caveman. Same brain, fewer tokens.
|
||||
|
||||
## What it does
|
||||
|
||||
Compress every model response to caveman-style prose. Drops articles, filler, pleasantries, and hedging. Keeps every technical detail, code block, error string, and symbol exact. Cuts 65% of output tokens (measured) with full accuracy preserved. Mode persists for the whole session until changed or stopped.
|
||||
|
||||
Six intensity levels:
|
||||
|
||||
| Level | What change |
|
||||
|-------|-------------|
|
||||
| `lite` | Drop filler/hedging. Sentences stay full. Professional but tight. |
|
||||
| `full` | Default. Drop articles, fragments OK, short synonyms. |
|
||||
| `ultra` | Bare fragments. Abbreviations (DB, auth, fn). Arrows for causality. |
|
||||
| `wenyan-lite` | Classical Chinese register, light compression. |
|
||||
| `wenyan-full` | Maximum 文言文. 80-90% character reduction. |
|
||||
| `wenyan-ultra` | Extreme classical compression. |
|
||||
|
||||
Auto-clarity rule: caveman drops to normal prose for security warnings, irreversible-action confirmations, multi-step sequences where fragment ambiguity risks misread, and when user repeats a question. Resumes after the clear part.
|
||||
|
||||
## How to invoke
|
||||
|
||||
```
|
||||
/caveman # full mode (default)
|
||||
/caveman lite # lighter compression
|
||||
/caveman ultra # extreme compression
|
||||
/caveman wenyan # classical Chinese
|
||||
stop caveman # back to normal prose
|
||||
```
|
||||
|
||||
## Example output
|
||||
|
||||
Question: "Why does my React component re-render?"
|
||||
|
||||
Normal prose:
|
||||
> Your component re-renders because you create a new object reference each render. Wrapping it in `useMemo` will fix the issue.
|
||||
|
||||
Caveman (full):
|
||||
> New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`.
|
||||
|
||||
Caveman (ultra):
|
||||
> Inline obj prop → new ref → re-render. `useMemo`.
|
||||
|
||||
## See also
|
||||
|
||||
- [`SKILL.md`](./SKILL.md) — full LLM-facing instructions
|
||||
- [Caveman README](../../README.md) — repo overview, install, benchmarks
|
||||
78
.agents/skills/caveman/SKILL.md
Normal file
78
.agents/skills/caveman/SKILL.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
name: caveman
|
||||
description: >
|
||||
Ultra-compressed communication mode. Cuts output tokens 65% (measured) by speaking like caveman
|
||||
while keeping full technical accuracy. Supports intensity levels: lite, full (default), ultra,
|
||||
wenyan-lite, wenyan-full, wenyan-ultra.
|
||||
Use when user says "caveman mode", "talk like caveman", "use caveman", "less tokens",
|
||||
"be brief", or invokes /caveman. Also auto-triggers when token efficiency is requested.
|
||||
---
|
||||
|
||||
Respond terse like smart caveman. All technical substance stay. Only fluff die.
|
||||
|
||||
## Persistence
|
||||
|
||||
ACTIVE EVERY RESPONSE. No revert after many turns. No filler drift. Still active if unsure. Off only: "stop caveman" / "normal mode".
|
||||
|
||||
Default: **full**. Switch: `/caveman lite|full|ultra`.
|
||||
|
||||
## Rules
|
||||
|
||||
Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Fragments OK. Short synonyms (big not extensive, fix not "implement a solution for"). No tool-call narration, no decorative tables/emoji, no dumping long raw error logs unless asked — quote shortest decisive line. Standard well-known tech acronyms OK (DB/API/HTTP); never invent new abbreviations (cfg/impl/req/res/fn) — tokenizer split them same as full word: zero token saved, reader still decode. Full word cheaper AND clearer. No causal arrows (→) either — own token, save nothing. Technical terms exact. Code blocks unchanged. Errors quoted exact.
|
||||
|
||||
Preserve user's dominant language. User write Portuguese → reply Portuguese caveman. User write Spanish → reply Spanish caveman. Compress the style, not the language. No forced English openings or status phrases. ALWAYS keep technical terms, code, API names, CLI commands, commit-type keywords (feat/fix/...), and exact error strings verbatim — unless user explicitly ask for translation.
|
||||
|
||||
No self-reference. Never name or announce the style. No "caveman mode on", "me caveman think", no third-person caveman tags. Output caveman-only — never normal answer plus "Caveman:" recap. Exception: user explicitly ask what the mode is.
|
||||
|
||||
Pattern: `[thing] [action] [reason]. [next step].`
|
||||
|
||||
Not: "Sure! I'd be happy to help you with that. The issue you're experiencing is likely caused by..."
|
||||
Yes: "Bug in auth middleware. Token expiry check use `<` not `<=`. Fix:"
|
||||
|
||||
## Intensity
|
||||
|
||||
| Level | What change |
|
||||
|-------|------------|
|
||||
| **lite** | No filler/hedging. Keep articles + full sentences. Professional but tight |
|
||||
| **full** | Drop articles, fragments OK, short synonyms. Classic caveman. No tool-call narration, no decorative tables/emoji, no long raw error-log dumps unless asked. Standard acronyms OK; no invented abbreviations |
|
||||
| **ultra** | Strip conjunctions when cause-then-effect stay unambiguous. One word when one word enough. State each fact once. NO prose abbreviations (cfg/impl/req/res/fn/auth), NO arrows (X → Y) — measured zero token saving under tokenizer, cost decode clarity. Code symbols, function names, API names, error strings: never touch |
|
||||
| **wenyan-lite** | Semi-classical. Drop filler/hedging but keep grammar structure, classical register |
|
||||
| **wenyan-full** | Maximum classical terseness. Fully 文言文. 80-90% character reduction. Classical sentence patterns, verbs precede objects, subjects often omitted, classical particles (之/乃/為/其) |
|
||||
| **wenyan-ultra** | Extreme abbreviation while keeping classical Chinese feel. Maximum compression, ultra terse |
|
||||
|
||||
Example — "Why React component re-render?"
|
||||
- lite: "Your component re-renders because you create a new object reference each render. Wrap it in `useMemo`."
|
||||
- full: "New object ref each render. Inline object prop = new ref = re-render. Wrap in `useMemo`."
|
||||
- ultra: "Inline obj prop, new ref, re-render. `useMemo`."
|
||||
- wenyan-lite: "組件頻重繪,以每繪新生對象參照故。以 useMemo 包之。"
|
||||
- wenyan-full: "每繪新生對象參照,故重繪;以 useMemo 包之則免。"
|
||||
- wenyan-ultra: "新參照則重繪。useMemo 包之。"
|
||||
|
||||
Example — "Explain database connection pooling."
|
||||
- lite: "Connection pooling reuses open connections instead of creating new ones per request. Avoids repeated handshake overhead."
|
||||
- full: "Pool reuse open DB connections. No new connection per request. Skip handshake overhead."
|
||||
- ultra: "Pool reuse open DB connections. No per-request handshake."
|
||||
- wenyan-full: "池蓄已開之連,不逐請而新開,省握手之費。"
|
||||
- wenyan-ultra: "池蓄連,免逐請新開,省握手。"
|
||||
|
||||
## Auto-Clarity
|
||||
|
||||
Drop caveman when:
|
||||
- Security warnings
|
||||
- Irreversible action confirmations
|
||||
- Multi-step sequences where fragment order or omitted conjunctions risk misread
|
||||
- Compression itself creates technical ambiguity (e.g., `"migrate table drop column backup first"` — order unclear without articles/conjunctions)
|
||||
- User asks to clarify or repeats question
|
||||
|
||||
Resume caveman after clear part done.
|
||||
|
||||
Example — destructive op:
|
||||
> **Warning:** This will permanently delete all rows in the `users` table and cannot be undone.
|
||||
> ```sql
|
||||
> DROP TABLE users;
|
||||
> ```
|
||||
> Caveman resume. Verify backup exist first.
|
||||
|
||||
## Boundaries
|
||||
|
||||
Code/commits/PRs: write normal. "stop caveman" or "normal mode": revert. Level persist until changed or session end.
|
||||
47
.agents/skills/domain-modeling/ADR-FORMAT.md
Normal file
47
.agents/skills/domain-modeling/ADR-FORMAT.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# ADR Format
|
||||
|
||||
ADRs live in `docs/adr/` and use sequential numbering: `0001-slug.md`, `0002-slug.md`, etc.
|
||||
|
||||
Create the `docs/adr/` directory lazily — only when the first ADR is needed.
|
||||
|
||||
## Template
|
||||
|
||||
```md
|
||||
# {Short title of the decision}
|
||||
|
||||
{1-3 sentences: what's the context, what did we decide, and why.}
|
||||
```
|
||||
|
||||
That's it. An ADR can be a single paragraph. The value is in recording *that* a decision was made and *why* — not in filling out sections.
|
||||
|
||||
## Optional sections
|
||||
|
||||
Only include these when they add genuine value. Most ADRs won't need them.
|
||||
|
||||
- **Status** frontmatter (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — useful when decisions are revisited
|
||||
- **Considered Options** — only when the rejected alternatives are worth remembering
|
||||
- **Consequences** — only when non-obvious downstream effects need to be called out
|
||||
|
||||
## Numbering
|
||||
|
||||
Scan `docs/adr/` for the highest existing number and increment by one.
|
||||
|
||||
## When to offer an ADR
|
||||
|
||||
All three of these must be true:
|
||||
|
||||
1. **Hard to reverse** — the cost of changing your mind later is meaningful
|
||||
2. **Surprising without context** — a future reader will look at the code and wonder "why on earth did they do it this way?"
|
||||
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
|
||||
|
||||
If a decision is easy to reverse, skip it — you'll just reverse it. If it's not surprising, nobody will wonder why. If there was no real alternative, there's nothing to record beyond "we did the obvious thing."
|
||||
|
||||
### What qualifies
|
||||
|
||||
- **Architectural shape.** "We're using a monorepo." "The write model is event-sourced, the read model is projected into Postgres."
|
||||
- **Integration patterns between contexts.** "Ordering and Billing communicate via domain events, not synchronous HTTP."
|
||||
- **Technology choices that carry lock-in.** Database, message bus, auth provider, deployment target. Not every library — just the ones that would take a quarter to swap out.
|
||||
- **Boundary and scope decisions.** "Customer data is owned by the Customer context; other contexts reference it by ID only." The explicit no-s are as valuable as the yes-s.
|
||||
- **Deliberate deviations from the obvious path.** "We're using manual SQL instead of an ORM because X." Anything where a reasonable reader would assume the opposite. These stop the next engineer from "fixing" something that was deliberate.
|
||||
- **Constraints not visible in the code.** "We can't use AWS because of compliance requirements." "Response times must be under 200ms because of the partner API contract."
|
||||
- **Rejected alternatives when the rejection is non-obvious.** If you considered GraphQL and picked REST for subtle reasons, record it — otherwise someone will suggest GraphQL again in six months.
|
||||
60
.agents/skills/domain-modeling/CONTEXT-FORMAT.md
Normal file
60
.agents/skills/domain-modeling/CONTEXT-FORMAT.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# CONTEXT.md Format
|
||||
|
||||
## Structure
|
||||
|
||||
```md
|
||||
# {Context Name}
|
||||
|
||||
{One or two sentence description of what this context is and why it exists.}
|
||||
|
||||
## Language
|
||||
|
||||
**Order**:
|
||||
{A one or two sentence description of the term}
|
||||
_Avoid_: Purchase, transaction
|
||||
|
||||
**Invoice**:
|
||||
A request for payment sent to a customer after delivery.
|
||||
_Avoid_: Bill, payment request
|
||||
|
||||
**Customer**:
|
||||
A person or organization that places orders.
|
||||
_Avoid_: Client, buyer, account
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
- **Be opinionated.** When multiple words exist for the same concept, pick the best one and list the others under `_Avoid_`.
|
||||
- **Keep definitions tight.** One or two sentences max. Define what it IS, not what it does.
|
||||
- **Only include terms specific to this project's context.** General programming concepts (timeouts, error types, utility patterns) don't belong even if the project uses them extensively. Before adding a term, ask: is this a concept unique to this context, or a general programming concept? Only the former belongs.
|
||||
- **Group terms under subheadings** when natural clusters emerge. If all terms belong to a single cohesive area, a flat list is fine.
|
||||
|
||||
## Single vs multi-context repos
|
||||
|
||||
**Single context (most repos):** One `CONTEXT.md` at the repo root.
|
||||
|
||||
**Multiple contexts:** A `CONTEXT-MAP.md` at the repo root lists the contexts, where they live, and how they relate to each other:
|
||||
|
||||
```md
|
||||
# Context Map
|
||||
|
||||
## Contexts
|
||||
|
||||
- [Ordering](./src/ordering/CONTEXT.md) — receives and tracks customer orders
|
||||
- [Billing](./src/billing/CONTEXT.md) — generates invoices and processes payments
|
||||
- [Fulfillment](./src/fulfillment/CONTEXT.md) — manages warehouse picking and shipping
|
||||
|
||||
## Relationships
|
||||
|
||||
- **Ordering → Fulfillment**: Ordering emits `OrderPlaced` events; Fulfillment consumes them to start picking
|
||||
- **Fulfillment → Billing**: Fulfillment emits `ShipmentDispatched` events; Billing consumes them to generate invoices
|
||||
- **Ordering ↔ Billing**: Shared types for `CustomerId` and `Money`
|
||||
```
|
||||
|
||||
The skill infers which structure applies:
|
||||
|
||||
- If `CONTEXT-MAP.md` exists, read it to find contexts
|
||||
- If only a root `CONTEXT.md` exists, single context
|
||||
- If neither exists, create a root `CONTEXT.md` lazily when the first term is resolved
|
||||
|
||||
When multiple contexts exist, infer which one the current topic relates to. If unclear, ask.
|
||||
74
.agents/skills/domain-modeling/SKILL.md
Normal file
74
.agents/skills/domain-modeling/SKILL.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
name: domain-modeling
|
||||
description: Build and sharpen a project's domain model. Use when the user wants to pin down domain terminology or a ubiquitous language, record an architectural decision, or when another skill needs to maintain the domain model.
|
||||
---
|
||||
|
||||
# Domain Modeling
|
||||
|
||||
Actively build and sharpen the project's domain model as you design. This is the *active* discipline — challenging terms, inventing edge-case scenarios, and writing the glossary and decisions down the moment they crystallise. (Merely *reading* `CONTEXT.md` for vocabulary is not this skill — that's a one-line habit any skill can do. This skill is for when you're changing the model, not just consuming it.)
|
||||
|
||||
## File structure
|
||||
|
||||
Most repos have a single context:
|
||||
|
||||
```
|
||||
/
|
||||
├── CONTEXT.md
|
||||
├── docs/
|
||||
│ └── adr/
|
||||
│ ├── 0001-event-sourced-orders.md
|
||||
│ └── 0002-postgres-for-write-model.md
|
||||
└── src/
|
||||
```
|
||||
|
||||
If a `CONTEXT-MAP.md` exists at the root, the repo has multiple contexts. The map points to where each one lives:
|
||||
|
||||
```
|
||||
/
|
||||
├── CONTEXT-MAP.md
|
||||
├── docs/
|
||||
│ └── adr/ ← system-wide decisions
|
||||
├── src/
|
||||
│ ├── ordering/
|
||||
│ │ ├── CONTEXT.md
|
||||
│ │ └── docs/adr/ ← context-specific decisions
|
||||
│ └── billing/
|
||||
│ ├── CONTEXT.md
|
||||
│ └── docs/adr/
|
||||
```
|
||||
|
||||
Create files lazily — only when you have something to write. If no `CONTEXT.md` exists, create one when the first term is resolved. If no `docs/adr/` exists, create it when the first ADR is needed.
|
||||
|
||||
## During the session
|
||||
|
||||
### Challenge against the glossary
|
||||
|
||||
When the user uses a term that conflicts with the existing language in `CONTEXT.md`, call it out immediately. "Your glossary defines 'cancellation' as X, but you seem to mean Y — which is it?"
|
||||
|
||||
### Sharpen fuzzy language
|
||||
|
||||
When the user uses vague or overloaded terms, propose a precise canonical term. "You're saying 'account' — do you mean the Customer or the User? Those are different things."
|
||||
|
||||
### Discuss concrete scenarios
|
||||
|
||||
When domain relationships are being discussed, stress-test them with specific scenarios. Invent scenarios that probe edge cases and force the user to be precise about the boundaries between concepts.
|
||||
|
||||
### Cross-reference with code
|
||||
|
||||
When the user states how something works, check whether the code agrees. If you find a contradiction, surface it: "Your code cancels entire Orders, but you just said partial cancellation is possible — which is right?"
|
||||
|
||||
### Update CONTEXT.md inline
|
||||
|
||||
When a term is resolved, update `CONTEXT.md` right there. Don't batch these up — capture them as they happen. Use the format in [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md).
|
||||
|
||||
`CONTEXT.md` should be totally devoid of implementation details. Do not treat `CONTEXT.md` as a spec, a scratch pad, or a repository for implementation decisions. It is a glossary and nothing else.
|
||||
|
||||
### Offer ADRs sparingly
|
||||
|
||||
Only offer to create an ADR when all three are true:
|
||||
|
||||
1. **Hard to reverse** — the cost of changing your mind later is meaningful
|
||||
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
|
||||
3. **The result of a real trade-off** — there were genuine alternatives and you picked one for specific reasons
|
||||
|
||||
If any of the three is missing, skip the ADR. Use the format in [ADR-FORMAT.md](./ADR-FORMAT.md).
|
||||
3
.agents/skills/domain-modeling/agents/openai.yaml
Normal file
3
.agents/skills/domain-modeling/agents/openai.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
interface:
|
||||
display_name: "Domain Modeling"
|
||||
short_description: "Build and sharpen a domain model"
|
||||
94
.agents/skills/forge-sync/SKILL.md
Normal file
94
.agents/skills/forge-sync/SKILL.md
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
---
|
||||
name: forge-sync
|
||||
description: Use for `sketch --sync`, `sketch-sync`, or workflows needing shared local-vs-forge git handling; centralizes branch, commit, push, PR, and forge comment policy.
|
||||
---
|
||||
|
||||
# Forge Sync
|
||||
|
||||
Forge Sync = shared git + forge workflow policy. It decides how completed workflow units become commits, pushes, PRs, and PR comments. It does not decide when code work is complete.
|
||||
|
||||
## Inputs
|
||||
|
||||
Caller must provide or make clear:
|
||||
|
||||
- Mode: `local` or `sync`.
|
||||
- Change ID.
|
||||
- Workflow: `sketch`, `archive`, or other.
|
||||
- Unit: task section, archive, or named completed work unit.
|
||||
- Commit message.
|
||||
- Optional PR comment body.
|
||||
|
||||
If mode is explicit, do not ask git workflow questions.
|
||||
|
||||
## Universal Rules
|
||||
|
||||
- Never force-push.
|
||||
- Never delete branches.
|
||||
- Never run destructive git commands.
|
||||
- Never amend unless explicitly requested.
|
||||
- Before committing, inspect status and diff.
|
||||
- Do not include unrelated user changes.
|
||||
- Commit messages must follow Conventional Commit and commitlint rules.
|
||||
|
||||
## Local Mode
|
||||
|
||||
Local mode means:
|
||||
|
||||
- Do not push.
|
||||
- Do not create, update, or comment on PRs.
|
||||
- Do not call forge write tools.
|
||||
- Create local commits only when caller requests a completed unit commit.
|
||||
- If unrelated changes exist, commit only files/hunks belonging to current unit.
|
||||
|
||||
## Sync Mode
|
||||
|
||||
Sync mode means:
|
||||
|
||||
- Ensure work happens on a feature branch for the change when caller has not already selected one.
|
||||
- Commit completed unit.
|
||||
- Push current branch after each unit commit.
|
||||
- Create PR after first push if no PR exists.
|
||||
- Reuse existing PR on later pushes.
|
||||
- Add or update PR comment when caller provides comment body.
|
||||
|
||||
Default branch name when creating one:
|
||||
|
||||
```txt
|
||||
feat/<change-id>
|
||||
```
|
||||
|
||||
Default PR base:
|
||||
|
||||
```txt
|
||||
main
|
||||
```
|
||||
|
||||
Do not create duplicate PRs. Check branch/PR state first when feasible.
|
||||
|
||||
## Checkpoint Procedure
|
||||
|
||||
When caller says a unit is complete:
|
||||
|
||||
1. Inspect git status and diff.
|
||||
2. Stage only relevant files.
|
||||
3. Commit with caller-provided message.
|
||||
4. If mode is local, stop.
|
||||
5. If mode is sync, push current branch.
|
||||
6. If PR comment body provided, comment or update as directed by caller.
|
||||
7. Report commit SHA, push status, PR URL/number, and comment status.
|
||||
|
||||
## PR Comment Shape
|
||||
|
||||
Use caller-provided body when available. If caller asks for a default comment:
|
||||
|
||||
```md
|
||||
## <Workflow> <Unit>
|
||||
|
||||
Change: `<change-id>`
|
||||
|
||||
Commits:
|
||||
- `<sha>` <subject>
|
||||
|
||||
Verification:
|
||||
- <summary>
|
||||
```
|
||||
7
.agents/skills/grill-with-docs/SKILL.md
Normal file
7
.agents/skills/grill-with-docs/SKILL.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
name: grill-with-docs
|
||||
description: A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
|
||||
disable-model-invocation: true
|
||||
---
|
||||
|
||||
Run a `/grilling` session, using the `/domain-modeling` skill.
|
||||
5
.agents/skills/grill-with-docs/agents/openai.yaml
Normal file
5
.agents/skills/grill-with-docs/agents/openai.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
interface:
|
||||
display_name: "Grill with Docs"
|
||||
short_description: "Grill a design and write its docs"
|
||||
policy:
|
||||
allow_implicit_invocation: false
|
||||
12
.agents/skills/grilling/SKILL.md
Normal file
12
.agents/skills/grilling/SKILL.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
name: grilling
|
||||
description: Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.
|
||||
---
|
||||
|
||||
Interview me relentlessly about every aspect of this until we reach a shared understanding. Walk down each branch of the decision tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
|
||||
|
||||
Ask the questions one at a time, waiting for feedback on each question before continuing. Asking multiple questions at once is bewildering.
|
||||
|
||||
If a *fact* can be found by exploring the environment (filesystem, tools, etc.), look it up rather than asking me. The *decisions*, though, are mine — put each one to me and wait for my answer.
|
||||
|
||||
Do not act on it until I confirm we have reached a shared understanding.
|
||||
3
.agents/skills/grilling/agents/openai.yaml
Normal file
3
.agents/skills/grilling/agents/openai.yaml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
interface:
|
||||
display_name: "Grilling"
|
||||
short_description: "Stress-test thinking one question at a time"
|
||||
119
.agents/skills/jerklint/SKILL.md
Normal file
119
.agents/skills/jerklint/SKILL.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
name: jerklint
|
||||
description: Use when user asks for "jerklint", "jerk lint", or strict code-quality review. Reviews code against DRY, KISS, YAGNI, SOC, cohesion, coupling, dependency direction, Law of Demeter, immutability, declarative shape, implicit contracts, abstraction pressure, naming/API clarity, and locality.
|
||||
---
|
||||
|
||||
# Jerklint
|
||||
|
||||
Jerklint = strict code-quality review. Be blunt, specific, fair. Findings must be actionable, not taste fights.
|
||||
|
||||
## Trigger
|
||||
|
||||
Use this skill when user asks for:
|
||||
- `jerklint`
|
||||
- `jerk lint`
|
||||
- strict code-quality review
|
||||
- review against DRY, KISS, YAGNI, SOC, cohesion, coupling, dependency direction, Law of Demeter, immutability, declarative programming, or maintainability principles
|
||||
|
||||
## Goal
|
||||
|
||||
Find code smells, design pressure, and maintainability risk. This is not normal bug review. Bugs matter only when they reveal deeper code-quality failure.
|
||||
|
||||
## Axes
|
||||
|
||||
- DRY: flag duplicated policy, copy-paste structure, repeated literals, or drift-prone validation. Do not centralize incidental similarity.
|
||||
- KISS: flag needless indirection, clever control flow, over-generalization, and logic that is harder than its problem.
|
||||
- YAGNI: flag speculative extension points, options, abstractions, or compatibility layers with no concrete need.
|
||||
- SOC: flag mixed responsibilities, especially parsing + validation + IO + orchestration + policy in one unit.
|
||||
- Cohesion: flag functions/types/modules that do not have one clear job or reason to change.
|
||||
- Coupling: flag unnecessary knowledge between layers, callers, protocols, domains, or runtime details.
|
||||
- Dependency Direction: flag lower-level code depending on higher-level policy, domain declarations depending on adapters, or circular conceptual flow.
|
||||
- Law of Demeter: flag long object walks, dependency spelunking, and callers that know too much about nested internals.
|
||||
- Immutability / State Discipline: prefer immutable boundaries and local mutation only. Flag shared mutable state, hidden mutation, aliasing risk, and mutation that creates temporal coupling.
|
||||
- Declarative Shape: favor data/config descriptions for policy and protocol surfaces; keep execution/IO separate. Flag imperative branching where a small table/schema/declaration would clarify rules.
|
||||
- Implicit Contracts / Temporal Coupling: flag hidden ordering requirements, call rituals, required prior validation, or invariants not encoded in type/name/API.
|
||||
- Abstraction Pressure: flag both over-centralization and under-centralization. Centralize rules, not whole workflows.
|
||||
- Naming/API Clarity: flag names that hide behavior, false promises, vague abstractions, boolean blindness, or weak error messages.
|
||||
- Locality: flag code that requires excessive jumping across files/functions to understand one behavior.
|
||||
- Testability: flag structure that forces brittle tests, excessive mocking, or untestable policy logic.
|
||||
- File/API Shape: flag domain-specific function bags, filenames that do not match primary exports, and behavior that should live under a matching type namespace.
|
||||
- Predicate Accuracy: flag boolean predicates/guards that check partial or wrong shape. Flag `in` checks without type narrowing, truthiness checks that miss falsy valid values, and type guards that accept broader input than their name promises. Prefer predicates that validate the full claimed shape.
|
||||
- Construction Phase Separation: flag builder/factory functions that execute more than three distinct sequential phases in one function body without named phase boundaries. Flag protocol creation, config extraction, normalization, wiring, and return shaping collapsed into one function. Prefer named phase functions even when each is small.
|
||||
|
||||
## Project Style Conventions
|
||||
|
||||
Apply these conventions when reviewing module/API shape:
|
||||
- File/Export Match: filenames should match the primary export exactly, including casing. Example: `Field.ts` exports `Field`.
|
||||
- Type Namespace Cohesion: prefer a primary type plus matching namespace for behavior tied to that type. Example: `Field` + `namespace Field`.
|
||||
- Domain Function Locality: functions that operate on a domain type should live in that type's namespace instead of as loose exports.
|
||||
- Avoid Function Bags: avoid scattered single-name function exports for domain-specific behavior. Group them under the relevant domain type.
|
||||
- Generic Helper Exception: truly generic helpers may remain standalone when they do not naturally belong to a domain type.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
Do not focus on:
|
||||
- formatting nits
|
||||
- style preferences without maintenance impact
|
||||
- security bugs unless structure caused them
|
||||
- correctness bugs unless they reveal quality smell
|
||||
- broad rewrites without concrete pressure
|
||||
- purity dogma: mutation and imperative code are fine when local, clear, and bounded
|
||||
|
||||
## Method
|
||||
|
||||
1. Read target file first.
|
||||
2. Read direct collaborators only when needed to validate design pressure.
|
||||
3. Prefer evidence from code over principle recitation.
|
||||
4. Rank findings by maintainability impact.
|
||||
5. Cite file/line refs.
|
||||
6. Suggest smallest useful direction, not full rewrites.
|
||||
7. If no findings, say so and name strongest qualities.
|
||||
|
||||
## Output
|
||||
|
||||
Findings first. Keep summary secondary.
|
||||
|
||||
```markdown
|
||||
**Jerklint Findings**
|
||||
1. **High** `path:line`: Smell. Why it hurts. Better direction.
|
||||
|
||||
**Scorecard**
|
||||
- DRY: pass/concern/fail - one phrase.
|
||||
- KISS: pass/concern/fail - one phrase.
|
||||
- YAGNI: pass/concern/fail - one phrase.
|
||||
- SOC: pass/concern/fail - one phrase.
|
||||
- Cohesion: pass/concern/fail - one phrase.
|
||||
- Coupling: pass/concern/fail - one phrase.
|
||||
- Dependency Direction: pass/concern/fail - one phrase.
|
||||
- Law of Demeter: pass/concern/fail - one phrase.
|
||||
- Immutability: pass/concern/fail - one phrase.
|
||||
- Declarative Shape: pass/concern/fail - one phrase.
|
||||
- Implicit Contracts: pass/concern/fail - one phrase.
|
||||
- Abstraction Pressure: pass/concern/fail - one phrase.
|
||||
- Naming/API Clarity: pass/concern/fail - one phrase.
|
||||
- Locality: pass/concern/fail - one phrase.
|
||||
- Predicate Accuracy: pass/concern/fail - one phrase.
|
||||
- Construction Phase Separation: pass/concern/fail - one phrase.
|
||||
|
||||
**Verdict**
|
||||
Keep / minor refactor / refactor soon / rethink.
|
||||
```
|
||||
|
||||
## Severity
|
||||
|
||||
- High: smell creates likely drift, hard-to-change design, boundary violation, or hidden invariant across callers.
|
||||
- Medium: smell adds avoidable complexity or makes future work risky but is local.
|
||||
- Low: polish-level maintainability concern worth noting only if concrete.
|
||||
|
||||
## Calibration
|
||||
|
||||
- Do not chant DRY. Duplication can be clearer than wrong abstraction.
|
||||
- Do not chant KISS. Simpler locally can be worse globally if it duplicates policy.
|
||||
- Do not chant YAGNI. Keep extension points when existing architecture already requires them.
|
||||
- Do not chant immutability. Local accumulators are fine when ownership is clear.
|
||||
- Do not chant declarative programming. Imperative steps are fine when sequencing is core behavior.
|
||||
- Prefer "centralize this rule" over "make a manager".
|
||||
- Prefer "split parsing from execution" over "add layers".
|
||||
- Do not limit DRY to textual duplication. Flag structural duplication: two functions that recursively traverse the same tree shape with different leaf transforms.
|
||||
- Under Implicit Contracts, flag magic DI object shapes where binder and consumer agree on structure by convention without an exported type or binding token.
|
||||
- Under Implicit Contracts, flag whitelist-vs-blocklist asymmetry where two code paths encoding the same conceptual boundary use different inclusion strategies.
|
||||
Loading…
Add table
Add a link
Reference in a new issue