feat: refresh shared skills catalog
This commit is contained in:
1 parent
98bb35e6fb
commit
418792d1ec
49 files changed
+2272
-2389
No files matched your search
@@ -0,0 +1,2 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
@@ -1,85 +1,111 @@
|
||||
# global-skills
|
||||
|
||||
Personal skill repository shared by every coding agent on this host
|
||||
(Antigravity/agy, Codex, OpenCode, Claude Code). Kept separate from JEV,
|
||||
which remains its own project with its own skills.
|
||||
Reusable workflows for coding agents: planning, debugging, API and database design,
|
||||
security, UI, writing, performance benchmarking, and optional spec-driven development.
|
||||
Skills help an agent complete the requested work with clear steps and appropriate verification.
|
||||
|
||||
## Sources
|
||||
This repository is the canonical source for 20 shared skills on this host.
|
||||
Installed skills link back to the source, so edits take effect without copying
|
||||
files into each agent's directory. The workflows favor direct execution: use
|
||||
existing context, preserve user work, and check only what the change needs.
|
||||
|
||||
Agents see skills from two sources:
|
||||
## Install
|
||||
|
||||
| Source | Owner | Path |
|
||||
|---|---|---|
|
||||
| This repo | here | `~/Projects/work/global-skills/skills/` |
|
||||
| JEV skills | JEV project | `~/Projects/work/JEV/.agents/skills/` |
|
||||
Requires Bash, Python 3, and a filesystem supporting symbolic links. The supplied
|
||||
installer targets Linux-style home directories and uses Python's standard library.
|
||||
|
||||
## Targets
|
||||
|
||||
`sync-skills.sh` maintains symlinks into each agent's skills directory:
|
||||
|
||||
- `~/.agents/skills` (OpenCode)
|
||||
- `~/.codex/skills` (Codex)
|
||||
- `~/.claude/skills` (Claude Code)
|
||||
|
||||
Antigravity reads both sources directly via `~/.gemini/config/skills.json`.
|
||||
|
||||
## Skill Catalog
|
||||
|
||||
All skills adhere to the 5-phase Skill Architect anatomy (`Phase 0: Setup` through `Phase 4: Output Execution & Verification`) with System One balance invariants.
|
||||
|
||||
### Planning & Review
|
||||
- [`junior-to-senior`](skills/junior-to-senior/SKILL.md) — Adversarial staff-engineer review upgrading agent plans using live codebase inspection and SOTA research.
|
||||
- [`debugging-workflow`](skills/debugging-workflow/SKILL.md) — Systematic root-cause isolation, minimal reproduction, and regression testing.
|
||||
- [`emergency-procedures`](skills/emergency-procedures/SKILL.md) — Recovery protocols for broken agent loops, git tangle, and context drift.
|
||||
|
||||
### Writing & UI Craft
|
||||
- [`fuck-slop`](skills/fuck-slop/SKILL.md) — Multi-genre de-slop pass eliminating statistical AI writing fingerprints.
|
||||
- [`interface-kit`](skills/interface-kit/SKILL.md) — Authoritative implementation guide for UI craft, spring animations, and WCAG AA accessibility.
|
||||
|
||||
### Spec-Driven Development (SDD) Suite
|
||||
- [`grill`](skills/grill/SKILL.md) — Calibrated plan interrogation before speccing.
|
||||
- [`spec`](skills/spec/SKILL.md) — Sole mutator of `SPEC.md` managing goals, invariants, tasks, and bugs.
|
||||
- [`caveman`](skills/caveman/SKILL.md) — Token-compression dialect (~75% reduction) for dense invariant specification.
|
||||
- [`review`](skills/review/SKILL.md) — Adversarial pre-implementation spec refutation and gatekeeper.
|
||||
- [`build`](skills/build/SKILL.md) — Single-threaded plan-to-execute loop with automated test oracles.
|
||||
- [`check`](skills/check/SKILL.md) — Read-only drift detector verifying code against active invariants.
|
||||
- [`backprop`](skills/backprop/SKILL.md) — Bug-to-spec feedback loop binding regression tests.
|
||||
- [`deepen`](skills/deepen/SKILL.md) — Module design pass pulling complexity down and shrinking interfaces.
|
||||
|
||||
### Architecture & Security
|
||||
- [`api-design`](skills/api-design/SKILL.md) — REST membranes, contract-first schemas, and boundary clamping.
|
||||
- [`database-design`](skills/database-design/SKILL.md) — SQLite WAL persistence, repository abstraction, and keyset pagination.
|
||||
- [`app-security`](skills/app-security/SKILL.md) — Four-Pillar upload defense, outbound SSRF guards, and secret masking.
|
||||
- [`git-workflow`](skills/git-workflow/SKILL.md) — Atomic commit grouping, selective staging, and conventional commits.
|
||||
|
||||
### Meta & Infrastructure
|
||||
- [`deliver-file`](skills/deliver-file/SKILL.md) — Push files and directories to the user's workstation over Tailscale SSH via `t3-deliver`.
|
||||
- [`skill-architect`](skills/skill-architect/SKILL.md) — Standardized authoring, auditing, and maintenance of global agent skills.
|
||||
|
||||
## Usage
|
||||
From a checkout:
|
||||
|
||||
```sh
|
||||
./sync-skills.sh # after adding/updating/removing a skill
|
||||
cd /path/to/global-skills
|
||||
./sync-skills.sh --dry-run
|
||||
./sync-skills.sh
|
||||
./sync-skills.sh --check
|
||||
```
|
||||
|
||||
Idempotent: re-links only what changed, never touches unrelated entries
|
||||
(omarchy system skills etc.), warns on name collisions between the two
|
||||
sources (this repo wins).
|
||||
The default targets are:
|
||||
|
||||
## Adding a skill
|
||||
| Target | Skill directory |
|
||||
| --- | --- |
|
||||
| OpenCode / shared agents | `~/.agents/skills` |
|
||||
| Codex | `~/.codex/skills` |
|
||||
| Claude Code | `~/.claude/skills` |
|
||||
|
||||
1. Create `skills/<skill-name>/SKILL.md` following the [sample-skill blueprint](skills/skill-architect/references/sample-skill.md).
|
||||
2. Run `./sync-skills.sh`.
|
||||
3. Commit.
|
||||
Sync also includes JEV skills when `~/Projects/work/JEV/.agents/skills` exists.
|
||||
It preserves unrelated files and symlinks, removes stale managed links, and rejects
|
||||
source-name collisions. Antigravity uses separate source-path configuration.
|
||||
|
||||
## t3-deliver
|
||||
See [installation and usage](docs/installation.md) for first-time setup, installing
|
||||
one skill, custom targets, Antigravity configuration, updates, and troubleshooting.
|
||||
|
||||
`bin/t3-deliver` is symlinked to `~/.local/bin/t3-deliver`. It prints a
|
||||
ready-to-paste `scp` command (Tailscale SSH) so the user can pull any file
|
||||
from this host to their Windows machine. The `deliver-file` skill teaches
|
||||
every agent to use it.
|
||||
## Use
|
||||
|
||||
## T3 integration
|
||||
Ask for the outcome in normal language. An agent can select a skill from its
|
||||
name and description, or you can explicitly name the workflow:
|
||||
|
||||
Open this folder as a project in T3 Code to get a top-bar Action running
|
||||
`sync-skills.sh` (Actions are project-scoped commands).
|
||||
- “Use debugging-workflow to diagnose this failing request.”
|
||||
- “Use interface-kit to improve this form using the existing components.”
|
||||
- “Use junior-to-senior to review this implementation plan.”
|
||||
- “Use benchmark-refactor to profile this module and evaluate optimizations.”
|
||||
- “Use spec to write a specification, then implement task T1 with build.”
|
||||
|
||||
The spec suite applies when you choose that workflow. Ordinary bug fixes and
|
||||
feature edits do not require a spec. Requests to review or report remain read-only.
|
||||
Discovery and activation depend on the agent; this repository installs Markdown
|
||||
instructions and links, without adding runtime hooks or model calls.
|
||||
|
||||
For projects with substantial architecture or design history, keep a concise,
|
||||
project-owned context index pointing to the key code paths and design documents.
|
||||
Load it when the task needs that history; avoid generating directory-by-directory
|
||||
documentation unless maintainers will keep it accurate.
|
||||
|
||||
## Catalog
|
||||
|
||||
| Work | Skills |
|
||||
| --- | --- |
|
||||
| Plan and review | [grill](skills/grill/SKILL.md), [junior-to-senior](skills/junior-to-senior/SKILL.md), [review](skills/review/SKILL.md) |
|
||||
| Adopted spec workflow | [spec](skills/spec/SKILL.md), [build](skills/build/SKILL.md), [check](skills/check/SKILL.md), [backprop](skills/backprop/SKILL.md), [caveman](skills/caveman/SKILL.md) |
|
||||
| Fix and simplify | [debugging-workflow](skills/debugging-workflow/SKILL.md), [deepen](skills/deepen/SKILL.md), [emergency-procedures](skills/emergency-procedures/SKILL.md) |
|
||||
| Architecture | [api-design](skills/api-design/SKILL.md), [database-design](skills/database-design/SKILL.md), [app-security](skills/app-security/SKILL.md), [benchmark-refactor](skills/benchmark-refactor/SKILL.md) |
|
||||
| UI and writing | [interface-kit](skills/interface-kit/SKILL.md), [fuck-slop](skills/fuck-slop/SKILL.md) |
|
||||
| Maintenance | [git-workflow](skills/git-workflow/SKILL.md), [deliver-file](skills/deliver-file/SKILL.md), [skill-architect](skills/skill-architect/SKILL.md) |
|
||||
|
||||
JEV supplies `context-architect`, `lint-architect`, `typesafe-ai`, `doc-architect`,
|
||||
and `system-one-balance-protocol`. Its `anti-slop-editor` is a compatibility alias
|
||||
to `fuck-slop`.
|
||||
|
||||
## Maintain
|
||||
|
||||
Content edits propagate through existing links immediately. Sync after adding,
|
||||
removing, or moving a skill. Running agents may need a new session to refresh their
|
||||
cached skill list or instructions.
|
||||
|
||||
```sh
|
||||
python3 bin/validate-skills # metadata, local links, duplicate names; read-only
|
||||
./sync-skills.sh --check # installed-link drift/conflicts; read-only
|
||||
```
|
||||
|
||||
Validation is for catalog maintenance, not a preflight for everyday coding.
|
||||
See [authoring and maintenance](docs/maintenance.md) for metadata, ownership,
|
||||
verification conventions, and tool regression checks.
|
||||
|
||||
## Workflow conventions
|
||||
|
||||
[Shared workflow and verification](protocols/workflow.md) defines proportional
|
||||
checks and preservation of user work. User and repository instructions take
|
||||
precedence. Telemetry and pull requests follow [the telemetry protocol](protocols/telemetry.md).
|
||||
Repository governance rules and boundary tiers adhere to [the agents template](protocols/agents-template.md).
|
||||
References load on demand; there is no required phase anatomy, per-task commit,
|
||||
separate review invocation, or blanket full-suite run.
|
||||
|
||||
Skills declare `scope: global`, `project`, or `alias`. Scope documents applicability;
|
||||
it does not change a harness router by itself. JEV-dependent skills state their
|
||||
project requirements. Some optional references assume a sibling JEV checkout.
|
||||
|
||||
## Host-specific file delivery
|
||||
|
||||
[deliver-file](skills/deliver-file/SKILL.md) uses `bin/t3-deliver` to print a command
|
||||
for the user's Windows machine to pull files over Tailscale SSH. Its host address
|
||||
is configured for this machine; adapt it before using delivery on another host.
|
||||
The helper assumes `realpath` locally and OpenSSH scp with SFTP support remotely.
|
||||
It prints a command and does not start a transfer.
|
||||
Executable
+103
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Synchronize skill symlinks without taking ownership of unrelated entries."""
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def lexical(path):
|
||||
return Path(os.path.abspath(path))
|
||||
|
||||
|
||||
def link_target(path):
|
||||
return lexical(path.parent / os.readlink(path))
|
||||
|
||||
|
||||
def inside(path, root):
|
||||
return path != root and root in path.parents
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--dry-run', action='store_true', help='show changes without writing')
|
||||
parser.add_argument('--check', action='store_true', help='exit 1 if links differ; do not write')
|
||||
parser.add_argument('--global-dir', type=Path, default=Path(__file__).resolve().parents[1] / 'skills')
|
||||
parser.add_argument('--jev-dir', type=Path, default=Path.home() / 'Projects/work/JEV/.agents/skills')
|
||||
parser.add_argument('--target', action='append', type=Path, help='override target directories; repeatable')
|
||||
args = parser.parse_args(argv)
|
||||
sources = [lexical(args.global_dir), lexical(args.jev_dir)]
|
||||
targets = args.target if args.target is not None else [Path.home() / p for p in ('.agents/skills', '.codex/skills', '.claude/skills')]
|
||||
targets = [lexical(p) for p in targets]
|
||||
# Reject destinations inside catalogs (or containing them) before any mutation.
|
||||
for target in targets:
|
||||
resolved_target = target.resolve()
|
||||
if any(resolved_target == source.resolve() or
|
||||
inside(resolved_target, source.resolve()) or
|
||||
inside(source.resolve(), resolved_target) for source in sources):
|
||||
parser.error(f'target overlaps a source catalog: {target}')
|
||||
if not sources[0].is_dir():
|
||||
parser.error(f'global skill source unavailable: {sources[0]}')
|
||||
available = [p for p in sources if p.is_dir()]
|
||||
expected = {}
|
||||
errors = []
|
||||
for root in available:
|
||||
for child in sorted(root.iterdir()):
|
||||
if not child.is_dir():
|
||||
continue
|
||||
if not re.fullmatch(r'[a-z0-9]+(?:-[a-z0-9]+)*', child.name) or not (child / 'SKILL.md').is_file():
|
||||
errors.append(f'invalid skill directory: {child}')
|
||||
continue
|
||||
if child.name in expected:
|
||||
errors.append(f'colliding skill name: {child.name} ({expected[child.name]}, {child})')
|
||||
else:
|
||||
expected[child.name] = child
|
||||
if errors:
|
||||
print('\n'.join(errors), file=sys.stderr)
|
||||
return 2
|
||||
if len(available) != len(sources):
|
||||
print(f'WARN: JEV source unavailable; preserving its existing links: {sources[1]}', file=sys.stderr)
|
||||
changes = 0
|
||||
conflicts = 0
|
||||
readonly = args.check or args.dry_run
|
||||
for target in targets:
|
||||
if target.exists() and not target.is_dir():
|
||||
print(f'SKIP: target is not a directory: {target}', file=sys.stderr)
|
||||
conflicts += 1
|
||||
continue
|
||||
if not readonly:
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
# Only prune links to sources that were successfully inventoried.
|
||||
for dest in sorted(target.iterdir()) if target.is_dir() else []:
|
||||
if dest.is_symlink() and any(inside(link_target(dest), root) for root in available) and dest.name not in expected:
|
||||
print(f'remove stale: {dest}')
|
||||
changes += 1
|
||||
if not readonly:
|
||||
dest.unlink()
|
||||
for name, src in sorted(expected.items()):
|
||||
dest = target / name
|
||||
if dest.is_symlink():
|
||||
current = link_target(dest)
|
||||
if current == src:
|
||||
continue
|
||||
if not any(inside(current, root) for root in available):
|
||||
print(f'SKIP: unrelated symlink: {dest}', file=sys.stderr)
|
||||
conflicts += 1
|
||||
continue
|
||||
elif dest.exists():
|
||||
print(f'SKIP: unrelated entry: {dest}', file=sys.stderr)
|
||||
conflicts += 1
|
||||
continue
|
||||
print(f'link: {dest} -> {src}')
|
||||
changes += 1
|
||||
if not readonly:
|
||||
if dest.is_symlink():
|
||||
dest.unlink()
|
||||
dest.symlink_to(src, target_is_directory=True)
|
||||
print(f'{"check" if args.check else "dry-run" if args.dry_run else "sync"}: {changes} changes, {conflicts} conflicts')
|
||||
return 1 if conflicts or (args.check and changes) else 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
+15
-22
@@ -1,32 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Print a ready-to-paste scp command for pulling a file from this host
|
||||
# to the user's Windows machine over Tailscale SSH.
|
||||
# Print a command for the user's Windows machine to pull a path over Tailscale SSH.
|
||||
set -euo pipefail
|
||||
|
||||
HOST="vasily@msi.tail0b014a.ts.net"
|
||||
|
||||
DELIVERY_HOST="vasily@msi.tail0b014a.ts.net"
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "usage: t3-deliver <file-or-directory>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
path="$1"
|
||||
if [[ ! -e "$path" ]]; then
|
||||
echo "t3-deliver: no such path: $path" >&2
|
||||
if [[ ! -e "$1" ]]; then
|
||||
echo "t3-deliver: no such path: $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$path" != /* ]]; then
|
||||
path="$(realpath "$path")"
|
||||
else
|
||||
path="$(realpath -m "$path")"
|
||||
DELIVERY_PATH="$(realpath -- "$1")"
|
||||
# Reject characters that cannot be shared safely between cmd and PowerShell.
|
||||
# OpenSSH SFTP mode handles the quoted remote path without a remote shell.
|
||||
if [[ "$DELIVERY_PATH" == *[\"\$\`\%\!]* || "$DELIVERY_PATH" == *$'\n'* || "$DELIVERY_PATH" == *$'\r'* ]]; then
|
||||
echo 't3-deliver: rename or archive this path with a simple name before delivery' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
flags=""
|
||||
if [[ -d "$path" ]]; then
|
||||
flags="-r "
|
||||
DELIVERY_FLAGS=""
|
||||
if [[ -d "$DELIVERY_PATH" ]]; then
|
||||
DELIVERY_FLAGS="-r "
|
||||
fi
|
||||
|
||||
echo "Paste in cmd or PowerShell on your Windows machine:"
|
||||
echo
|
||||
echo "${flags}scp ${HOST}:\"${path}\" ."
|
||||
printf 'Paste in cmd or PowerShell on your Windows machine (OpenSSH scp with SFTP support):\n\n'
|
||||
printf 'scp %s"%s:%s" .\n' "$DELIVERY_FLAGS" "$DELIVERY_HOST" "$DELIVERY_PATH"
|
||||
Executable
+125
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check catalog metadata, local links, and duplicate names without mutating files."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def metadata(text):
|
||||
"""Read the catalog's scalar and block-string YAML frontmatter subset."""
|
||||
match = re.match(r'\A---\r?\n(.*?)\r?\n---(?:\r?\n|$)', text, re.S)
|
||||
if not match:
|
||||
raise ValueError('missing frontmatter')
|
||||
result = {}
|
||||
field = None
|
||||
for line in match[1].splitlines():
|
||||
if not line.strip() or line.lstrip().startswith('#'):
|
||||
continue
|
||||
if line[0].isspace():
|
||||
if field is None:
|
||||
raise ValueError('unexpected indentation in frontmatter')
|
||||
result[field] += ' ' + line.strip()
|
||||
continue
|
||||
item = re.fullmatch(r'([a-z][a-z0-9_-]*):(?:\s+(.*))?', line)
|
||||
if not item:
|
||||
raise ValueError('invalid frontmatter field')
|
||||
key, value = item.groups()
|
||||
if key in result:
|
||||
raise ValueError(f'duplicate field: {key}')
|
||||
value = (value or '').strip()
|
||||
field = key if value in ('>', '|', '>-', '|-') else None
|
||||
if field:
|
||||
result[key] = ''
|
||||
else:
|
||||
if value.startswith('"'):
|
||||
try:
|
||||
result[key] = json.loads(value)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise ValueError(f'invalid quoted field: {key}') from exc
|
||||
elif value.startswith("'"):
|
||||
if len(value) < 2 or not value.endswith("'"):
|
||||
raise ValueError(f'invalid quoted field: {key}')
|
||||
result[key] = value[1:-1].replace("''", "'")
|
||||
else:
|
||||
if re.search(r':\s', value):
|
||||
raise ValueError(f'invalid plain scalar: {key}; use a block string')
|
||||
result[key] = value.split(' #', 1)[0]
|
||||
return {k: v.strip() for k, v in result.items()}
|
||||
|
||||
|
||||
def local_links(path):
|
||||
fenced = False
|
||||
for number, line in enumerate(path.read_text().splitlines(), 1):
|
||||
if line.lstrip().startswith(('```', '~~~')):
|
||||
fenced = not fenced
|
||||
continue
|
||||
if fenced:
|
||||
continue
|
||||
for raw in re.findall(r'\]\(([^)]+)\)', line):
|
||||
target = raw.strip().split('#', 1)[0]
|
||||
if not target or re.match(r'[a-zA-Z][a-zA-Z0-9+.-]*:', target):
|
||||
continue
|
||||
target = target.strip('<>')
|
||||
resolved = path.parent / target
|
||||
if not resolved.exists():
|
||||
yield f'{path}:{number}: missing link target {target}'
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--global-dir', type=Path, default=Path(__file__).resolve().parents[1] / 'skills')
|
||||
parser.add_argument('--jev-dir', type=Path, default=Path.home() / 'Projects/work/JEV/.agents/skills')
|
||||
args = parser.parse_args(argv)
|
||||
errors = []
|
||||
names = {}
|
||||
count = 0
|
||||
if not args.global_dir.is_dir():
|
||||
parser.error(f'global catalog unavailable: {args.global_dir}')
|
||||
roots = [args.global_dir]
|
||||
if args.jev_dir.is_dir():
|
||||
roots.append(args.jev_dir)
|
||||
else:
|
||||
print(f'WARN: JEV catalog unavailable: {args.jev_dir}', file=sys.stderr)
|
||||
for root in roots:
|
||||
for directory in sorted(root.iterdir()):
|
||||
if not directory.is_dir():
|
||||
continue
|
||||
path = directory / 'SKILL.md'
|
||||
if not path.is_file():
|
||||
errors.append(f'{directory}: missing SKILL.md')
|
||||
continue
|
||||
count += 1
|
||||
try:
|
||||
fields = metadata(path.read_text())
|
||||
name = fields.get('name', '')
|
||||
if name != directory.name or not re.fullmatch(r'[a-z0-9]+(?:-[a-z0-9]+)*', name):
|
||||
errors.append(f'{path}: invalid or mismatched name')
|
||||
if not fields.get('description'):
|
||||
errors.append(f'{path}: empty description')
|
||||
if fields.get('scope') not in ('global', 'project', 'alias'):
|
||||
errors.append(f'{path}: scope must be global, project, or alias')
|
||||
if name in names:
|
||||
errors.append(f'{path}: name collides with {names[name]}')
|
||||
names[name] = path
|
||||
except ValueError as exc:
|
||||
errors.append(f'{path}: {exc}')
|
||||
for path in sorted(root.rglob('*.md')):
|
||||
errors.extend(local_links(path))
|
||||
# Global protocols are part of this catalog; JEV protocols belong to its source.
|
||||
for folder in [args.global_dir.parent / 'protocols', args.jev_dir.parent / 'protocols']:
|
||||
if folder.is_dir():
|
||||
for path in sorted(folder.glob('*.md')):
|
||||
errors.extend(local_links(path))
|
||||
readme = args.global_dir.parent / 'README.md'
|
||||
if readme.is_file():
|
||||
errors.extend(local_links(readme))
|
||||
for error in errors:
|
||||
print(error, file=sys.stderr)
|
||||
print(f'catalog: {count} skills, {len(errors)} errors')
|
||||
return bool(errors)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,151 @@
|
||||
# Installation and usage
|
||||
|
||||
## Get the source
|
||||
|
||||
Use an existing checkout or clone the repository into a stable location. Replace
|
||||
`<repository-url>` with the URL of your copy; this checkout has no configured Git
|
||||
remote from which to derive one.
|
||||
|
||||
```sh
|
||||
git clone <repository-url> ~/Projects/work/global-skills
|
||||
cd ~/Projects/work/global-skills
|
||||
```
|
||||
|
||||
Requirements: Bash, Python 3, and symbolic-link support. No Python packages or Node
|
||||
packages are needed for syncing. Keep the checkout after installing: installed
|
||||
links point into it.
|
||||
|
||||
The commands here target a Linux host. Native Windows installation and junction
|
||||
management are not implemented by this script.
|
||||
|
||||
## Install the catalog
|
||||
|
||||
```sh
|
||||
./sync-skills.sh --dry-run
|
||||
./sync-skills.sh
|
||||
./sync-skills.sh --check
|
||||
```
|
||||
|
||||
The first command previews changes, the second applies them, and the third checks
|
||||
the result without writing. Default destinations are `~/.agents/skills`,
|
||||
`~/.codex/skills`, and `~/.claude/skills`.
|
||||
|
||||
Sync includes every valid skill directory from this checkout and, when available,
|
||||
`~/Projects/work/JEV/.agents/skills`. A source skill must have a kebab-case directory
|
||||
name and a `SKILL.md` file. Duplicate names across sources stop sync before writes.
|
||||
Existing unrelated destinations are preserved and reported as conflicts.
|
||||
|
||||
If JEV is absent, sync warns and installs the shared catalog. Some skill references
|
||||
and the `anti-slop-editor` alias depend on JEV or the expected sibling-checkout
|
||||
layout. The optional catalog validator reports unresolved local references; it is
|
||||
not required to install the shared skills.
|
||||
|
||||
## Install into selected agent directories
|
||||
|
||||
`--target` replaces the default destinations. Repeat it to select several:
|
||||
|
||||
```sh
|
||||
./sync-skills.sh --target "$HOME/.codex/skills"
|
||||
./sync-skills.sh --target "$HOME/.codex/skills" --target "$HOME/.claude/skills"
|
||||
```
|
||||
|
||||
Both commands install the available source catalogs, not a selected subset of
|
||||
skills. Targets cannot overlap a source catalog.
|
||||
|
||||
For a different JEV location, use the same override for syncing and checking:
|
||||
|
||||
```sh
|
||||
./sync-skills.sh --jev-dir /path/to/JEV/.agents/skills --target "$HOME/.codex/skills"
|
||||
./sync-skills.sh --check --jev-dir /path/to/JEV/.agents/skills --target "$HOME/.codex/skills"
|
||||
```
|
||||
|
||||
`--global-dir` overrides the shared source directory. Moving sources may require
|
||||
manual removal of old links: the script recognizes ownership only under the source
|
||||
roots supplied for that invocation.
|
||||
|
||||
## Install one shared skill
|
||||
|
||||
For a small selection, create links directly instead of running catalog sync.
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
mkdir -p "$HOME/.codex/skills"
|
||||
ln -s "$PWD/skills/interface-kit" "$HOME/.codex/skills/interface-kit"
|
||||
```
|
||||
|
||||
Repeat with the desired skill name and agent directory. Link the whole skill
|
||||
directory so its references remain available. Keep the checkout and its protocols;
|
||||
copying just `SKILL.md` can break relative references.
|
||||
|
||||
`ln -s` fails if that destination already exists. Inspect an existing entry before
|
||||
replacing it. Catalog sync later adds all available skills to that target; it is
|
||||
not a subset installer.
|
||||
|
||||
## Antigravity
|
||||
|
||||
The sync script does not edit Antigravity configuration. On this host, Antigravity
|
||||
reads source directories listed in `~/.gemini/config/skills.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"entries": [
|
||||
{ "path": "/absolute/path/to/global-skills/skills" },
|
||||
{ "path": "/absolute/path/to/JEV/.agents/skills" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Use your actual absolute paths and omit JEV if unavailable. Merge entries with
|
||||
existing configuration rather than overwriting unrelated sources. This is the
|
||||
configuration used by the current host integration; another Antigravity version
|
||||
or setup may discover skills differently.
|
||||
|
||||
## Use and update
|
||||
|
||||
Ask for work normally or explicitly name a skill. For example:
|
||||
|
||||
```text
|
||||
Use app-security to check authorization on these routes. Give me a report first.
|
||||
Use deepen to simplify this module while preserving its public behavior.
|
||||
Use fuck-slop to edit this draft without changing its claims.
|
||||
```
|
||||
|
||||
The agent decides applicability from its available skill catalog. Naming a skill
|
||||
does not authorize unrelated edits, publishing, or other external actions.
|
||||
|
||||
Edit the canonical source to update a skill. Existing links expose that content
|
||||
immediately; start a new agent session if the running session cached older
|
||||
instructions. Sync after changes to skill names or directory locations.
|
||||
|
||||
For Git updates, follow your checkout's branch/remote convention. Inspect local
|
||||
changes before pulling; this project does not impose a remote or auto-update policy.
|
||||
|
||||
## Remove an installation
|
||||
|
||||
Remove an individual symlink from the agent directory after inspecting it:
|
||||
|
||||
```sh
|
||||
ls -l "$HOME/.codex/skills/interface-kit"
|
||||
```
|
||||
|
||||
If it points to this checkout, remove that link. Removing an installed link leaves
|
||||
the source intact; the next full sync recreates it. To retire a skill from the
|
||||
catalog, remove its source directory and sync while the source root is still
|
||||
available. Missing JEV sources cause their old links to be preserved, not removed.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Result | Meaning and next step |
|
||||
| --- | --- |
|
||||
| `check: 0 changes, 0 conflicts` | Installed links match the available catalogs. |
|
||||
| Check exits `1` with changes | Preview with `--dry-run`, then sync to apply the changes. |
|
||||
| `SKIP: unrelated entry` or `unrelated symlink` | Inspect that destination; sync preserves it. Choose another target or deliberately resolve the collision. |
|
||||
| Colliding skill name, exit `2` | Rename or consolidate the source skills; there is no silent precedence rule. |
|
||||
| JEV unavailable warning | Shared skills can install; JEV links are preserved until its source is available. |
|
||||
| Validator reports missing local links | Restore the referenced file/checkouts or correct the source link. Sync checks installation, not reference integrity. |
|
||||
| Skill missing in a running agent | Check the source and installed link, then refresh that agent's session/catalog. |
|
||||
|
||||
`--dry-run` and `--check` make no changes. Dry-run exits `0` for a conflict-free
|
||||
preview even when changes are needed. Check exits `1` for drift or conflicts.
|
||||
Sync also exits `1` for destination conflicts; unaffected destinations may already
|
||||
have been updated. Invalid source catalogs/arguments exit `2` before syncing.
|
||||
@@ -0,0 +1,111 @@
|
||||
# Authoring and maintenance
|
||||
|
||||
Shared workflows live in `skills/<name>/`; JEV runtime-specific skills remain in
|
||||
JEV. Installed directories link to those sources. Maintain one procedure per
|
||||
workflow and use small aliases when an old name needs to remain callable.
|
||||
|
||||
## Add or edit a skill
|
||||
|
||||
Use [skill-architect](../skills/skill-architect/SKILL.md) for catalog work. A skill
|
||||
needs concrete activation criteria, useful steps, and appropriate completion
|
||||
evidence. There is no required phase structure or length quota.
|
||||
|
||||
Example `SKILL.md` metadata:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: example-skill
|
||||
description: >
|
||||
Perform a specific workflow when the user requests its concrete outcome.
|
||||
scope: global
|
||||
---
|
||||
```
|
||||
|
||||
Names use lowercase kebab-case and match the containing directory. Scope values:
|
||||
|
||||
| Scope | Meaning |
|
||||
| --- | --- |
|
||||
| `global` | Reusable workflow; preserve the target repository's conventions. |
|
||||
| `project` | Requires a named project's tooling or layout; explain that dependency. |
|
||||
| `alias` | Explicit compatibility entry point delegating to another skill. |
|
||||
|
||||
Scope is descriptive metadata; a harness must implement its own routing policy.
|
||||
Write optional recipes under `references/` and link them where they help a decision.
|
||||
Keep relative links valid from the source file. Use the
|
||||
[template](../skills/skill-architect/references/sample-skill.md) as an example.
|
||||
|
||||
For catalog changes, validate once from the repository root:
|
||||
|
||||
```sh
|
||||
python3 bin/validate-skills
|
||||
```
|
||||
|
||||
After adding, removing, or moving a skill, preview and sync:
|
||||
|
||||
```sh
|
||||
./sync-skills.sh --dry-run
|
||||
./sync-skills.sh
|
||||
```
|
||||
|
||||
Content-only edits already propagate through existing links. Commit according to
|
||||
the user's request and repository/session conventions; these tools do not commit.
|
||||
|
||||
## Workflow rules
|
||||
|
||||
Follow [shared workflow and verification](../protocols/workflow.md): use existing
|
||||
context, preserve user work, and choose checks that can detect a real failure in
|
||||
the changed behavior. Avoid mandatory cross-skill handoffs, repeated confirmation,
|
||||
full suites for prose edits, or automatic spec creation for ordinary bug fixes.
|
||||
|
||||
In an adopted spec workflow, `spec` owns architecture and task definitions, `build`
|
||||
owns task statuses, and `backprop` owns bug records and bug-related invariants.
|
||||
See [the spec format](../skills/spec/references/format.md). A review-only request
|
||||
produces findings without edits or commits.
|
||||
|
||||
## What validation covers
|
||||
|
||||
`bin/validate-skills` checks metadata, matching names, scope, duplicate source
|
||||
names, and local Markdown targets outside fenced examples. It uses Python's
|
||||
standard library and supports this catalog's scalar/block-string YAML subset.
|
||||
It does not verify web links, Markdown anchors, arbitrary YAML schemas, or whether
|
||||
an agent will activate or execute a skill correctly.
|
||||
|
||||
Both tools accept `--global-dir` and `--jev-dir`. Sync additionally accepts
|
||||
repeatable `--target` arguments. Use source overrides consistently when checking
|
||||
a custom installation. Link ownership is inferred from those source roots; it is
|
||||
not recorded in a separate manifest.
|
||||
|
||||
## Verify tool changes
|
||||
|
||||
When sync, validation, or delivery behavior changes, run the relevant regression
|
||||
checks from the repository root:
|
||||
|
||||
```sh
|
||||
python3 -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
Tests use temporary source catalogs and targets; they do not change installed
|
||||
agent directories. Coverage includes link ownership, stale cleanup, read-only
|
||||
modes, collisions, missing sources, and delivery command generation.
|
||||
|
||||
[Workflow evaluation cases](../tests/workflow-cases.md) are optional fixtures for
|
||||
trigger or policy changes. A behavioral evaluation requires observed agent actions;
|
||||
passing script tests does not prove routing quality. Use real failures to guide
|
||||
small corrections rather than adding more mandatory checks.
|
||||
|
||||
## Delivery helper
|
||||
|
||||
`bin/t3-deliver` prints a quoted `scp` command using this host's Tailscale address.
|
||||
It requires Bash and `realpath`; the receiving Windows machine needs OpenSSH scp
|
||||
with SFTP support and access to the host. It starts no server or transfer.
|
||||
|
||||
To expose it on PATH, link the helper from the repository root:
|
||||
|
||||
```sh
|
||||
mkdir -p "$HOME/.local/bin"
|
||||
ln -s "$PWD/bin/t3-deliver" "$HOME/.local/bin/t3-deliver"
|
||||
```
|
||||
|
||||
Inspect an existing destination before replacing it. `sync-skills.sh` installs
|
||||
skill directories, not this executable link. On another host, adapt the address
|
||||
in `bin/t3-deliver` and the delivery skill's host-specific instructions together.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Autonomous Agent Repository Rules Template
|
||||
|
||||
This protocol defines the standard structure for a repository's root `AGENTS.md`
|
||||
(and symlinked `CLAUDE.md`). It establishes concise behavioral baselines,
|
||||
deterministic boundary tiers, and progressive disclosure pointers.
|
||||
|
||||
## Design imperatives
|
||||
|
||||
- **Length limit**: Keep the root instruction file concise ($\le 100$ lines target,
|
||||
300 lines maximum). Long rule files dilute model attention and are ignored.
|
||||
- **Progressive disclosure**: Keep the root file an index of essential build/test
|
||||
commands and pointers. Direct deep subsystem knowledge or tutorials into
|
||||
specialized documents under `docs/` or `.agents/`.
|
||||
- **Deterministic tooling**: Never delegate code formatting, whitespace, or import
|
||||
sorting to LLM prompt prose. Formatting and linting belong exclusively to
|
||||
deterministic CLI tools (Ruff, Biome, Prettier) run via hooks or CI.
|
||||
|
||||
## Three-tier operational boundaries
|
||||
|
||||
Root repository instructions must establish three explicit operational tiers:
|
||||
|
||||
### 1. ALWAYS (Autonomous Execution)
|
||||
Actions the agent must execute autonomously without asking for confirmation:
|
||||
- Run targeted local unit and regression tests after making code changes.
|
||||
- Execute deterministic linters and formatters before staging files.
|
||||
- Update relevant documentation and architectural records when public interfaces change.
|
||||
- Follow existing repository patterns, conventions, and module structure.
|
||||
|
||||
### 2. ASK FIRST (Human Confirmation Required)
|
||||
Boundary actions requiring explicit confirmation before invocation:
|
||||
- Modifying database schemas or executing destructive data migrations.
|
||||
- Introducing new third-party dependencies, packages, or external services.
|
||||
- Altering production deployment configurations, Dockerfiles, or CI workflows.
|
||||
- Deleting existing tracked source files or removing deprecated public APIs.
|
||||
|
||||
### 3. NEVER (Non-Negotiable Invariants)
|
||||
Hard negative constraints that must never be violated under any circumstances:
|
||||
- Never commit plain-text credentials, tokens, or environment files (`.env`).
|
||||
- Never force-push (`git push --force` or `-f`) to any remote tracking branch.
|
||||
- Never execute destructive git resets (`git reset --hard` or `git clean -f`) on uncommitted work.
|
||||
- Never commit directly to primary branches (`main` or `master`).
|
||||
- Never suppress compiler warnings or type errors with blanket ignores (`# noqa`, `@ts-ignore`).
|
||||
|
||||
## Canonical AGENTS.md template
|
||||
|
||||
```markdown
|
||||
# [Project Name] Agent Rules
|
||||
|
||||
## Stack & Commands
|
||||
- Language & Runtime: [e.g. Python 3.12 / Node 20 / Rust 1.80]
|
||||
- Package Manager: [e.g. uv / pnpm / cargo]
|
||||
- Fast Check: [e.g. pytest tests/unit/ / pnpm test / cargo test]
|
||||
- Linter & Formatter: [e.g. ruff check --fix && ruff format / pnpm biome check --apply]
|
||||
- Type Checker: [e.g. pyright / pnpm tsc --noEmit]
|
||||
|
||||
## Three-Tier Boundaries
|
||||
- **ALWAYS**: Run relevant checks before declaring completion. Run deterministic formatters.
|
||||
- **ASK FIRST**: Adding dependencies, altering database schemas, or changing CI/deploy configs.
|
||||
- **NEVER**: Direct commits to main, force pushes, hard resets, or committing secrets/.env.
|
||||
|
||||
## Workflow & References
|
||||
- Feature work occurs in isolated git worktrees or dedicated branches.
|
||||
- Follow WHAT-WHY-HOW-LEARNINGS telemetry format for commits and pull requests.
|
||||
- Subsystem details: see docs/architecture.md and docs/gotchas/.
|
||||
```
|
||||
@@ -0,0 +1,73 @@
|
||||
# Standardized Agent Telemetry Protocol
|
||||
|
||||
This protocol defines the **WHAT-WHY-HOW-LEARNINGS** communication standard for
|
||||
autonomous agents. It eliminates unstructured conversational filler and ensures
|
||||
every completion report and pull request provides verified empirical evidence and
|
||||
captures reusable operational memory.
|
||||
|
||||
## Governing principle
|
||||
|
||||
**"The model proposes, but the engine measures."**
|
||||
An agent must never claim completion based on internal heuristics or theoretical
|
||||
assumptions. Verification requires concrete CLI execution evidence with explicit
|
||||
exit codes and metric outputs.
|
||||
|
||||
## Telemetry structure
|
||||
|
||||
When reporting task completion or generating pull request bodies, format the
|
||||
output using these four distinct sections:
|
||||
|
||||
### 1. WHAT (System Modifications)
|
||||
Itemize physical repository deltas. Do not use speculative language. Mirror the
|
||||
factual `git status` / `git diff` state:
|
||||
- **Modified Components**: Relative paths of modified files.
|
||||
- **Added Assets**: Relative paths of newly created modules, tests, or configurations.
|
||||
- **Removed Assets**: Deprecated files, removed functions, or deleted packages.
|
||||
|
||||
### 2. WHY (Context & Architectural Intent)
|
||||
Articulate the underlying rationale and business justification:
|
||||
- **Problem Statement**: Explicit description of the bug, requirement, or performance bottleneck.
|
||||
- **Requirement Traceability**: Reference to specification issue, plan bead, or task ticket.
|
||||
- **Design Justification**: Why this approach was selected over alternative implementations.
|
||||
|
||||
### 3. HOW (Technical Implementation & Verification Evidence)
|
||||
Detail the mechanical execution and empirical proof of correctness:
|
||||
- **Implementation Details**: Summary of algorithmic changes, API updates, or data structures.
|
||||
- **Deterministic Verification Evidence**:
|
||||
- Exact command(s) executed (e.g. `pytest tests/unit/test_auth.py -v`).
|
||||
- Terminal exit code (must be 0).
|
||||
- Test runner output metrics (e.g. `38 passed, 0 failed, 100% pass rate in 1.4s`).
|
||||
- **Static Analysis & Type Checks**:
|
||||
- Linter/type checker commands and output (e.g. `ruff check src/` -> clean).
|
||||
|
||||
### 4. LEARNINGS & ARCHITECTURAL GOTCHAS
|
||||
Capture operational traps, latent technical debt, and environment quirks:
|
||||
- **Operational Traps**: Version sensitivities, platform discrepancies, race conditions.
|
||||
- **Uncovered Debt**: Missing mocks, tight couplings, or obsolete patterns uncovered.
|
||||
- **Repository Gotchas**: When a new trap or quirk is discovered, persist it to
|
||||
`docs/gotchas/<slug>.md` so subsequent sessions load it into context.
|
||||
- **Upstream Dependencies**: Follow-up tasks or recommendations.
|
||||
|
||||
## Markdown template for PRs and task reports
|
||||
|
||||
```markdown
|
||||
### 1. WHAT (System Modifications)
|
||||
- **Modified**: `src/auth/session.py`
|
||||
- **Added**: `tests/unit/test_session_refresh.py`
|
||||
- **Removed**: None
|
||||
|
||||
### 2. WHY (Context & Architectural Intent)
|
||||
- **Problem**: Concurrent session refresh requests cause race conditions and invalid tokens.
|
||||
- **Traceability**: Closes #142 (Task T-3).
|
||||
- **Design Justification**: Implemented in-process locking with Redis token leases.
|
||||
|
||||
### 3. HOW (Technical Implementation & Verification Evidence)
|
||||
- **Implementation**: Wrapped refresh logic in distributed mutex with 5s expiry.
|
||||
- **Verification Commands Executed**:
|
||||
- `pytest tests/unit/test_session_refresh.py` (Exit Code: 0, 12 passed in 0.8s)
|
||||
- `ruff check src/auth/` (Exit Code: 0, clean)
|
||||
|
||||
### 4. LEARNINGS & ARCHITECTURAL GOTCHAS
|
||||
- **Operational Trap**: Redis cluster failover resets key TTL in mock environment.
|
||||
- **Indexed Gotcha**: Saved to `docs/gotchas/redis-mock-cluster-ttl.md`.
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
# Shared workflow
|
||||
|
||||
Skills simplify an authorized task. User instructions and repository conventions
|
||||
set the scope; a skill supplies defaults where those leave a gap.
|
||||
|
||||
- Use the existing conversation, files, and project state before asking questions.
|
||||
Ask only when a missing answer changes the outcome and cannot be inferred safely.
|
||||
- A report or audit stays read-only. An implementation request authorizes the
|
||||
necessary reversible edits and checks. Continue authorized work without asking
|
||||
the user to approve each step.
|
||||
- Follow the repository's operational boundaries ([agents-template.md](agents-template.md)):
|
||||
distinguish autonomous actions (ALWAYS), user-approved boundaries (ASK FIRST),
|
||||
and hard invariants (NEVER).
|
||||
- Do not create a spec, force a review, run an editing skill, or start a refactor
|
||||
merely because another skill mentions it. Use another workflow only when its
|
||||
prerequisites and purpose fit the current task.
|
||||
- Preserve unrelated changes. Stage and commit only within the authorized scope,
|
||||
following repository and session instructions. A skill does not require commits.
|
||||
- Keep references optional: read the relevant section when needed. Do not load
|
||||
every protocol or checklist on each task.
|
||||
- Report completion and pull requests using the [telemetry protocol](telemetry.md)
|
||||
(WHAT-WHY-HOW-LEARNINGS).
|
||||
|
||||
## Verification
|
||||
|
||||
**"The model proposes, but the engine measures."**
|
||||
Choose checks that can detect a real failure in the changed behavior.
|
||||
|
||||
1. Run the smallest relevant check first: syntax, a focused test, type check,
|
||||
rendered interaction, or direct output inspection.
|
||||
2. Broaden to integration or the full suite when shared behavior, security,
|
||||
migrations, or unresolved failures justify it, or project instructions require it.
|
||||
3. Do not add tests that mirror implementation or cover only a reversible prose
|
||||
or cosmetic edit. Add regression coverage for meaningful behavioral bugs when
|
||||
practical; a reproduction or manual check can be the evidence when automation
|
||||
is unsuitable.
|
||||
4. Distinguish new failures from pre-existing failures and missing dependencies.
|
||||
Report what passed and what remains unverified; do not claim unavailable checks
|
||||
passed or rewrite unrelated code to make the entire repository green.
|
||||
5. Once relevant checks pass, stop repeating them unless something changed.
|
||||
6. When reporting verification in task handoffs or PRs, document the exact terminal
|
||||
command, exit code, and pass counts under the HOW section of telemetry.
|
||||
|
||||
Complete means the requested behavior is implemented and supported by empirical
|
||||
evidence. A successful command exit alone does not prove the user-facing outcome.
|
||||
+19
-97
@@ -1,104 +1,26 @@
|
||||
---
|
||||
name: api-design
|
||||
description: >
|
||||
Designs RESTful APIs, typed schema membranes, request/response validation contracts, and API documentation.
|
||||
Use when creating or modifying API routes, defining request/response schemas, designing error responses,
|
||||
or standardizing API contracts.
|
||||
concerns: [security, system-one-balance]
|
||||
Design or modify API routes, validated request/response schemas, error contracts, and API documentation within the existing project stack.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# API Design & Membrane Architecture
|
||||
# API design
|
||||
|
||||
Governs API design and boundary membranes, ensuring typed validation, input clamping, predictable HTTP semantics, and consistent structured error contracts.
|
||||
1. Inspect the existing transport, schema library, auth, and error conventions.
|
||||
Keep domain logic independent of HTTP/framework request objects where practical.
|
||||
2. Define inputs, outputs, status codes, authorization, and meaningful payload limits.
|
||||
Use runtime validation at untrusted boundaries; TypeScript interfaces alone do
|
||||
not validate requests. Derive limits from product needs and resource budgets.
|
||||
3. Implement the route using existing services and data access patterns. Reuse
|
||||
existing dependency injection; do not introduce layers or repositories by default.
|
||||
4. Preserve HTTP semantics and the project's error shape. Use Problem Details
|
||||
when adopting that format; otherwise document the existing structured contract.
|
||||
Serialize timestamps consistently with explicit timezone information.
|
||||
5. Verify changed contracts and failure behavior under
|
||||
[shared verification](../../protocols/workflow.md#verification).
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Membrane Principles**:
|
||||
- **Boundary Isolation**: Route handlers serve as the transport membrane. Core business services and data access layers remain transport-agnostic (never import web framework request objects or HTTP status codes into domain logic).
|
||||
- **Contract-First Validation**: Define typed schemas (e.g. Pydantic, Zod, TypeScript interfaces) before implementing endpoint logic.
|
||||
- **Dependency Injection**: Inject database sessions, repositories, and authentication state into route handlers; avoid importing global singletons directly.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Identify Endpoint Requirements**:
|
||||
- Resource name, target path, HTTP method (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`).
|
||||
- Expected input payload, query parameters, route path variables, and headers.
|
||||
- Response model, status codes (200, 201, 204), and error failure modes.
|
||||
2. **Input Boundary Clamping**:
|
||||
- Enforce explicit upper bounds on all strings (e.g. `min_length=1`, `max_length=200` for names; `max_length=50000` for content).
|
||||
- Enforce pagination limits: `1 <= limit <= 50` (or `100` max).
|
||||
- Constrain array inputs: clamp batch endpoints to maximum batch sizes.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Define Typed Contracts
|
||||
```python
|
||||
# 1. Request & Response Schemas
|
||||
class ResourceCreateRequest(BaseModel):
|
||||
name: str = Field(..., min_length=1, max_length=200)
|
||||
description: str | None = Field(None, max_length=2000)
|
||||
|
||||
class ResourceResponse(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
description: str | None = None
|
||||
created_at: datetime
|
||||
```
|
||||
|
||||
### Step 2: Implement Route Handler
|
||||
```python
|
||||
# 2. Endpoint Implementation
|
||||
@router.post("/resources", response_model=ResourceResponse, status_code=201)
|
||||
async def create_resource(
|
||||
payload: ResourceCreateRequest,
|
||||
repo: ResourceRepository = Depends(get_resource_repo),
|
||||
):
|
||||
entity = await repo.create(payload.model_dump())
|
||||
return ResourceResponse.model_validate(entity)
|
||||
```
|
||||
|
||||
### Step 3: Enforce HTTP & Error Semantics
|
||||
- **HTTP Methods**:
|
||||
- `POST`: Resource creation / command execution (201 Created or 200 OK).
|
||||
- `GET`: Idempotent retrieval (200 OK).
|
||||
- `PUT`: Full resource replacement (200 OK).
|
||||
- `PATCH`: Partial state update (200 OK).
|
||||
- `DELETE`: Resource removal (204 No Content).
|
||||
- **Structured Error Responses**:
|
||||
- Return standardized error objects (e.g. RFC 7807 problem details or structured error payloads):
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "RESOURCE_NOT_FOUND",
|
||||
"message": "Resource with id 'xyz' was not found",
|
||||
"details": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
- Standard status codes: 400 (Validation), 401 (Unauthenticated), 403 (Unauthorized), 404 (Not Found), 409 (Conflict).
|
||||
- **Timezone Invariant**: Always serialize timestamps in UTC using ISO-8601 (`YYYY-MM-DDTHH:MM:SSZ`).
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT over-complicate simple internal endpoints with bloated enterprise middleware.
|
||||
- Keep route handlers thin: route logic should unpack requests, call services/repos, and map to response models.
|
||||
- Fail open on safe internal queries; enforce rigorous clamping at external boundary layers.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Verify:
|
||||
- Route docstrings populate OpenAPI / Swagger schemas accurately.
|
||||
- All response models are strongly typed without bare `dict` or `Any` escapes.
|
||||
- Input clamping fields prevent memory exhaustion and DoS.
|
||||
2. Deliver the schema definition, route implementation, and corresponding test case.
|
||||
Read [security guidance](../app-security/SKILL.md) for affected untrusted boundaries,
|
||||
not as a mandatory second audit. Validation and authorization failures reject the
|
||||
request. A dependency fallback requires an explicit behavior contract; never infer
|
||||
"fail open" merely because an endpoint is internal.
|
||||
@@ -1,98 +1,38 @@
|
||||
---
|
||||
name: app-security
|
||||
description: >
|
||||
Full-stack application and API security hardening: Four-Pillar upload defense,
|
||||
SSRF prevention, input boundary clamping, IDOR elimination, and secret masking.
|
||||
Use when creating or auditing API routes, handling uploads, making outbound requests,
|
||||
or preparing pre-release security verification.
|
||||
concerns: [security]
|
||||
Harden affected application boundaries when implementing or auditing authorization, uploads, user-influenced outbound requests, or sensitive data handling.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Application Security Hardening
|
||||
# Application security
|
||||
|
||||
Enforces defensive boundaries across the API membrane, eliminating exploit vectors, path traversals, SSRF risks, IDOR vulnerabilities, and payload exhaustion.
|
||||
Inspect the affected boundary and existing controls. Apply the protections relevant
|
||||
to the task; a small fix does not require a full application audit.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Inbound Request"] --> B["1. Membrane Clamping<br/>(Schema & Bound Validation)"]
|
||||
B --> C["2. Four-Pillar Uploads<br/>(Size, Ext, Magic, Path)"]
|
||||
C --> D["3. Outbound SSRF Guard<br/>(Loopback/Metadata Block)"]
|
||||
D --> E["4. Secret Masking<br/>(Zero Token Sediment)"]
|
||||
```
|
||||
1. Validate untrusted payloads with runtime schemas and resource bounds derived
|
||||
from product requirements. Reject invalid data; do not silently truncate credentials.
|
||||
2. Derive identity from verified server authentication. Enforce tenant/resource
|
||||
permissions on private reads and writes, preferably within the data operation.
|
||||
Cover unauthenticated access, cross-tenant access, and relevant races.
|
||||
3. For uploads, enforce a product-specific extension/type allowlist, stream byte
|
||||
limits, and appropriate content validation. Magic headers alone do not prove
|
||||
safety. Use generated storage names and an isolated non-executable root; prevent
|
||||
traversal and symlink escapes. Serve potentially active content with appropriate
|
||||
isolation and headers. Bound archive expansion or decoding work when applicable.
|
||||
4. For user-influenced outbound destinations, allowlist known services where possible.
|
||||
Parse URLs, restrict schemes, resolve and validate all IPv4/IPv6 addresses, and
|
||||
prevent DNS changes from bypassing connection checks. Disable redirects or validate
|
||||
each destination using the same policy. Block private, loopback, link-local,
|
||||
unspecified, and metadata targets unless a specific trusted internal service is
|
||||
intentionally allowed. Apply time, response-size, and network egress limits.
|
||||
5. Redact credentials at logging/telemetry boundaries and keep public errors free
|
||||
of secrets and internal traces. Apply relevant session, CSRF, rate-limiting, and
|
||||
browser content controls using existing framework facilities.
|
||||
6. Verify the changed boundary with meaningful negative cases under
|
||||
[shared verification](../../protocols/workflow.md#verification). Report actual
|
||||
protections and gaps; do not claim the whole app is secure from a checklist.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Review reference playbooks:
|
||||
- [references/app-hardening-playbook.md](references/app-hardening-playbook.md) for concrete TypeScript/Python code patterns and boundary clamps.
|
||||
- [references/review-checklist.md](references/review-checklist.md) for pre-release OWASP verification checks.
|
||||
2. Invariants:
|
||||
- Every input payload must be typed and bounded.
|
||||
- Every state mutation must verify session identity and tenant ownership.
|
||||
- Outbound HTTP fetches must never touch private/loopback networks.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Surface Identification**:
|
||||
- Inbound API routes (REST, GraphQL, RPC handlers).
|
||||
- File/document ingestion and attachment endpoints.
|
||||
- Outbound network calls (webhooks, URL unfurlers, external data scrapers).
|
||||
- Data persistence operations and logging sinks.
|
||||
2. **Access Control Check**:
|
||||
- Confirm identity is derived from verified server sessions/tokens, never trusted client parameters (`userId`, `orgId`).
|
||||
- Confirm entity queries enforce ownership: verify record exists AND belongs to the authenticated caller before mutating.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Input Boundaries & Membrane Clamping
|
||||
- Never accept arbitrary, unvalidated request dictionaries. Model all payloads using strict schemas (e.g. Pydantic, Zod).
|
||||
- Enforce hard string limits:
|
||||
- Text prompts / message content: Max 50,000 characters.
|
||||
- Titles / Names: Max 100–200 characters.
|
||||
- Pagination limits: Clamped to `1 <= limit <= 50`.
|
||||
- Batch arrays: Clamped to max 100–200 items.
|
||||
- Sanitize entity and path identifiers against path traversal tokens (`../`, `..\\`).
|
||||
|
||||
### Step 2: Four-Pillar Upload Defense
|
||||
When handling file or media uploads:
|
||||
1. **Size Bounds**: Reject payloads exceeding size thresholds (e.g., 100MB for docs; 5MB for images).
|
||||
2. **Blocked Extensions**: Reject executable and script formats (`.exe`, `.bat`, `.sh`, `.svg`, `.html`, `.php`).
|
||||
3. **Magic Byte Inspection**: Inspect file headers to detect disguised binaries (PE `MZ`, ELF, Mach-O).
|
||||
4. **Path Traversal Defense**:
|
||||
- Sanitize original filenames (strip path separators and non-printable characters).
|
||||
- Write files strictly to designated, isolated upload roots with unique IDs (e.g. UUID filenames).
|
||||
|
||||
### Step 3: Outbound SSRF Guard
|
||||
Before executing outbound HTTP requests (scraping, webhooks):
|
||||
- Validate target URLs against an allowlist or safety filter.
|
||||
- Block loopback addresses (`127.0.0.1`, `localhost`, `::1`), RFC 1918 private subnets (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), and cloud metadata services (`169.254.169.254`).
|
||||
- Restrict allowed protocols strictly to `http` and `https`.
|
||||
|
||||
### Step 4: Secret Masking & Error Shielding
|
||||
- Scrub Authorization tokens (`Bearer ***`), provider API keys, and sensitive credentials from logs, database traces, and telemetry.
|
||||
- In public HTTP error responses, return clean structured error objects with opaque error codes; never leak internal filesystem paths, environment variables, or stack traces.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT break local development workflows: allow local mock endpoints and fixture testing in non-production test environments.
|
||||
- Keep security checks non-intrusive during prototyping; enforce strictly at boundaries and pre-release gates.
|
||||
- Avoid noisy confirmation warnings for routine safe operations.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Run verification checks from [references/review-checklist.md](references/review-checklist.md).
|
||||
2. Provide a security verification summary detailing:
|
||||
- Bound clamps applied to route schemas.
|
||||
- Upload filters active (size, extension, magic bytes, safe path).
|
||||
- SSRF protection status on outbound calls.
|
||||
- Secret scrubbing confirmation.
|
||||
Use [the playbook](references/app-hardening-playbook.md) for implementation choices
|
||||
and [the checklist](references/review-checklist.md) for an explicitly requested audit.
|
||||
Local fixtures need deliberate configuration, not an automatic security bypass.
|
||||
@@ -1,160 +1,50 @@
|
||||
# Full-Stack Application Security Hardening Playbook
|
||||
# Boundary hardening choices
|
||||
|
||||
This high-level guide provides a reusable, standardized protocol for auditing and securing full-stack applications (Next.js, Node.js, Express, etc.).
|
||||
Read the relevant section when implementing that boundary. Values and tools come
|
||||
from the product's threat model, stack, and resource budgets, not this document.
|
||||
|
||||
---
|
||||
## Identity and authorization
|
||||
|
||||
## Phase 1: Endpoint & Access Control (Preventing IDOR)
|
||||
Authenticate on the server. Bind private reads and writes to the caller's allowed
|
||||
resources and tenant. Prefer an ownership predicate in the data operation; a
|
||||
separate read-check-write sequence can race. Verify cookie-authenticated mutations
|
||||
have appropriate CSRF/origin protections and session expiry behavior.
|
||||
|
||||
### 1. The Multi-Tenant Ownership Rule
|
||||
Every state-changing API request (`POST`, `PUT`, `PATCH`, `DELETE`) and private resource read (`GET`) must establish identity via the server session—never by trusting client parameters.
|
||||
## Payloads and credentials
|
||||
|
||||
#### Never Trust Client User IDs:
|
||||
```typescript
|
||||
// ❌ Vulnerable (attacker can pass any userId in body)
|
||||
const { title, userId } = await req.json();
|
||||
await db.resource.create({ data: { title, userId } });
|
||||
Validate runtime shapes and bound request bytes, field lengths, array counts, and
|
||||
expensive processing. Reject invalid credentials without silent truncation. Hash
|
||||
passwords with the framework's supported algorithm and settings; bcrypt's 72-byte
|
||||
input limitation is bytes, not characters. Use the selected algorithm's documented
|
||||
limits and preserve long-password support when choosing the design.
|
||||
|
||||
// ✅ Secure (always bind to verified session)
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session?.user?.id) return unauthorized();
|
||||
await db.resource.create({ data: { title, userId: session.user.id } });
|
||||
```
|
||||
## Uploads
|
||||
|
||||
#### Verify Resource Ownership Before Mutation:
|
||||
```typescript
|
||||
// Verify target record exists AND belongs to the caller
|
||||
const item = await db.resource.findUnique({ where: { id } });
|
||||
if (!item) return notFound();
|
||||
if (item.userId !== session.user.id) return forbidden();
|
||||
```
|
||||
Choose an explicit extension/content allowlist and byte cap per supported format.
|
||||
Stop streaming at the cap. Inspect content with a suitable parser; signatures alone
|
||||
cannot validate the whole file. Generate storage IDs; keep the storage root isolated
|
||||
and non-executable, prevent traversal/symlink escapes, and bound archive expansion.
|
||||
Serve active content in an appropriate isolated origin or as an attachment. Apply
|
||||
malware scanning or re-encoding when the threat model warrants it.
|
||||
|
||||
#### Lock Down Sensitive Data Endpoints:
|
||||
* Strip internal data (emails, password hashes, roles, permissions) from public query endpoints.
|
||||
* Never allow query flags like `?includePrivate=true` unless the caller has verified ownership or administrative authorization for that account.
|
||||
## User-influenced outbound requests
|
||||
|
||||
---
|
||||
Prefer service allowlists. Resolve all IPv4/IPv6 addresses and validate the actual
|
||||
connection destination, including DNS changes. Disable redirects or repeat checks
|
||||
for each hop. Bound time, bytes, and egress. Trusted internal service calls use their
|
||||
own allowlist rather than a blanket private-network ban.
|
||||
See [OWASP SSRF guidance](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html).
|
||||
|
||||
## Phase 2: Input Boundaries & Payload Sanitization
|
||||
## Browser and abuse controls
|
||||
|
||||
### 1. Enforce Hard Limits on Every Field
|
||||
Unbounded input strings can cause database exhaustion, buffer overruns, or CPU denial-of-service (e.g., Bcrypt hashing huge strings).
|
||||
Use CSP, framing rules, safe content types, CSRF protection, and rate limiting for
|
||||
the relevant flow. Configure limits by actor, cost, and deployment topology. Apply
|
||||
HSTS only to intended HTTPS domains; subdomains/preload require deliberate coverage.
|
||||
Do not disable required browser capabilities through a blanket Permissions-Policy.
|
||||
|
||||
| Field Type | Recommended Hard Bound | Rationale |
|
||||
| :--- | :--- | :--- |
|
||||
| **Passwords** | Min 8 chars, Max 72–100 chars | Bcrypt truncates or burns excessive CPU beyond 72 bytes |
|
||||
| **Emails** | Max 254 chars | Standard RFC 5321 length; prevents regex DoS |
|
||||
| **Titles / Names** | Max 100–200 chars | Prevents UI overflow and DB memory bloat |
|
||||
| **Descriptions / Content** | Max 2,000–50,000 chars | Prevents payload bombing |
|
||||
| **Pagination limit** | Clamped to `1 <= limit <= 50` | Prevents querying the entire table at once |
|
||||
## Verification
|
||||
|
||||
### 2. JSON & Batch Array Clamping
|
||||
When accepting array batches (e.g., bulk updating nodes or items), enforce an explicit upper limit (e.g., max 200–500 items per request).
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Safe File & Document Upload Architecture
|
||||
|
||||
If an application accepts images, PDFs, or documents, implement the **Four-Pillar Upload Defense**:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["File Upload"] --> B["1. Size Check"]
|
||||
B --> C["2. Extension & MIME Allowlist"]
|
||||
C --> D["3. Magic Bytes Inspection"]
|
||||
D --> E["4. Filename Sanitization & Storage"]
|
||||
```
|
||||
|
||||
### 1. Size Caps:
|
||||
* Check file size before buffering: images (max 2–5MB), documents (max 10MB).
|
||||
* Terminate stream early if incoming chunks exceed the configured byte threshold.
|
||||
|
||||
### 2. Strict MIME & Extension Allowlists:
|
||||
* **Allowed:** `image/jpeg` (`.jpg`, `.jpeg`), `image/png` (`.png`), `image/webp` (`.webp`), `application/pdf` (`.pdf`), `application/json` (`.json`), `text/markdown` (`.md`).
|
||||
* **Strictly Blocked:** `.exe`, `.bat`, `.sh`, `.php`, `.js`, `.html`, `.svg` (SVGs can embed `<script>` tags and execute XSS unless explicitly sanitized).
|
||||
|
||||
### 3. Magic Bytes (Header Signature) Inspection:
|
||||
Do not trust the client `Content-Type` header or file extension alone. Inspect the initial bytes of the file buffer:
|
||||
|
||||
| Format | Magic Bytes Signature | Hex Representation |
|
||||
| :--- | :--- | :--- |
|
||||
| **JPEG** | `\xFF\xD8\xFF` | `FF D8 FF` |
|
||||
| **PNG** | `\x89PNG\r\n\x1a\n` | `89 50 4E 47` |
|
||||
| **WebP** | `RIFF....WEBP` | `52 49 46 46` ('RIFF') |
|
||||
| **PDF** | `%PDF-` | `25 50 44 46` ('%PDF') |
|
||||
|
||||
### 4. Filename Sanitization & Non-Executable Storage:
|
||||
* Strip directory traversal sequences (`../`, `..\\`) and null bytes (`\0`).
|
||||
* Store files using randomized UUIDs/CUIDs (e.g., `clx987654321.png`) rather than the original user-supplied name.
|
||||
* Serve uploaded files with `Content-Disposition: attachment` or host from dedicated static object storage (S3/GCS) where server script execution is disabled.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Rate Limiting & Abuse Prevention
|
||||
|
||||
### Protect Sensitive Action Gates:
|
||||
* **Login attempts:** Max 5–10 per 15 minutes per IP.
|
||||
* **User registrations:** Max 3–5 per hour per IP.
|
||||
* **Password resets:** Max 3 per hour per email/IP.
|
||||
* **General API read/write:** 60–120 requests per minute per authenticated user / IP.
|
||||
|
||||
### Implementation Strategy:
|
||||
* **Single Server / Microservice:** Use an in-memory sliding-window bucket with automatic timestamp cleanup.
|
||||
* **Distributed / Serverless:** Use Redis (e.g., Upstash / Redis token bucket) to share rate limits across multiple instances.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Framework Hardening & HTTP Security Headers
|
||||
|
||||
### 1. Disable Fingerprinting
|
||||
* In `next.config.ts` / `next.config.js`:
|
||||
```typescript
|
||||
const nextConfig = {
|
||||
poweredByHeader: false,
|
||||
};
|
||||
```
|
||||
* In Express:
|
||||
```typescript
|
||||
app.disable('x-powered-by');
|
||||
```
|
||||
|
||||
### 2. Standard Security Headers
|
||||
Inject these headers across all routes (via Next.js `headers()` config, middleware, or reverse proxy):
|
||||
|
||||
```http
|
||||
X-Frame-Options: SAMEORIGIN
|
||||
X-Content-Type-Options: nosniff
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
|
||||
Permissions-Policy: camera=(), microphone=(), geolocation=()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Continuous Dependency & Build Verification
|
||||
|
||||
Establish a 4-step security check before every release:
|
||||
|
||||
### 1. Vulnerability Audit:
|
||||
```bash
|
||||
npm audit
|
||||
# Apply automated non-breaking security fixes:
|
||||
npm audit fix
|
||||
```
|
||||
|
||||
### 2. Static Code & Lint Analysis:
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### 3. Automated Security Unit Tests:
|
||||
Maintain unit tests validating that:
|
||||
* File upload allowlists reject `.exe`, `.html`, `.svg`, and mismatched magic bytes.
|
||||
* Rate limiters trigger HTTP 429 when thresholds are exceeded.
|
||||
* Boundary helpers clamp oversized numbers and truncate/reject excessive payload strings.
|
||||
* Endpoints reject unauthenticated mutations and IDOR resource manipulation.
|
||||
|
||||
### 4. Production Build Verification:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
Test relevant unauthorized and malformed cases. Audit dependencies when dependency
|
||||
risk is part of the task; inspect the result before changing versions. Do not run
|
||||
`npm audit fix` as an automatic audit step or change the user's stack by default.
|
||||
Follow [shared verification](../../../protocols/workflow.md#verification).
|
||||
@@ -1,30 +1,18 @@
|
||||
# Security Review & OWASP Verification Checklist
|
||||
# Optional security audit checklist
|
||||
|
||||
## Input Validation & Boundaries
|
||||
- [ ] Pydantic schemas enforce hard string bounds (max 50,000 for text, max 200 for titles).
|
||||
- [ ] Dynamic path/query identifiers validated via `sanitize_identifier()`.
|
||||
- [ ] Pagination limits clamped to `1 <= limit <= 50`.
|
||||
- [ ] Batch array inputs clamped to safe upper bounds (max 100–200 items).
|
||||
Select checks for the requested surface. Record observed controls and evidence;
|
||||
unchecked items do not automatically become blocking work outside the task.
|
||||
|
||||
## Four-Pillar Upload Defense
|
||||
- [ ] Uploads restricted by `DEFAULT_MAX_FILE_SIZE` (100MB; 5MB for images).
|
||||
- [ ] Blocked executable extensions rejected (`BLOCKED_EXTENSIONS`).
|
||||
- [ ] Extension checked against `ALLOWED_EXTENSIONS`.
|
||||
- [ ] Header magic bytes inspected (`check_magic_bytes`) to block disguised binaries.
|
||||
- [ ] Filenames sanitized with `sanitize_filename()` (path traversal and CLI injection stripped).
|
||||
- [ ] Disk writes resolved strictly via `safe_resolve_path()`.
|
||||
- Runtime input validation and product-specific byte/field/batch limits.
|
||||
- Verified identity and resource/tenant authorization on private reads and writes.
|
||||
- Relevant session, CSRF, and rate-limit behavior.
|
||||
- Upload allowlist, streaming cap, content validation, storage isolation, and safe serving.
|
||||
- User-influenced URL parsing, all-address DNS checks, connection enforcement,
|
||||
IPv4/IPv6 policy, redirect controls, time/byte limits, and egress restrictions.
|
||||
- Credential redaction across logs and telemetry; public errors omit internal traces.
|
||||
- Parameterized values and separately validated dynamic SQL identifiers.
|
||||
- Browser content/framing policies appropriate to the application's actual flows.
|
||||
- Meaningful negative cases for the changed controls, with remaining gaps stated.
|
||||
|
||||
## SSRF Defense
|
||||
- [ ] All outbound requests in research/web-retrieval validated with `validate_safe_url()`.
|
||||
- [ ] Loopback (`127.0.0.1`), private RFC 1918 subnets, and cloud metadata (`169.254.169.254`) blocked.
|
||||
- [ ] Scheme restricted strictly to `http` and `https`.
|
||||
|
||||
## Secrets & Data Hygiene
|
||||
- [ ] Zero API keys, bearer tokens, or password hashes written to `error_log` or logs.
|
||||
- [ ] Authorization headers masked in logging formatters (`Bearer ***`).
|
||||
- [ ] Production error responses mask internal database paths and raw tracebacks.
|
||||
|
||||
## Authorization & State Safety
|
||||
- [ ] Mutations verify that target records match the active session / conversation scope.
|
||||
- [ ] SQLite queries use parameterized SQL; no raw string concatenation.
|
||||
- [ ] Rate limits applied on expensive inference and digestion endpoints.
|
||||
Helper names and constants follow the existing project. No particular framework,
|
||||
file cap, pagination limit, or security helper is required by this checklist.
|
||||
+18
-71
@@ -1,78 +1,25 @@
|
||||
---
|
||||
name: backprop
|
||||
description: >
|
||||
Bug-to-spec feedback loop: when a bug occurs or test fails, traces root cause,
|
||||
adds an invariant (§V) to prevent recurrence, logs to §B, and binds a regression test.
|
||||
Use on test failure during build, user bug report, post-mortem, or when asked to "backprop".
|
||||
concerns: [system-one-balance]
|
||||
Record a meaningful behavioral bug and its prevention in an existing SPEC.md when using the spec workflow or explicitly asked to backprop. Use ordinary debugging for bugs in projects without a spec.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Backprop — Bug → Spec Feedback Loop
|
||||
# Bug feedback
|
||||
|
||||
Plan-then-execute fixes the code and forgets.
|
||||
Spec-Driven Development fixes the code AND amends the spec so recurrence is impossible.
|
||||
That feedback loop is **backprop**.
|
||||
1. Establish expected behavior and reproduce or otherwise demonstrate the failure.
|
||||
Inspect the cause; use focused debugging probes instead of speculative fixes.
|
||||
2. If `SPEC.md` exists, append a concise §B record. Add or amend a §V invariant
|
||||
only when it expresses a useful behavioral rule not already covered. Preserve
|
||||
monotonically numbered IDs and relevant interface/task references.
|
||||
3. Add regression coverage for the meaningful failure when practical, then apply
|
||||
the smallest fix. For non-automatable failures, preserve reproduction steps and
|
||||
the evidence instead of inventing a test.
|
||||
4. Run the relevant checks under [shared verification](../../protocols/workflow.md#verification).
|
||||
Report the cause, fix, and evidence.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Governing Invariants**:
|
||||
- Every bug gets a row in the §B table of `SPEC.md`.
|
||||
- Behavioral bugs should be paired with a new §V invariant whenever a rule can prevent recurrence.
|
||||
- A new invariant without an automated test is incomplete: always pin with a test citing the invariant.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Parse the failure input: test failure traceback, reproduction log, or user bug report.
|
||||
2. Confirm `SPEC.md` exists; if absent, invoke `spec distill` or create it before logging.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Trace Root Cause
|
||||
- Locate the exact file and line producing the incorrect behavior.
|
||||
- State the root cause in one crisp Caveman sentence.
|
||||
|
||||
### Step 2: Invariant Formulation
|
||||
Evaluate:
|
||||
- Would a testable §V invariant prevent this entire class of bug? (Commonly yes).
|
||||
- Did the interface definition (§I) promise a shape the code cannot deliver?
|
||||
- Was a task (§T) misunderstood or incomplete?
|
||||
|
||||
Draft the proposed additions:
|
||||
```text
|
||||
§B row: B<next>|<date>|<root cause>|V<N>
|
||||
§V line: V<next>: <testable rule that would have caught it>
|
||||
```
|
||||
|
||||
### Step 3: Pin Reproduction Test
|
||||
- Author a failing regression test before modifying application code.
|
||||
- Name the test to cite the invariant: e.g. `test_v7_refund_idempotent()`.
|
||||
|
||||
### Step 4: Implement Fix & Verify
|
||||
- Apply minimal surgical code fix.
|
||||
- Run the regression test to confirm green.
|
||||
- Run the full project test suite to verify no collateral regressions.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT invent artificial §V rules for one-off typos or transient external network outages (log in §B, but skip §V).
|
||||
- State invariants positively where possible (`! hold` rather than complex negative conditionals).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Every complete backprop run produces:
|
||||
1. Append to §B table in `SPEC.md`.
|
||||
2. Append to §V invariants (when applicable).
|
||||
3. Passing regression test.
|
||||
4. Minimal code fix.
|
||||
5. Atomic git commit: `backprop §B.<n> + §V.<N>: <one-line cause>`.
|
||||
`backprop` owns §B and bug-related §V amendments. Use `spec` for changes to goals,
|
||||
constraints, or interfaces. Do not create or distill a spec as a prerequisite to a
|
||||
bug fix. If explicitly requested without a spec, provide the feedback record with
|
||||
the fix and explain that no spec was updated. Typos and transient outages need no
|
||||
new invariant, regression test, or mandatory commit.
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: benchmark-refactor
|
||||
description: >
|
||||
Measure baselines, evaluate optimization candidates in isolated branches, and record MADRs for performance-critical refactoring.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Benchmark-driven refactoring
|
||||
|
||||
**"The model proposes, but the engine measures."**
|
||||
Optimization and refactoring must never rely on theoretical claims or synthetic
|
||||
unit test speedups. Every performance-critical change must be empirically proven
|
||||
against a deterministic baseline.
|
||||
|
||||
## 4-Phase refactoring workflow
|
||||
|
||||
### 1. Baseline profiling
|
||||
Before altering any production code, establish and record the empirical baseline:
|
||||
1. Select the profiling harness appropriate for the stack:
|
||||
- Python: `pytest-benchmark`
|
||||
- Rust: `Criterion.rs`
|
||||
- CLI / Compiled binaries: `hyperfine`
|
||||
- C / C++: `google/benchmark`
|
||||
2. Run the suite under clean conditions to capture mean execution duration ($\mu$),
|
||||
standard deviation ($\sigma$), memory overhead, and throughput.
|
||||
3. Export the baseline as a machine-readable JSON artifact (e.g. `benchmark-baseline.json`).
|
||||
|
||||
### 2. Hypothesis & candidate generation
|
||||
1. Formulate 2–3 discrete optimization strategies (e.g. vectorization, streaming iterators,
|
||||
in-memory caching).
|
||||
2. Implement each candidate in an isolated Git worktree or ephemeral branch
|
||||
(`candidate-a`, `candidate-b`). Do not mutate the baseline tree.
|
||||
|
||||
### 3. Differential benchmarking & elimination
|
||||
1. Execute the benchmark suite against each candidate under identical conditions.
|
||||
2. Apply strict statistical thresholds:
|
||||
- Candidate is valid only if it demonstrates statistically significant gain
|
||||
($p < 0.01$ and $\ge 15\%$ improvement in throughput or latency).
|
||||
- Zero regression across all unit, integration, and type checks.
|
||||
3. Immediately eliminate and hard-reset candidates that fail tests or fall below
|
||||
the performance threshold.
|
||||
4. Select the winning candidate balancing performance gain against code complexity.
|
||||
|
||||
### 4. Automated Architecture Decision Record (MADR)
|
||||
Refactoring without documentation produces code that future agents will revert.
|
||||
Formalize the decision by generating a Markdown Architectural Decision Record in
|
||||
`docs/adr/NNNN-[slug].md` using [the MADR template](references/madr-template.md).
|
||||
Commit the MADR alongside the refactored code and benchmark JSON outputs.
|
||||
Follow [shared verification](../../protocols/workflow.md#verification).
|
||||
@@ -0,0 +1,45 @@
|
||||
# Markdown Architectural Decision Record (MADR) Template
|
||||
|
||||
Save approved architectural and refactoring decisions to `docs/adr/NNNN-[slug].md`.
|
||||
|
||||
```markdown
|
||||
# ADR-[NNNN]: [Short Title of Architectural Decision]
|
||||
|
||||
## Status
|
||||
[Proposed | Accepted | Superseded | Deprecated]
|
||||
|
||||
## Context and Problem Statement
|
||||
[Describe the context, performance bottleneck, or structural limitation prompting this decision.]
|
||||
|
||||
## Decision Drivers
|
||||
- [Driver 1, e.g. Throughput requirement: sustain >= 25,000 events/sec]
|
||||
- [Driver 2, e.g. Latency target: maintain p99 < 15ms]
|
||||
- [Driver 3, e.g. Interface stability: zero breaking changes to public API]
|
||||
- [Driver 4, e.g. Regression safety: zero test or type check regressions]
|
||||
|
||||
## Considered Options
|
||||
- **Option 1**: [Short description of candidate A]
|
||||
- **Option 2**: [Short description of candidate B]
|
||||
- **Option 3**: [Short description of candidate C]
|
||||
|
||||
## Decision Outcome
|
||||
Chosen Option: [Option X], because [justification based on empirical benchmark results and complexity balance].
|
||||
|
||||
## Empirical Benchmark Outcomes
|
||||
- **Baseline Execution**:
|
||||
$\mu = XX.X\text{ms} \pm X.X\text{ms}$ (Throughput: $XX,\!XXX\text{ ops/sec}$)
|
||||
- **Option 1 Benchmark**:
|
||||
$\mu = XX.X\text{ms} \pm X.X\text{ms}$ ($+XX\%$ improvement; [reason if rejected])
|
||||
- **Option 2 Benchmark**:
|
||||
$\mu = XX.X\text{ms} \pm X.X\text{ms}$ ($+XX\%$ improvement, $p < 0.001$; [selected])
|
||||
- **Option 3 Benchmark**:
|
||||
[Eliminated due to test failure or infrastructure complexity]
|
||||
|
||||
## Positive Consequences
|
||||
- [Positive consequence 1]
|
||||
- [Positive consequence 2]
|
||||
|
||||
## Negative Consequences & Accepted Trade-offs
|
||||
- [Negative consequence 1, e.g. Added dependency]
|
||||
- [Negative consequence 2, e.g. Increased algorithmic complexity]
|
||||
```
|
||||
+23
-69
@@ -1,77 +1,31 @@
|
||||
---
|
||||
name: build
|
||||
description: >
|
||||
Plan-then-execute implementation loop against SPEC.md tasks. Operates single-threaded on main agent thread.
|
||||
Executes tasks in order, runs verification tests as external oracles, and triggers backprop on failure.
|
||||
Use when asked to "build", "implement spec", "build §T.n", "build next task", or "run the build".
|
||||
concerns: [system-one-balance]
|
||||
Implement tasks from an existing SPEC.md when asked to implement the spec, build a named spec task, or continue the spec workflow. Ordinary compiler/build commands do not activate this skill.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Build — Implement Spec
|
||||
# Build spec tasks
|
||||
|
||||
Single-threaded native plan → execute loop against `SPEC.md`.
|
||||
Use this workflow only when the project has adopted `SPEC.md`. An ordinary feature
|
||||
or bug fix does not require creating one. Follow [shared verification](../../protocols/workflow.md#verification).
|
||||
|
||||
---
|
||||
1. Read the selected tasks and their relevant constraints, interfaces, invariants,
|
||||
and research. Treat sourced findings as evidence; recheck them if stale or
|
||||
contradicted by current code.
|
||||
2. Select the named task, the first pending/in-progress task for `--next`, or all
|
||||
unfinished tasks for `--all` or a request to implement the whole spec.
|
||||
3. Inspect touched code and choose a concrete completion check. For changes to
|
||||
auth, payments, shared contracts, or migrations, inspect the risks and existing
|
||||
review findings; perform a focused review yourself if needed without making
|
||||
the user launch another skill.
|
||||
4. Mark the selected task `~`, implement it, and verify the requested behavior.
|
||||
Mark it `x` only when the evidence supports completion. Leave incomplete tasks
|
||||
unfinished and explain any limitations.
|
||||
5. On failure, inspect the cause before changing anything else. Fix task defects
|
||||
directly. Use `backprop` for a meaningful spec gap or recurring behavioral bug;
|
||||
do not create invariants for ordinary intermediate mistakes.
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Verify Prerequisites**:
|
||||
- `SPEC.md` must exist at the project root. If absent, defer to `spec` to author it first.
|
||||
- Read §R if present: external facts the build must honor, never contradict or re-derive.
|
||||
- For high-blast-radius changes (shared modules, auth, payments, database migrations), confirm `/review` has run.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Parse invocation arguments:
|
||||
- `§T.n`: Target specific task row.
|
||||
- `--next`: Target the lowest-numbered row with status `.` or `~`.
|
||||
- `--all` (or empty): Execute every pending `.` row in sequential order.
|
||||
2. Confirm verification oracle:
|
||||
- Identify the exact automated command (e.g. `pytest`, `cargo test`, `npm test`) that verifies completion.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Plan Task Implementation
|
||||
For the chosen task(s):
|
||||
1. Cite every §V invariant that applies; the implementation must satisfy all.
|
||||
2. Cite every §I interface touched; preserve specified signatures and shapes.
|
||||
3. List files to create or modify.
|
||||
4. Establish the verification contract: specify which concrete test will prove each §V touched.
|
||||
|
||||
### Step 2: Sequential Execution
|
||||
For each task in order:
|
||||
1. Flip `§T.n` status cell from `.` → `~` in `SPEC.md`.
|
||||
2. Edit code according to plan.
|
||||
3. Run the verification command.
|
||||
4. **Pass**: Flip `~` → `x` in `SPEC.md`. Create atomic commit: `T<n>: <task description>`.
|
||||
5. **Fail**: Do NOT retry blindly; route to Failure Recovery.
|
||||
|
||||
### Step 3: Failure Recovery & Backprop
|
||||
When a verification test fails:
|
||||
1. Inspect failure output.
|
||||
2. Determine failure classification:
|
||||
- **Code defect in task**: Fix code and re-test.
|
||||
- **Spec defect or unhandled edge case**: Invoke `backprop` with `bug: <cause>` to record in §B and draft §V before resuming.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Keep execution single-threaded on the main agent; avoid uncoordinated background subagent sprawl.
|
||||
- Flip only §T status cells in `SPEC.md` during build; leave architectural changes to `spec`.
|
||||
- Avoid speculative work beyond the assigned task.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
A task is verified as complete (`x`) only when:
|
||||
1. The verification command exits with code 0.
|
||||
2. Every §V touched has an automated passing test.
|
||||
3. Full test suite passes with zero regressions.
|
||||
4. `SPEC.md` reflects current completion state.
|
||||
`build` owns task status cells. Architectural or scope changes belong to `spec`;
|
||||
perform a targeted amendment within the authorized task when required. Continue
|
||||
in task order; do not impose commits or a full-suite run after every row.
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
name: cad-3d-print
|
||||
description: >
|
||||
Design, generate, and verify parametric 3D models for 3D printing using code-first CAD (OpenSCAD, build123d).
|
||||
scope: global
|
||||
---
|
||||
|
||||
# CAD 3D Print
|
||||
|
||||
Design, generate, and empirically verify 3D-printable parts using programmatic CAD.
|
||||
Follow the [shared workflow](../../protocols/workflow.md).
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Dimensional Budgeting & Tolerances**
|
||||
- Establish bounding box, mounting points, and mating interfaces from user specifications.
|
||||
- Apply standard FDM 3D printing tolerances:
|
||||
- **Horizontal hole clearance:** Add `+0.2 mm` to `+0.3 mm` for screw pass-through (e.g. M3 hole diameter = `3.2 mm`; tap hole = `2.9 mm`).
|
||||
- **Fit clearances:** Snug/snap fit `0.15 mm`; sliding fit `0.3 mm`; loose/hinged fit `0.4–0.5 mm`.
|
||||
- **Wall thickness:** Multiples of nozzle width (minimum `1.2 mm` for 0.4 mm nozzles).
|
||||
- **Bed contact:** Add 45° chamfers to bottom edges touching the build plate to prevent "elephant's foot" binding.
|
||||
- **Overhangs:** Keep unassisted overhangs $\le 45^\circ$ to minimize support material.
|
||||
|
||||
2. **Parametric Script Generation**
|
||||
- Author a standalone, self-documenting OpenSCAD (`.scad`) script:
|
||||
- Place all customizable dimensions at the top as labeled parametric variables.
|
||||
- Set curvature resolution: `$fn = 60;` or `$fs = 0.5; $fa = 5;` for smooth circular features.
|
||||
- Use Constructive Solid Geometry (CSG): `union()`, `difference()`, `intersection()`, `hull()`.
|
||||
- Prevent non-manifold coincident faces (Z-fighting): always extend cutting bodies slightly beyond the target surface (e.g., `translate([0, 0, -0.1]) cylinder(h = height + 0.2, ...)`).
|
||||
|
||||
3. **Empirical Verification**
|
||||
- **Compile STL mesh:**
|
||||
```bash
|
||||
openscad -o model.stl model.scad
|
||||
```
|
||||
Inspect compiler output to ensure `Simple: yes` (a manifold, watertight solid).
|
||||
- **Render visual preview:**
|
||||
```bash
|
||||
openscad --render --imgsize=800,600 -o preview.png model.scad
|
||||
```
|
||||
- Verify the rendered image to check geometry, clearances, and aesthetic proportions.
|
||||
|
||||
4. **Handoff Artifacts**
|
||||
- Keep the editable `.scad` source in the workspace.
|
||||
- Provide the compiled `.stl` or `.3mf` for slicing (PrusaSlicer, Bambu Studio, OrcaSlicer).
|
||||
- Embed or link the rendered `.png` preview.
|
||||
+20
-87
@@ -1,100 +1,33 @@
|
||||
---
|
||||
name: caveman
|
||||
description: >
|
||||
Token-compression encoding dialect for SPEC.md and spec-adjacent writes (~75% reduction vs prose).
|
||||
Preserves code identifiers and invariants verbatim while dropping filler and using formal symbols.
|
||||
Use when writing or editing SPEC.md, when asked to "caveman", "compress this", or "be brief".
|
||||
concerns: [system-one-balance]
|
||||
Use compact Caveman notation when explicitly requested, or when editing a spec that already adopts that notation. Ordinary requests to be brief use plain English.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Caveman — Spec Encoding
|
||||
# Compact spec notation
|
||||
|
||||
Applies to `SPEC.md` writes, spec-referencing text, and backprop entries.
|
||||
Does NOT apply to code, error strings, commit messages, or PR descriptions.
|
||||
Keep technical statements concise without losing conditions, scope, uncertainty,
|
||||
or modality. Preserve code, identifiers, paths, URLs, versions, numbers, quoted
|
||||
strings, and data formats verbatim. Plain English is preferable when symbols make
|
||||
a statement ambiguous; notation does not determine SPEC.md ownership.
|
||||
|
||||
---
|
||||
- `→` leads to/becomes; `∀` every; `∃` exists.
|
||||
- `!` required; `⊥` forbidden; `?` unknown.
|
||||
- `≤`, `≥`, `≠`, `∈`, `∉` retain mathematical meanings.
|
||||
- Write optional behavior and missing values (`null`, `nil`) explicitly; do not
|
||||
overload unknown/forbidden symbols with those meanings.
|
||||
- Remove filler and unnecessary articles. Retain negation, quantifiers, honest
|
||||
hedges, exception conditions, and words needed to distinguish implement from fix.
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
Examples:
|
||||
|
||||
1. **Grammar Invariants**:
|
||||
- Drop articles (a, an, the).
|
||||
- Drop filler (just, really, basically, simply, actually).
|
||||
- Drop auxiliary verbs where fragments work (is, are, was, were, being).
|
||||
- Drop pleasantries and hedging ("might", "perhaps", "could be worth").
|
||||
- Short synonyms: fix > implement, big > extensive, run > execute.
|
||||
2. **Symbol Table**:
|
||||
- `→` leads to / becomes / on `<x>`
|
||||
- `∴` therefore / fix
|
||||
- `∀` for all / every
|
||||
- `∃` exists / some
|
||||
- `!` must / required
|
||||
- `?` may / optional / unknown
|
||||
- `⊥` never / forbidden / nil
|
||||
- `≠` not equal
|
||||
- `∈` in, `∉` not in
|
||||
- `≤` at most, `≥` at least
|
||||
- `&` and, `|` or
|
||||
- `§` section reference
|
||||
3. **Preserve Verbatim**:
|
||||
- Never compress code blocks, paths (`src/auth/mw.go`), URLs, identifiers (`function_name`), numbers/versions, error strings, SQL/JSON/YAML, or quoted strings.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Confirm target document: `SPEC.md` section, backprop row, or prompt.
|
||||
2. Verify target is spec or technical invariant, NOT human prose, code, or commit messages.
|
||||
3. If user asks for prose explanation, switch to standard English.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
Encode into canonical Caveman shapes:
|
||||
|
||||
### 1. Invariant (§V)
|
||||
```text
|
||||
V<n>: <subject> <relation> <condition>
|
||||
V1: ∀ req → auth check before handler
|
||||
V2: token expiry ≤ current_time → reject
|
||||
api: POST /x → 201 {id:string}
|
||||
T3|~|add auth middleware|V1,I.api
|
||||
```
|
||||
|
||||
### 2. Bug Row (§B pipe table)
|
||||
```text
|
||||
id|date|cause|fix
|
||||
B1|2026-04-20|token `<` not `≤`|V2
|
||||
```
|
||||
|
||||
### 3. Task Row (§T pipe table)
|
||||
```text
|
||||
id|status|task|cites
|
||||
T3|x|add auth mw|V1,I.api
|
||||
```
|
||||
*Status: `x` done, `~` wip, `.` todo. Escape literal `|` as `\|`.*
|
||||
|
||||
### 4. Interface (§I)
|
||||
```text
|
||||
<kind>: <name> → <shape>
|
||||
api: POST /x → 200 {id:string}
|
||||
cmd: `foo bar <arg>` → stdout JSON
|
||||
env: FOO_KEY ! set
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Compression, Not Amputation**:
|
||||
- If cutting a word loses an invariant or factual boundary, keep the word.
|
||||
- Never sacrifice precision for token brevity.
|
||||
- Fail open to standard English when ambiguous.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Output compressed text in valid Markdown.
|
||||
2. Verify:
|
||||
- All code tokens, identifiers, and paths are intact.
|
||||
- All symbols use standard UTF-8 characters (`→`, `∀`, `⊥`, `!`).
|
||||
- Pipe tables parse cleanly with balanced delimiters.
|
||||
Use the project's table format and escape literal pipes as needed. Verify that a
|
||||
reader can recover the exact behavioral claim; no token-reduction target, special
|
||||
scan, or automatic compression of human-facing reports is required.
|
||||
+14
-91
@@ -1,98 +1,21 @@
|
||||
---
|
||||
name: check
|
||||
description: >
|
||||
Read-only drift detector comparing SPEC.md against current codebase.
|
||||
Audits invariants (§V), interface shapes (§I), and task completion (§T), reporting violations with file:line citations.
|
||||
Use when asked to "check drift", "audit spec", "spec vs code", or before releasing.
|
||||
concerns: [system-one-balance]
|
||||
Audit an existing SPEC.md against code when asked to check drift, audit the spec, or compare spec versus implementation.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Check — Drift Detector
|
||||
# Spec drift audit
|
||||
|
||||
Pure diagnostic audit. Reports violations and interface drift. Strictly read-only; writes nothing.
|
||||
Read-only: inspect files and available evidence; do not edit, sync, or commit.
|
||||
If no `SPEC.md` exists, report that fact without creating one.
|
||||
|
||||
Spec drifting silently from code is the primary failure mode of long-lived projects. `check` catches drift before it becomes production defects.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Non-Negotiable Invariants**:
|
||||
- **Zero Writes**: Never edit code or `SPEC.md`. Report findings only.
|
||||
- Every violation must cite `file:line` evidence.
|
||||
- If `SPEC.md` is absent at repo root, report "no spec found" and exit.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Ingest `SPEC.md` from the project root.
|
||||
2. Parse audit scope from arguments:
|
||||
- `§V`: Audit invariants only (default).
|
||||
- `§I`: Audit external interfaces only.
|
||||
- `§T`: Audit task status against reality.
|
||||
- `--all` (or empty): Audit all three sections.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Audit Invariants (§V)
|
||||
For each `V<n>` invariant:
|
||||
1. Translate invariant into a verifiable assertion about code.
|
||||
2. Search and inspect corresponding files.
|
||||
3. Classify state:
|
||||
- **HOLD**: Invariant actively satisfied with test or code assertion.
|
||||
- **VIOLATE**: Invariant actively violated in implementation.
|
||||
- **UNVERIFIABLE**: Invariant has no corresponding automated test or code guard.
|
||||
|
||||
### Step 2: Audit Interfaces (§I)
|
||||
For each interface defined in §I:
|
||||
1. Locate implementation in routes, CLI, or exported functions.
|
||||
2. Classify state:
|
||||
- **MATCH**: Code shape matches §I specification exactly.
|
||||
- **DRIFT**: Implementation exists but signatures, parameters, or return types diverge.
|
||||
- **MISSING**: Interface declared in spec but absent from code.
|
||||
- **EXTRA**: Code exposes public endpoints/flags not documented in §I.
|
||||
|
||||
### Step 3: Audit Tasks (§T)
|
||||
For each `T<n>` row:
|
||||
1. If status is `x`: verify claimed files/tests exist in git. If absent, flag **STALE**.
|
||||
2. If status is `~`: note as in-progress.
|
||||
3. If status is `.`: note as pending.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Report findings concisely without lecturing or auto-triggering refactors.
|
||||
- Provide actionable remedy hints for each class of drift, leaving decisions to the user.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Emit the structured Caveman drift report:
|
||||
|
||||
```markdown
|
||||
## Drift Report
|
||||
|
||||
### §V Invariants
|
||||
- V2 VIOLATE: src/auth/mw.ts:47 uses `<` instead of `≤`.
|
||||
- V5 UNVERIFIABLE: no test covers concurrent refund boundary.
|
||||
|
||||
### §I Interfaces
|
||||
- I.api DRIFT: POST /v1/charge returns `{result}` instead of `{id}`. routes/charge.py:82.
|
||||
- I.cmd MISSING: `limiter bench` absent from CLI definitions.
|
||||
|
||||
### §T Tasks
|
||||
- T3 STALE: marked `x` but auth middleware file not found in tree.
|
||||
|
||||
### Summary
|
||||
- X violations, Y drifts, Z missing, W stale.
|
||||
- **Remedy Hints**:
|
||||
- VIOLATE / DRIFT: Invoke `spec` with `bug: <V.n>` or fix code at cited lines.
|
||||
- MISSING: Invoke `build §T.n` or `spec amend §T`.
|
||||
- STALE: Invoke `spec amend §T` to reset status.
|
||||
```
|
||||
1. Read the requested sections; default to §V, §I, and §T.
|
||||
2. For invariants, distinguish supported behavior, demonstrated violations, and
|
||||
missing evidence. A test's presence alone does not prove an invariant holds.
|
||||
3. Compare public interfaces with implementations and callers; identify missing,
|
||||
extra, or changed contracts with file/line evidence.
|
||||
4. Check task completion against the promised behavior, rather than only whether
|
||||
named files exist. Report incomplete or stale statuses.
|
||||
5. Give concise findings, evidence, and useful remedies. Do not launch refactors,
|
||||
impose release gates, or run test commands that would violate read-only scope.
|
||||
@@ -1,91 +1,31 @@
|
||||
---
|
||||
name: database-design
|
||||
description: >
|
||||
Designs high-performance relational schemas, SQLite WAL storage, repository data access patterns,
|
||||
composite indexing, and entity models. Use when creating or modifying database tables, defining entity models,
|
||||
optimizing query performance, or planning migrations.
|
||||
concerns: [system-one-balance]
|
||||
Design schemas, migrations, and queries or diagnose query performance using the project database and measured workload.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Database Design & Storage Architecture
|
||||
# Database design
|
||||
|
||||
Governs persistence, entity modeling, and high-concurrency relational/SQLite storage patterns across backend projects.
|
||||
1. Inspect the engine/version, existing models, migration tooling, queries, expected
|
||||
volume, concurrency, and durability requirements.
|
||||
2. Define keys, constraints, relationships, deletion behavior, and transaction
|
||||
boundaries. Bind values using driver parameters; validate dynamic identifiers
|
||||
separately. Keep consistency-sensitive checks and writes in one transaction.
|
||||
3. Design indexes around actual filters, joins, and ordering; inspect query plans
|
||||
when optimizing. Cardinality alone does not determine whether an index helps.
|
||||
4. Bound interactive list queries using product-appropriate limits. Use stable
|
||||
keyset ordering for deep pagination; exports and internal batch jobs may stream
|
||||
larger datasets. Do not impose pagination on every query.
|
||||
5. Use the existing migration mechanism and plan data/backward compatibility.
|
||||
Verify affected reads, constraints, and migration behavior under
|
||||
[shared verification](../../protocols/workflow.md#verification).
|
||||
|
||||
---
|
||||
## SQLite when applicable
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Storage Invariants**:
|
||||
- **SQLite WAL Mode**: Always enable Write-Ahead Logging (`PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL;`) for concurrent read/write throughput.
|
||||
- **Connection Scoping**: Thread-safety and connection pooling must be explicit. Never share open database cursor connections across concurrent threads or asynchronous tasks.
|
||||
- **Minimal Transaction Footprint**: Prepare data and run validation *before* opening a transaction. Commit writes swiftly to minimize table/row lock contention.
|
||||
- **Entity Separation**: Keep domain entities (dataclasses, Pydantic models) decoupled from low-level SQL row drivers. Repositories map raw rows to domain objects.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Model Requirements**:
|
||||
- Identify entities, relations (1:1, 1:N, N:M), cascade behaviors, and foreign key constraints.
|
||||
- Determine write concurrency levels and access patterns (read-heavy vs. write-intensive).
|
||||
- Identify query filter combinations to determine mandatory indexing.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Entity Definition
|
||||
Define pure domain entities decoupled from SQL execution:
|
||||
```python
|
||||
@dataclass
|
||||
class UserSession:
|
||||
id: str
|
||||
user_id: str
|
||||
token_hash: str
|
||||
created_at: datetime
|
||||
expires_at: datetime
|
||||
```
|
||||
|
||||
### Step 2: DDL & Migration Schema
|
||||
Author DDL with strict types, primary keys, and foreign keys:
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS user_sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
token_hash TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
expires_at TEXT NOT NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
```
|
||||
|
||||
### Step 3: Composite Indexing
|
||||
Create composite indexes on high-cardinality filters and join columns:
|
||||
```sql
|
||||
CREATE INDEX IF NOT EXISTS idx_user_sessions_user_expires
|
||||
ON user_sessions (user_id, expires_at);
|
||||
```
|
||||
|
||||
### Step 4: Query Optimization & Pagination
|
||||
- **Parameterized SQL**: Always bind query parameters with `:named` or `?` syntax. String interpolation or raw concatenation in SQL statements is strictly prohibited.
|
||||
- **Clamped Limits**: Never execute unbounded `SELECT *` queries. Enforce default limits (`1 <= limit <= 50`).
|
||||
- **Keyset Pagination**: For deep feeds or log tables, prefer keyset pagination (`WHERE id > :last_id ORDER BY id ASC LIMIT :limit`) over high-offset scans (`OFFSET 10000`) which cause linear disk scans in relational engines.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Keep migration scripts straightforward and forward-compatible.
|
||||
- Do NOT create premature indexes on low-cardinality flags (e.g. `is_active` boolean columns) where table scans are faster.
|
||||
- Choose the simplest storage architecture that satisfies requirements (e.g. SQLite WAL is sufficient for thousands of writes/sec without external DBMS overhead).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Verify:
|
||||
- Foreign key constraints enabled (`PRAGMA foreign_keys=ON;`).
|
||||
- All parameters sanitized via parameterized queries.
|
||||
- Composite indexes cover common query filters and sorting keys.
|
||||
2. Deliver the entity definition, DDL schema, repository access methods, and migration step.
|
||||
WAL can improve concurrent reads/writes on supported local storage; it is not a
|
||||
universal engine choice or a promise of a particular write rate. Choose `FULL` for
|
||||
power-loss durability, or `NORMAL` only when its durability tradeoff is acceptable.
|
||||
Enable foreign keys per connection, use explicit connection lifetimes, and choose
|
||||
busy handling/checkpoint behavior for the workload. Consult the installed version's
|
||||
[pragma documentation](https://www.sqlite.org/pragma.html) for exact semantics.
|
||||
@@ -1,79 +1,21 @@
|
||||
---
|
||||
name: debugging-workflow
|
||||
description: >
|
||||
Systematic, hypothesis-driven debugging workflow: reproduction, isolation, root cause identification,
|
||||
surgical fixes, and regression prevention. Use when diagnosing bugs, unexpected runtime errors,
|
||||
failing tests, or when asked to debug an issue.
|
||||
concerns: [system-one-balance]
|
||||
Diagnose and fix unexpected behavior, runtime errors, or failing checks when asked to debug or repair an issue.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Debugging Workflow
|
||||
# Debugging
|
||||
|
||||
A systematic, disciplined protocol for finding and fixing software bugs efficiently without guessing or introducing collateral regressions.
|
||||
1. Establish expected versus actual behavior from existing errors, logs, and code.
|
||||
Build a small reproduction when useful; do not ask for information already given.
|
||||
2. Rank plausible causes and choose a focused probe that distinguishes them.
|
||||
Inspect boundary inputs, recent relevant diffs, or execution state as needed.
|
||||
3. Fix the demonstrated cause with a small change. Stop blind retry loops and
|
||||
avoid broad refactoring while resolving a bug.
|
||||
4. Add regression coverage for meaningful behavioral failures when practical.
|
||||
Use [shared verification](../../protocols/workflow.md#verification) to choose checks.
|
||||
5. Report the cause, changed behavior, evidence, and any remaining uncertainty.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Invariants:
|
||||
- Never apply random fixes hoping one works. Every fix must be preceded by an identified root cause.
|
||||
- Prefer minimal surgical edits over wide refactors during bug resolution.
|
||||
- Every resolved bug should ideally be pinned with a reproduction test.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Information Gathering**:
|
||||
- Inspect the verbatim error message, stack trace, and relevant log streams.
|
||||
- Identify the exact file and line where failure manifests.
|
||||
- Record the expected vs. actual behavior and environmental conditions.
|
||||
2. **Reproduction & Isolation**:
|
||||
- Determine whether the bug is reliably reproducible.
|
||||
- Construct a minimal reproduction case or failing test.
|
||||
- Identify recent changes: review `git diff HEAD~5..HEAD` or recent commits if the issue is a regression.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Formulate and Rank Hypotheses
|
||||
Classify the issue into primary failure categories:
|
||||
- **Logic Errors**: Off-by-one, inversion of boolean operators, missing edge cases.
|
||||
- **Data Errors**: Null/undefined references, schema divergence, malformed encodings.
|
||||
- **State & Concurrency**: Race conditions, stale cache, incomplete state mutation.
|
||||
- **Integration Errors**: API contract drift, network timeouts, environment configuration.
|
||||
|
||||
Formulate the most probable hypothesis and design a quick diagnostic probe to validate or falsify it.
|
||||
|
||||
### Step 2: Diagnostic Probing
|
||||
- Add focused diagnostic logging or evaluate intermediate states.
|
||||
- Use binary search / bisection when isolating faults in large code paths.
|
||||
- Check assumptions at subsystem boundaries: inspect inputs immediately before and outputs immediately after the failure site.
|
||||
|
||||
### Step 3: Implement Minimal Surgical Fix
|
||||
- Address the underlying defect rather than masking the symptom (e.g. don't simply wrap with a silent `try/catch` or null check if an invariant was violated upstream).
|
||||
- Keep changes minimal and localized to the responsible subsystem.
|
||||
|
||||
### Step 4: Regression Defense
|
||||
- Execute test suites to confirm no existing functionality broke.
|
||||
- Add or update an automated unit/integration test capturing the failure condition.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- If full stack trace and error context are already visible in the conversation, do NOT ask the user redundant intake questions ("Can you provide the logs?"). Proceed directly to diagnosis.
|
||||
- Do NOT rewrite unrelated modules or refactor working code while fixing a bug.
|
||||
- Fix fast; reserve deep architectural audits for dedicated refactoring passes.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Deliver the debugging report with:
|
||||
1. **Root Cause**: Crisp explanation of why the failure occurred.
|
||||
2. **Surgical Diff**: The exact code changes applied.
|
||||
3. **Verification**: Command executed or test output demonstrating the fix.
|
||||
4. **Prevention**: Regression test added to guard against recurrence.
|
||||
Use `backprop` only when an existing spec needs a bug record or invariant update.
|
||||
No spec creation, mandatory full suite, or separate review is required for a routine fix.
|
||||
+15
-71
@@ -1,78 +1,22 @@
|
||||
---
|
||||
name: deepen
|
||||
description: >
|
||||
Codebase design improvement pass that finds shallow modules, shrinks interfaces, and pulls complexity down.
|
||||
Hides decisions behind clean boundaries with behavior held constant and full test suite green.
|
||||
Use when asked to "deepen this", "improve design", "module feels shallow", or "pull complexity down".
|
||||
concerns: [system-one-balance]
|
||||
Simplify module interfaces while preserving behavior when asked to deepen modules, improve their design, or hide leaked implementation decisions.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Deepen — Make Modules Deep
|
||||
# Deepen a module
|
||||
|
||||
**Behavior is sacred**: tests must be green before AND after. Every change shrinks an interface surface or hides a private decision. Deepen, don't churn.
|
||||
1. Inspect the target module, callers, and existing behavior checks. Identify the
|
||||
concrete complexity exposed to callers with file/line evidence.
|
||||
2. Choose the smallest interface improvement that hides a real decision. Keep
|
||||
existing behavior and contracts unless the user authorized changing them.
|
||||
3. Refactor the selected boundary without unrelated cleanup or speculative layers.
|
||||
Update an existing spec only if its contract is affected; do not require a spec.
|
||||
4. Verify affected behavior under [shared verification](../../protocols/workflow.md#verification).
|
||||
Distinguish pre-existing failures from regressions rather than requiring the
|
||||
entire repository to be green before starting.
|
||||
5. Show the interface change, complexity hidden, and verification result.
|
||||
|
||||
A **deep module** hides substantial internal logic behind a simple interface; a **shallow module**'s interface is nearly as complex as its implementation.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Invariants**:
|
||||
- Never change observable behavior during a deepening pass.
|
||||
- Run only when the test suite is fully passing.
|
||||
- Refactor one module per pass; deepening is surgical, never a wide codebase rewrite.
|
||||
- Avoid speculative abstraction: single-use code does not need complex generalization.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Confirm test suite is green.
|
||||
2. Scan the modules touched by the active spec or recent tasks.
|
||||
3. Identify shallowness symptoms:
|
||||
- Pass-through methods that simply forward to another layer.
|
||||
- Callers required to set 5+ configuration flags to perform a basic action.
|
||||
- Leaked internal mechanisms (e.g. caller forced to know rotation policies or cache keys).
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Diagnose Shallowness
|
||||
Cite the exact defect in Caveman style with `file:line`:
|
||||
> `src/auth/token.go:42`: 6-arg constructor leaks rotation policy to every caller. Shallow interface.
|
||||
|
||||
### Step 2: Design the Deeper Interface
|
||||
Apply core deepening principles:
|
||||
- **Pull Complexity Down**: Move complex parameter coordination inside the module; provide callers with a clean, obvious default.
|
||||
- **Define Errors Out of Existence**: Structure signatures so invalid states cannot be represented or called.
|
||||
- **Information Hiding**: Keep internal data structures private so callers never depend on implementation details.
|
||||
|
||||
### Step 3: Propose Spec Updates
|
||||
Draft changes for `spec`:
|
||||
- New, simplified §I interface shape.
|
||||
- New §V invariant preventing future regressions into shallowness.
|
||||
- Targeted §T refactoring task.
|
||||
|
||||
### Step 4: Execute & Verify Behavior
|
||||
- Implement refactor behind existing tests.
|
||||
- Verify test suite passes with zero failures.
|
||||
- Add tests confirming backwards compatibility or clean interface boundaries.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Run only when deliberate design improvements are requested or token budget permits; never interrupt active feature delivery.
|
||||
- One module per pass. Deepen the single worst offender and stop.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Deliver the deepening summary:
|
||||
1. **Interface Comparison**: Show concise before vs. after interface signature.
|
||||
2. **Complexity Hidden**: What private decision callers no longer have to manage.
|
||||
3. **Verification**: Confirm full test suite passed.
|
||||
4. **Proposed Spec Edits**: Drafted lines to hand to `spec`.
|
||||
Do not activate merely because token budget remains. Improve the requested scope;
|
||||
keep dependent changes coherent rather than imposing an arbitrary one-module limit.
|
||||
@@ -4,6 +4,7 @@ description: >
|
||||
Deliver a file or directory from this host to the user's device over
|
||||
Tailscale SSH. Use when the user wants to download, receive, or get a
|
||||
file, document, archive, report, or folder from the host machine.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Deliver File
|
||||
@@ -21,10 +22,12 @@ Host address: `vasily@msi.tail0b014a.ts.net` (Tailscale IP 100.67.41.125).
|
||||
If `t3-deliver` is missing, print the equivalent command yourself:
|
||||
|
||||
```text
|
||||
scp vasily@msi.tail0b014a.ts.net:"/absolute/path/to/file" .
|
||||
scp "vasily@msi.tail0b014a.ts.net:/absolute/path/to/file" .
|
||||
```
|
||||
|
||||
Add `-r` for directories.
|
||||
Add `-r` after `scp` for directories. This command assumes OpenSSH scp with
|
||||
SFTP support. For names containing shell expansion characters, use a simple
|
||||
archive name rather than handing the user an unsafe command.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -1,83 +1,27 @@
|
||||
---
|
||||
name: emergency-procedures
|
||||
description: >
|
||||
Recovery protocols when development loops fail, agent context is corrupted, git state is tangled,
|
||||
or quality gates break. Use when development becomes chaotic, thrashing loops occur, or when asked to recover state.
|
||||
concerns: [system-one-balance]
|
||||
Recover from repeated failed fixes, tangled git state, or lost task context when ordinary debugging cannot make progress or recovery is requested.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Emergency Recovery Procedures
|
||||
# Recovery
|
||||
|
||||
Standardized protocols for halting cascading failures, stabilizing git state, restoring agent context, and recovering working development branches.
|
||||
1. Stop speculative edits. Inspect status, diffs, branch, HEAD, and the current
|
||||
failure. Re-read the active objective and relevant repository conventions.
|
||||
2. Preserve work before changing branches or discarding anything. A branch at HEAD
|
||||
preserves commits only. Save tracked staged/unstaged diffs and copy relevant
|
||||
untracked files into an identified recovery location; or use a repository-approved
|
||||
snapshot method that captures those files. Verify the snapshot can recover them.
|
||||
Account for ignored files when relevant; do not accidentally collect credentials.
|
||||
3. Identify a known-good checkpoint from tests or history. Prefer a separate
|
||||
worktree for investigation so the user's current checkout remains intact.
|
||||
Returning to the previous branch is not evidence that it is healthy.
|
||||
4. Recover or fix the smallest demonstrated cause. Split work by meaningful
|
||||
behavior, without line-count limits or a new approval gate for the same task.
|
||||
5. Verify the relevant recovery outcome and report the preserved state and next step.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Circuit-Breaker Invariants**:
|
||||
- **Halt Implementation**: When an agent gets stuck in a thrashing loop, stop writing additional code immediately.
|
||||
- **Zero Destructive Discards**: Never run destructive commands (`git reset --hard`, `git clean -fdx`) without creating a safe backup branch or stash first.
|
||||
- **Isolate the Failure**: Determine whether the defect is environment, git state, code regression, or context divergence.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Detect emergency signals:
|
||||
- **Context Loss**: Agent suggests solutions contradicting established repo patterns or attempts wide, unsolicited rewrites.
|
||||
- **Git Confusion**: Unmerged conflicts, detached HEAD state, or untracked changes scattered across directories.
|
||||
- **Test Thrashing**: Attempted fixes repeatedly break tests in alternating cycles.
|
||||
2. Freeze and document:
|
||||
- Record the current git commit SHA, active branch, and modified file list (`git status`).
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Secure Working State
|
||||
Before making any changes, preserve the current uncommitted state:
|
||||
```bash
|
||||
# Create a safety branch with current WIP
|
||||
git checkout -b emergency-backup-$(date +%Y%m%d%H%M%S)
|
||||
git add -A
|
||||
git commit -m "emergency: snapshot before recovery"
|
||||
```
|
||||
|
||||
### Step 2: Roll Back to Last Known Good State
|
||||
Return to the main branch or stable checkpoint:
|
||||
```bash
|
||||
git checkout -
|
||||
git status
|
||||
```
|
||||
|
||||
### Step 3: Re-anchor Context
|
||||
1. Inspect the last stable commit and review actual working patterns in the codebase.
|
||||
2. Read project README, architecture docs, or `SPEC.md` to re-align goals.
|
||||
3. Formulate the single smallest task that can be verified in isolation.
|
||||
|
||||
### Step 4: Decompose Complex Tasks
|
||||
If a task ballooned in complexity:
|
||||
1. Break down the task into steps of ≤ 50 lines of change each.
|
||||
2. Sequence steps so each can be independently tested and committed.
|
||||
3. Obtain user confirmation on the refined task plan before re-attempting.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT panic or spam long conversational apologies. State the issue concisely, show the preserved backup branch, and propose the recovery plan.
|
||||
- Safe inspection (`git status`, `git diff`, `git log`) must be executed immediately without confirmation gates.
|
||||
- Reserve confirmation prompts strictly for discarding branches or rolling back production databases.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Verify:
|
||||
- Workspace working tree is clean or returned to a stable, reproducible state.
|
||||
- Test suite passes on the recovered base.
|
||||
2. Deliver the incident summary:
|
||||
- Root cause of the disruption.
|
||||
- State of the backup branch.
|
||||
- Concrete, small next step to resume forward progress safely.
|
||||
Never bulk-stage user work, clean untracked files, or reset the checkout just to
|
||||
make status clean. Existing authorization governs recovery; ask only if the next
|
||||
step would discard work or change scope without authorization. Follow
|
||||
[shared workflow](../../protocols/workflow.md).
|
||||
+20
-79
@@ -1,86 +1,27 @@
|
||||
---
|
||||
name: fuck-slop
|
||||
description: >
|
||||
De-slop pass for any text: detects and erases statistical AI writing fingerprints
|
||||
(negative parallelisms, em-dash abuse, rule-of-three, false ranges, puffery, uniform cadence)
|
||||
and rewrites prose to match target genre registers. Use when asked to "fuck slop", "deslop",
|
||||
"remove AI tells", "humanize", or before publishing agent-drafted prose.
|
||||
concerns: [style]
|
||||
Edit prose for clarity and remove repetitive AI-style filler when asked to deslop, humanize, remove AI tells, or improve the writing. Do not activate solely because text will be published.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# F*ck Slop
|
||||
# Edit prose
|
||||
|
||||
Strip every mark of AI writing from a text and make it authentic to its genre. Not "make it pass an AI detector" — make it read as if a specific human with a specific point wrote it for a specific audience.
|
||||
1. Read the text, audience, author voice, and constraints. Preserve the author's
|
||||
claims, uncertainty, numbers, citations, quotations, and meaningful terminology.
|
||||
2. Locate filler, vague claims, decorative contrast, redundant lists, and mechanical
|
||||
rhythm. Use [tell patterns](references/tells.md) only when useful; matches are
|
||||
review candidates, not defects or proof of AI authorship.
|
||||
3. State the actual claim directly, trim repetition, and keep concrete evidence.
|
||||
Preserve real comparisons, useful lists, and honest hedges. Do not fabricate
|
||||
detail, force short sentences, inject slang, or alter claims to clear a regex.
|
||||
4. Read the result once for meaning and register. Rescan only if a substantial
|
||||
rewrite may have introduced another problem. Stop when the text is clear;
|
||||
zero regex hits and fixed sentence-length quotas are not completion criteria.
|
||||
5. Deliver the edited text or requested file. Explain material edits when helpful;
|
||||
no mandatory diagnostic table or pass count.
|
||||
|
||||
## The Core Problem
|
||||
|
||||
The worst tells — especially **"not X but Y"** negative parallelisms — are emergent properties of preference tuning rewarding contrastive, comprehensive-sounding framing.
|
||||
1. **You cannot reliably see your own slop**: Detection must be mechanical (regex against a fixed catalog), never subjective impressions.
|
||||
2. **Rewriting reintroduces slop**: Rewriting "it's not just X, it's Y" often outputs "this is less about X than Y" — the same tell in a wig. The scan must loop until clean.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Review governing catalogs:
|
||||
- [references/tells.md](references/tells.md) for runnable `grep -Ein` patterns across all diagnostic categories.
|
||||
- [references/voices.md](references/voices.md) for target register profiles (academic, tweet, reddit, email, blog, docs, marketing).
|
||||
2. Rule: Never fix a pattern by paraphrasing the pattern. Fix by asking what the sentence asserts, then asserting that directly.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Establish the Target**:
|
||||
- **Genre & Venue**: Academic article, technical documentation, blog, tweet, email, Reddit post.
|
||||
- **Audience & Stance**: Who reads it, and what does the author specifically claim? Slop fills the space where a claim should be.
|
||||
- **Constraints**: Word limits, house style, required terminology.
|
||||
2. **Mechanical Scan**:
|
||||
- Run the regex catalog from [references/tells.md](references/tells.md) against the text.
|
||||
- Flag structural rhythm failures:
|
||||
- **Cadence**: 3+ consecutive sentences within $\pm 4$ words of equal length.
|
||||
- **Formatting**: Bold scattering through prose, emoji bullet spam, symmetrical triads.
|
||||
- Summarize findings into a concise diagnostic list before rewriting.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Negative Parallelism Triage
|
||||
Every "not X but Y" pattern receives one of three treatments:
|
||||
1. **Negation is a strawman** (nobody believes X): Delete X entirely; state Y directly with concrete evidence.
|
||||
2. **Contrast is genuine** (people hold X): Name who holds X and show concretely why Y wins.
|
||||
3. **Sentence asserts nothing** (decoration over empty claim): Delete the entire sentence.
|
||||
|
||||
*Banned escape hatches*: "less about X than Y", "X matters, but Y matters more", "the question isn't X, it's Y".
|
||||
|
||||
### Step 2: Vocabulary & Structure De-Slopping
|
||||
- **Puffery Tokens**: Replace inflated words (`pivotal`, `seismic`, `testament`, `tapestry`, `delve`, `multifaceted`) with plain verbs or concrete metrics.
|
||||
- **Rule-of-Three Lists**: Keep the single strongest item and discard filler. If keeping all three, break the symmetrical syntax.
|
||||
- **False Ranges**: ("from X to Y"): If no meaningful midpoint exists, name the two separate entities or cut one.
|
||||
- **Hedged Both-Sidesing**: ("it is worth noting", auto-counterpoints): Commit to a clear stance. Concede counterpoints only if genuine.
|
||||
- **Cadence Variance**: Mix short punchy sentences (3–6 words) with compound analytical statements. Break metronomic rhythm.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Preserve Ground Truth**:
|
||||
- Do NOT alter author claims, empirical numbers, code identifiers, or citations. This is a stylistic de-slop pass, not content censorship.
|
||||
- **Avoid Overcorrection**:
|
||||
- Do NOT inject fake typos, manufactured slang, or artificial cynicism ("humanizer" slop).
|
||||
- Em dashes are permitted when used naturally (maximum one per 150 words; never two in a sentence).
|
||||
- In technical and academic registers, prioritize clarity and precision over informal attitude.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. **Verification Loop**:
|
||||
- Re-run the Phase 1 scan on the rewritten text.
|
||||
- Fix and re-scan until zero regex hits occur (maximum 4 passes; if a sentence fails 4 passes, discard and rewrite its bare assertion from scratch).
|
||||
2. **Register Verification**:
|
||||
- Verify formatting and tone match [references/voices.md](references/voices.md).
|
||||
3. **Delivery**:
|
||||
- Output the clean, de-slopped text.
|
||||
- Provide a concise changelog table: Tell category, occurrences caught, and passes required.
|
||||
Read the relevant [register profile](references/voices.md) if the venue needs it.
|
||||
Use the author's supplied examples first. The optional
|
||||
[Vasily voice profile](../../../JEV/.agents/protocols/style-protocol.md) applies when
|
||||
writing as Vasily or for JEV, not to every author's text.
|
||||
@@ -12,7 +12,7 @@ When the text only exists in conversation, apply each pattern by hand. A match i
|
||||
|
||||
## 1. Negative parallelism — the "not X but Y" family
|
||||
|
||||
The highest-priority category. LLMs reach for the negation-then-assertion move roughly once a paragraph; humans use it occasionally and deliberately. It is an emergent generative habit, so expect it to reappear in paraphrased form after every rewrite pass — that is why the scan loops.
|
||||
The highest-priority category. LLMs reach for the negation-then-assertion move roughly once a paragraph; humans use it occasionally and deliberately. It is an emergent generative habit, so expect it to reappear in paraphrased form after every rewrite pass — a targeted rescan may help after a substantial rewrite.
|
||||
|
||||
```
|
||||
not (just|only|merely|simply|solely) [^.;]{2,80}(but|it'?s| — )
|
||||
@@ -123,7 +123,7 @@ Triage by hand: if you can name a meaningful midpoint, it's a real range and sta
|
||||
\b(\w+ \w+), (\w+ \w+), and (\w+ \w+)
|
||||
```
|
||||
|
||||
Triage: keep the strongest item, cut the rest — or keep all three only if each carries distinct information, and then break the rhythm.
|
||||
Triage: retain every distinct useful item. Remove only repetition or filler; no fixed list-length or rhythm quota.
|
||||
|
||||
## 5. Punctuation and formatting
|
||||
|
||||
@@ -148,7 +148,7 @@ Other formatting tells (check by hand; most regexes here are layout-dependent):
|
||||
|
||||
No regex; measure or eyeball.
|
||||
|
||||
- **Uniform sentence length** (the single strongest current tell): a run of 3+ consecutive sentences within ±4 words of each other, paragraph after paragraph of 18–24-word sentences. Quick measurement on a file:
|
||||
- **Uniform sentence length** (the single strongest current tell): a run of 3+ consecutive sentences within ±4 words of each other, paragraph after paragraph of 18–24-word sentences. Optional diagnostic on a file (not a completion gate):
|
||||
|
||||
```bash
|
||||
tr '\n' ' ' < draft.txt | sed 's/[.!?] /\n/g' | awk '{print NF}'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Register Guide
|
||||
|
||||
What "good" means per genre, what tells are fatal there, and what the de-slopped text should sound like. Use in Phase 0 (fix the target) and Phase 4 (register check). Two universal rules first:
|
||||
What "good" means per genre, what tells are fatal there, and what the de-slopped text should sound like. Read the relevant profile when the target venue needs it. Two universal rules first:
|
||||
|
||||
1. **Voice comes from commitment, not decoration.** A text sounds human when it asserts specific things a specific person believes, at the level of detail only someone who did the work would know. Slang, typos, and "personality" sprinkled on top do not produce this and read as humanizer-tool output.
|
||||
2. **Match the author, not a persona.** If the user supplied earlier writing or a draft with their own phrasing in it, keep their words wherever they survive the scan. De-slopping someone into a generic "casual" voice is just different slop.
|
||||
|
||||
@@ -1,77 +1,29 @@
|
||||
---
|
||||
name: git-workflow
|
||||
description: >
|
||||
Atomic commit grouping, selective staging, conventional commit messages, and clean git history hygiene.
|
||||
Use when preparing commits, staging changes selectively, reviewing git diffs, or standardizing commit messages.
|
||||
concerns: [system-one-balance]
|
||||
Inspect, stage, commit, and manage isolated branches and pull requests. Enforces worktree isolation and structured PR telemetry.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Git Workflow & Atomic Staging
|
||||
# Git workflow
|
||||
|
||||
Enforces clean, logical version control hygiene, atomic commits, and conventional commit standards across repositories.
|
||||
1. **Isolation**: When starting complex or multi-step tasks, operate within an
|
||||
isolated physical worktree ([references/worktrees.md](references/worktrees.md))
|
||||
or a T3 Code managed thread workspace. Never commit directly to primary branches
|
||||
(`main` or `master`).
|
||||
2. **Inspection**: Inspect staged, unstaged, and untracked changes. Identify
|
||||
ownership and requested scope before staging anything.
|
||||
3. **Cohesive grouping**: Group commits by complete behavior. Keep implementation,
|
||||
tests, and docs together when they belong to the same change; do not split
|
||||
automatically by file type or layer.
|
||||
4. **Staging & checks**: Stage named files or selected hunks. Preserve unrelated user
|
||||
edits. Run relevant checks under [shared verification](../../protocols/workflow.md#verification)
|
||||
and formatters. Use conventional commit messages (`feat:`, `fix:`, `perf:`, `docs:`).
|
||||
5. **Pull requests & telemetry**: Push feature branches and generate pull requests
|
||||
using `gh pr create` with the structured WHAT-WHY-HOW-LEARNINGS format
|
||||
([references/pr-template.md](references/pr-template.md)).
|
||||
6. **Cleanup**: Remove ephemeral worktrees after PR creation or merge.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Non-Negotiable Invariants**:
|
||||
- **Never Stage Unrelated Edits**: Inspect `git status` and diffs before staging. Stage only files directly relevant to the current task. Preserve untouched user work.
|
||||
- **Never Use Destructive Resets**: Never execute `git reset --hard` or `git checkout .` without explicit user instruction.
|
||||
- **Verify Before Committing**: Run quality gates (tests, linter) before creating commits.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Run `git status` to inspect modified, staged, and untracked files.
|
||||
2. Review `git diff` for staged vs. unstaged changes to ensure no extraneous edits or debug logs are included.
|
||||
3. Identify the logical boundaries of the work to separate independent changes.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Logical Commit Grouping
|
||||
Group changes into focused, cohesive commits rather than bulk-committing unrelated subsystems:
|
||||
1. **Infrastructure & DDL**: Table migrations, config schemas, and models.
|
||||
2. **Core Logic**: Services, domain algorithms, and processors.
|
||||
3. **API & Routes**: Web endpoints, controllers, and schemas.
|
||||
4. **Tests & Docs**: Automated tests, documentation, and specs.
|
||||
|
||||
### Step 2: Selective Staging
|
||||
- Stage specific files explicitly:
|
||||
```bash
|
||||
git add path/to/file1 path/to/file2
|
||||
```
|
||||
- Avoid blanket `git add .` when unstaged experimental edits exist in the workspace.
|
||||
|
||||
### Step 3: Conventional Commit Formatting
|
||||
Follow standard conventional commit prefixes:
|
||||
- `feat(<scope>):` New functionality or feature.
|
||||
- `fix(<scope>):` Bug fix or regression resolution.
|
||||
- `refactor(<scope>):` Code restructuring without behavioral change.
|
||||
- `perf(<scope>):` Performance optimization.
|
||||
- `sec(<scope>):` Security hardening or vulnerability fix.
|
||||
- `docs(<scope>):` Documentation updates.
|
||||
- `test(<scope>):` Adding or updating tests.
|
||||
- `chore(<scope>):` Tooling, dependencies, or maintenance.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Safe operations (e.g. `git status`, `git diff`, staging known files, creating a commit) must be frictionless fast paths.
|
||||
- Do NOT prompt the user with interactive confirmation modals for routine commits during an ongoing implementation.
|
||||
- Reserve confirmation prompts strictly for irreversible actions (`git push --force`, `git branch -D`, `git clean -fdx`).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Create the commit with a concise, descriptive message.
|
||||
2. Verify commit creation:
|
||||
```bash
|
||||
git log -n 1 --oneline
|
||||
```
|
||||
3. Confirm working tree status remains clean and expected.
|
||||
No routine confirmation prompt is needed for authorized staging or commits on
|
||||
feature branches. Destructive operations (force push, hard reset) are strictly
|
||||
forbidden under repository negative constraints.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Standard Pull Request Telemetry Template
|
||||
|
||||
Use this markdown structure for automated pull request bodies (`gh pr create --body-file ...`)
|
||||
and formal task completion records:
|
||||
|
||||
```markdown
|
||||
## 1. WHAT (System Modifications)
|
||||
- **Modified Components**:
|
||||
- `path/to/modified_file.ext`
|
||||
- **Added Assets**:
|
||||
- `path/to/new_file.ext`
|
||||
- **Removed Assets**:
|
||||
- None
|
||||
|
||||
## 2. WHY (Context & Architectural Intent)
|
||||
- **Problem Statement**: Concise description of defect, bottleneck, or requirement.
|
||||
- **Requirement Traceability**: Issue # / Task ID / Plan bead.
|
||||
- **Design Justification**: Rationale for chosen implementation architecture.
|
||||
|
||||
## 3. HOW (Technical Implementation & Verification Evidence)
|
||||
- **Implementation Details**: Summary of algorithmic, API, or structural updates.
|
||||
- **Deterministic Verification Evidence**:
|
||||
- **Command**: `pytest tests/unit/test_target.py -v`
|
||||
- **Exit Code**: `0`
|
||||
- **Output Metrics**: `XX passed, 0 failed, 100% pass rate`
|
||||
- **Static Analysis & Linting**:
|
||||
- **Command**: `ruff check src/`
|
||||
- **Result**: Clean (0 errors)
|
||||
|
||||
## 4. LEARNINGS & ARCHITECTURAL GOTCHAS
|
||||
- **Operational Traps**: Specific runtime, environment, or dependency quirks discovered.
|
||||
- **Uncovered Debt**: Latent issues, missing coverage, or obsolete patterns identified.
|
||||
- **Indexed Gotchas**: Reference to saved `docs/gotchas/<slug>.md` if applicable.
|
||||
- **Follow-up Recommendations**: Subsequent tasks or architectural considerations.
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
# Physical Git Worktree Isolation
|
||||
|
||||
Developing directly on primary branches (`main` or `master`) or in a single shared
|
||||
working directory creates severe multi-agent concurrency risks:
|
||||
- Uncommitted edits from concurrent tasks get overwritten or cross-contaminated.
|
||||
- Branch switches abort background compilations or active test suites.
|
||||
- Half-finished experiments accidentally leak into tracking branches.
|
||||
|
||||
Physical Git worktrees resolve concurrency at the filesystem level. Each task or
|
||||
agent operates in an independent physical directory linked to the shared `.git`
|
||||
repository.
|
||||
|
||||
## Standard worktree lifecycle
|
||||
|
||||
### 1. Provision a dedicated worktree
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
# Create a new feature branch in an isolated worktree directory
|
||||
git worktree add -b feat/<task-id> ../worktrees/<task-id> main
|
||||
cd ../worktrees/<task-id>
|
||||
```
|
||||
|
||||
### 2. Implement, verify, and commit
|
||||
Inside the isolated worktree:
|
||||
- Make targeted changes.
|
||||
- Run local tests and deterministic formatters.
|
||||
- Stage changes and commit using conventional commit format:
|
||||
```sh
|
||||
git add <files>
|
||||
git commit -m "feat(module): implement scoped capability"
|
||||
```
|
||||
|
||||
### 3. Push and generate pull request
|
||||
Push the branch to remote origin:
|
||||
```sh
|
||||
git push -u origin feat/<task-id>
|
||||
```
|
||||
|
||||
Create the pull request via GitHub CLI using the WHAT-WHY-HOW-LEARNINGS template:
|
||||
```sh
|
||||
gh pr create \
|
||||
--title "feat(module): implement scoped capability" \
|
||||
--body-file docs/reports/<task-id>-telemetry.md \
|
||||
--base main \
|
||||
--head feat/<task-id>
|
||||
```
|
||||
|
||||
### 4. Cleanup after merge
|
||||
Once the PR is merged or the task is completed:
|
||||
```sh
|
||||
cd ../main-repo
|
||||
git worktree remove ../worktrees/<task-id>
|
||||
```
|
||||
|
||||
## T3 Code managed worktrees
|
||||
When operating within the T3 Code control plane, worktree provisioning, branch
|
||||
isolation, and diff tracking are handled natively per conversation thread. Use
|
||||
T3 Code's built-in PR tools (`link_pull_request`, `list_thread_pull_requests`) to
|
||||
associate PRs with the active task.
|
||||
+16
-75
@@ -1,83 +1,24 @@
|
||||
---
|
||||
name: grill
|
||||
description: >
|
||||
Calibrated interrogation to stress-test a fuzzy plan, design, or architecture before writing a spec or code.
|
||||
Asks one question at a time with recommended answers to extract concrete goals (§G) and constraints (§C).
|
||||
Use when asked to "grill me", "stress-test this", "challenge my plan", or before authoring a spec.
|
||||
concerns: [system-one-balance]
|
||||
Stress-test a fuzzy plan through questions when asked to grill, challenge, or interrogate the plan. Do not activate automatically before every spec.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Grill — Calibrated Plan Stress-Testing
|
||||
# Plan questions
|
||||
|
||||
Drags ambiguity into concrete goals (§G) and constraints (§C) *before* execution begins. A bad assumption caught here costs one question; caught later, it costs an architectural refactor.
|
||||
Inspect the conversation and relevant code before asking. Infer routine details;
|
||||
ask only about a product choice or uncertainty that materially changes the plan.
|
||||
|
||||
---
|
||||
1. Identify the most consequential unknown about the goal, completion criteria,
|
||||
scope, constraints, interfaces, or failure behavior.
|
||||
2. Ask one concise question with a recommended answer and a sentence explaining
|
||||
its impact. Respect the user's chosen level of detail and pressure.
|
||||
3. Incorporate the answer and continue only while consequential unknowns remain.
|
||||
Do useful independent investigation while waiting when possible.
|
||||
4. Stop when the goal and boundaries are clear. Summarize decisions and remaining
|
||||
uncertainties; distinguish deferred non-blocking questions from true blockers.
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. **Interrogation Invariants**:
|
||||
- **One Question at a Time**: Never ask multiple questions in a single turn. Ask one question, provide a recommended answer, and wait.
|
||||
- **Recommend an Answer**: Always provide a concrete default so the user can reply with "yes" or choose an alternative.
|
||||
- **Inspect Context First**: If an answer can be found in files, code, docs, or git history, inspect them directly instead of asking the user.
|
||||
- **Propose, Don't Decide**: Challenge tradeoffs and surface hidden edge cases, but leave final product choices to the user.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Determine user knowledge and desired pressure level from context:
|
||||
- **Knowledge Level**:
|
||||
- *New*: Explain missing frames briefly (2 sentences); focus on first principles and goals.
|
||||
- *Working*: Challenge standard tradeoffs, alternatives, and validation criteria.
|
||||
- *Expert*: Probe failure modes, boundary limits, migration costs, and reversibility.
|
||||
- **Pressure Level**:
|
||||
- *Light*: Clarify goals, scope, and missing definitions.
|
||||
- *Standard*: Challenge assumptions, resource bottlenecks, and execution paths.
|
||||
- *Hard*: Probe edge cases, adverse incentives, failure modes, and rollback mechanisms.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
Climb the Question Ladder in sequence. Stop as soon as the plan is clear; do not ask every rung by reflex:
|
||||
1. **Goal (§G)**: What must the code or feature accomplish in one single, unambiguous sentence?
|
||||
2. **Done Criteria (§C / §V)**: What observable signal (test, metric, terminal output) proves this works?
|
||||
3. **Boundaries (§C)**: What is explicitly *out of scope* for this change?
|
||||
4. **Non-Negotiables (§C)**: What architectural patterns, libraries, or constraints are strictly required or forbidden?
|
||||
5. **Surfaces (§I)**: What external membranes (API endpoints, CLI flags, DB tables, schemas) will be modified?
|
||||
6. **Failure Modes (§V)**: What is the primary edge case or input that breaks the happy path?
|
||||
7. **Unknowns (`?`)**: What do we not yet know? (Park unresolved items as `?` bullets; do not guess them).
|
||||
|
||||
### Question Format
|
||||
```text
|
||||
Question: ...
|
||||
Recommended answer: ...
|
||||
Why it matters: [1 sentence rationale]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Stop grilling immediately once the goal and boundaries are defined.
|
||||
- Never interrogate the user on routine file edits, typo fixes, or straightforward tasks.
|
||||
- Accept the user's recommended answer or override without debate.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Stop grilling when **all** of the following hold:
|
||||
- §G is one line, one reading, zero "or maybe".
|
||||
- §C covers every non-negotiable stated or implied.
|
||||
- Every blocking unknown is answered or parked as an explicit `?`.
|
||||
|
||||
Emit the structured handoff block to pass to the **spec** or **build** workflow:
|
||||
```markdown
|
||||
## Grill Handoff
|
||||
- **§G**: [One-line goal]
|
||||
- **§C**: [Constraints and non-negotiables]
|
||||
- **§I**: [Surfaces touched]
|
||||
- **Parked Unknowns (`?`)**: [Items deferred to research]
|
||||
```
|
||||
An explicit request to interrogate can use a question-at-a-time exchange. Otherwise
|
||||
follow [shared workflow](../../protocols/workflow.md); routine edits and already-clear
|
||||
implementation requests need no interview or mandatory handoff report.
|
||||
+34
-603
@@ -1,608 +1,39 @@
|
||||
---
|
||||
name: interface-kit
|
||||
description: >
|
||||
Comprehensive implementation guide for exceptional, accessible, performant UI: design engineering craft,
|
||||
spatial layout, typography, spring physics, accessibility (WCAG AA), and component patterns.
|
||||
Use when building UI, components, landing pages, styling, or polishing frontend interfaces.
|
||||
concerns: [system-one-balance]
|
||||
Implement or polish accessible UI using existing project components, design tokens, and platform conventions when asked to build or style an interface.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Interface Kit: Implementation Guide for Exceptional Interfaces
|
||||
|
||||
> If a DESIGN.md exists at the project root, its tokens and specifications override all defaults in this skill. This skill provides sensible defaults for when no design system exists, and implementation guidance that applies regardless.
|
||||
|
||||
> For deep dives on any section, see the reference files in this skill's `references/` directory.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Inspect project root for `DESIGN.md`: If present, tokens and definitions override defaults here.
|
||||
2. Reference auxiliary guides in `references/`:
|
||||
- [`references/accessibility-checklist.md`](references/accessibility-checklist.md) (WCAG AA)
|
||||
- [`references/animation-playbook.md`](references/animation-playbook.md) (Spring physics & timing)
|
||||
- [`references/component-patterns.md`](references/component-patterns.md) (Accessible component recipes)
|
||||
- [`references/review-checklist.md`](references/review-checklist.md) (30-point pre-delivery audit)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. Identify target platform (Web/React/Next.js/Tailwind/CSS).
|
||||
2. Pick a deliberate aesthetic direction from Section 3 before writing styles.
|
||||
3. Establish non-negotiable accessibility and contrast constraints.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Implementation Stack)
|
||||
|
||||
### 1. Core Philosophy
|
||||
|
||||
Taste is trained, not innate. Study why great interfaces feel right. Deconstruct apps you admire — the spacing, the timing, the weight of a shadow. The gap between "fine" and "exceptional" is built from hundreds of micro-decisions that users feel but never consciously notice.
|
||||
|
||||
**Unseen details compound.** A single rounded corner, a single eased transition, a single well-chosen shadow — none of these matter alone. Together they become "a thousand barely audible voices singing in tune." The cumulative effect is what separates craft from output.
|
||||
|
||||
**Beauty is leverage.** Polish is not vanity. Good defaults, considered typography, and intentional motion are real differentiators. Users trust interfaces that feel cared for. Investors notice. Competitors can't easily replicate taste.
|
||||
|
||||
**Intentionality over intensity.** Both bold maximalism and refined minimalism work — what fails is the absence of a clear point of view. Every visual decision should trace back to a deliberate conceptual direction. If you can't articulate WHY a choice was made, reconsider it.
|
||||
|
||||
**Choose a direction and execute with precision.** Don't hedge between styles. A brutalist page committed fully will always outperform a page that's "a little bit of everything." Commit, then refine.
|
||||
|
||||
**NEVER produce generic "AI slop" aesthetics.** No gratuitous gradients on white backgrounds. No cookie-cutter hero sections with stock illustrations. No safe, forgettable layouts that could belong to any product. Every interface should have a point of view that makes it recognizable.
|
||||
|
||||
---
|
||||
|
||||
### 2. The Priority Stack
|
||||
|
||||
When implementing UI, work through these priorities in order. Higher priorities are non-negotiable; lower priorities are polish that compounds quality.
|
||||
|
||||
| Priority | Level | What It Means |
|
||||
|----------|-------|---------------|
|
||||
| **Accessibility** | CRITICAL | Contrast 4.5:1, keyboard nav, ARIA semantics, visible focus rings. Ship nothing that excludes users. |
|
||||
| **Performance** | HIGH | WebP/AVIF images, lazy loading below fold, CLS < 0.1, transform-only animations on the compositor thread. |
|
||||
| **Typography** | HIGH | Font smoothing, text-wrap balance/pretty, tabular-nums for data, 65ch max line length. |
|
||||
| **Layout & Spatial** | HIGH | 4/8px grid, concentric border radius, optical alignment over geometric. |
|
||||
| **Color & Theme** | MEDIUM | HSL custom properties, semantic tokens, dark mode pairs tested separately. |
|
||||
| **Motion & Interaction** | MEDIUM | Frequency-based animation decisions, 150-300ms durations, ease-out default. |
|
||||
| **Polish & Details** | LOW | Layered shadows over borders, press feedback on buttons, staggered enter animations. |
|
||||
|
||||
Never skip a CRITICAL/HIGH item to chase a LOW item. A beautifully animated button that fails keyboard navigation is a net negative.
|
||||
|
||||
---
|
||||
|
||||
### 3. Aesthetic Direction
|
||||
|
||||
Before writing a single line of CSS, commit to a bold aesthetic direction. The most common failure mode in AI-generated UI is convergence on the same safe, forgettable look.
|
||||
|
||||
### Pick a Tone
|
||||
|
||||
Choose one and commit fully:
|
||||
|
||||
- **Brutally minimal** — generous whitespace, monospace type, stark contrast, near-zero decoration
|
||||
- **Maximalist chaos** — layered textures, clashing type scales, dense information, intentional visual noise
|
||||
- **Retro-futuristic** — CRT glow effects, monospace terminals, scan lines, neon on dark
|
||||
- **Organic / natural** — earth tones, rounded shapes, paper textures, hand-drawn accents
|
||||
- **Luxury / refined** — serif headlines, muted palettes, ample negative space, subtle gold or cream accents
|
||||
- **Editorial / magazine** — dramatic type hierarchy, full-bleed imagery, grid-breaking layouts
|
||||
- **Playful / bold** — bright primaries, chunky borders, exaggerated shadows, bouncy motion
|
||||
|
||||
### Match Complexity to Vision
|
||||
|
||||
Maximalist design demands elaborate code — layered backgrounds, complex grid structures, multiple font stacks. Minimalist design demands surgical precision — every pixel of spacing matters more when there's nothing to hide behind.
|
||||
|
||||
### The Ban List (When No DESIGN.md Exists)
|
||||
|
||||
When building without an existing design system, avoid these overused defaults that signal "AI-generated":
|
||||
|
||||
- **Fonts**: Inter, Roboto, Arial, system-ui as display fonts, Space Grotesk
|
||||
- **Colors**: Purple-to-blue gradients on white backgrounds
|
||||
- **Patterns**: Generic hero with centered text + CTA + stock illustration
|
||||
|
||||
Vary between light and dark themes, different font pairings, different aesthetic directions. Never converge on the same choices across projects.
|
||||
|
||||
### Visual Texture
|
||||
|
||||
Add depth through: gradient meshes, noise/grain overlays (`filter: url(#noise)`), layered transparencies, subtle background patterns, duotone image treatments.
|
||||
|
||||
**DESIGN.md overrides this entire section.** If DESIGN.md specifies Inter, use Inter. If it specifies purple gradients, use them. The ban list only applies when no design system exists and you're making aesthetic choices from scratch.
|
||||
|
||||
---
|
||||
|
||||
### 4. Typography Essentials
|
||||
|
||||
Typography is the single highest-leverage design element. Get it right and mediocre layouts still feel good. Get it wrong and nothing else saves it.
|
||||
|
||||
### Root Setup
|
||||
|
||||
```css
|
||||
html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
```
|
||||
|
||||
Apply font smoothing to the root layout. On macOS, the default sub-pixel rendering makes text appear heavier than the designer intended.
|
||||
|
||||
### Text Wrapping
|
||||
|
||||
```css
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
p, li, dd, blockquote {
|
||||
text-wrap: pretty;
|
||||
}
|
||||
```
|
||||
|
||||
`balance` distributes heading lines evenly. `pretty` avoids orphaned words in body text.
|
||||
|
||||
### Numeric Display
|
||||
|
||||
```css
|
||||
.data-value, .price, .counter, [data-numeric] {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
```
|
||||
|
||||
Use `tabular-nums` for any number that updates dynamically — prices, counters, table columns. Without it, layout shifts as digit widths change.
|
||||
|
||||
### Scale and Rhythm
|
||||
|
||||
- **Base size**: 16px minimum for body text. Never go below 14px for any readable content.
|
||||
- **Line height**: 1.5-1.75 for body text, 1.1-1.3 for large headings.
|
||||
- **Max line length**: `max-width: 65ch` for body text. Long lines destroy readability.
|
||||
- **Type scale**: Pick a consistent scale and stick to it: 12 / 14 / 16 / 18 / 24 / 32 / 48 / 64.
|
||||
|
||||
### Font Pairing
|
||||
|
||||
Pair a distinctive display font with a refined body font. The display font carries personality; the body font carries readability. Use `font-weight` for hierarchy within a family:
|
||||
|
||||
- **Headings**: 600-700 (semibold to bold)
|
||||
- **Body**: 400 (regular)
|
||||
- **Labels / UI**: 500 (medium)
|
||||
|
||||
Always include font stack fallbacks:
|
||||
|
||||
```css
|
||||
--font-display: "Instrument Serif", "Georgia", serif;
|
||||
--font-body: "Söhne", "Helvetica Neue", sans-serif;
|
||||
--font-mono: "JetBrains Mono", "Fira Code", monospace;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Color & Theme
|
||||
|
||||
### HSL Custom Properties (shadcn Pattern)
|
||||
|
||||
```css
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
```
|
||||
|
||||
Define semantic tokens: primary, secondary, destructive, muted, accent, background, foreground. Reference colors by semantic name — never hardcode hex values in components.
|
||||
|
||||
### Dark Mode
|
||||
|
||||
```css
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
/* ... desaturated, lighter tonal variants — NOT simply inverted */
|
||||
}
|
||||
```
|
||||
|
||||
Dark mode is not "invert colors." Use desaturated, lighter tonal variants. Backgrounds go dark but not pure black (`#000`). Text goes light but not pure white (`#fff`). Test contrast separately for dark mode — what passes in light may fail in dark.
|
||||
|
||||
### Contrast Requirements
|
||||
|
||||
- **WCAG AA minimum**: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+ regular)
|
||||
- Never convey information by color alone — always pair with an icon, label, or pattern
|
||||
- Test with browser devtools contrast checker or axe-core
|
||||
|
||||
### Color Confidence
|
||||
|
||||
Dominant colors with sharp accents outperform timid, evenly-distributed palettes. Pick one or two hero colors and let the rest of the palette recede. A confident palette has clear hierarchy; an uncertain palette spreads color evenly and feels flat.
|
||||
|
||||
---
|
||||
|
||||
## 6. Spatial Design
|
||||
|
||||
### Concentric Border Radius
|
||||
|
||||
This is the single most common thing that makes nested UI elements feel "off":
|
||||
|
||||
```
|
||||
outer_radius = inner_radius + padding
|
||||
```
|
||||
|
||||
```css
|
||||
/* Correct: concentric */
|
||||
.card { border-radius: 16px; padding: 8px; }
|
||||
.card-inner { border-radius: 8px; } /* 16 - 8 = 8 */
|
||||
|
||||
/* Wrong: same radius on parent and child */
|
||||
.card { border-radius: 12px; }
|
||||
.card-inner { border-radius: 12px; } /* Looks bloated */
|
||||
```
|
||||
|
||||
When geometric centering looks off, align optically. Play/pause icons, dropdown carets, and asymmetric glyphs often need 1-2px manual nudges to look centered.
|
||||
|
||||
### Shadows Over Borders
|
||||
|
||||
Layer multiple transparent `box-shadow` values for natural depth instead of using borders:
|
||||
|
||||
```css
|
||||
.elevated {
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0, 0, 0, 0.04),
|
||||
0 2px 4px rgba(0, 0, 0, 0.04),
|
||||
0 4px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
```
|
||||
|
||||
Multiple shadows at different spreads mimic how light works. A single hard shadow looks artificial.
|
||||
|
||||
### Image Outlines
|
||||
|
||||
Add a subtle inset outline to images and media for consistent depth against varied backgrounds:
|
||||
|
||||
```css
|
||||
img, video {
|
||||
outline: 1px solid rgba(0, 0, 0, 0.06);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
```
|
||||
|
||||
### Spacing Scale
|
||||
|
||||
Use a 4px / 8px base incremental system. Every spacing value should be a multiple of 4:
|
||||
|
||||
`4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128`
|
||||
|
||||
### Hit Areas
|
||||
|
||||
Minimum 44x44px for all interactive elements. If the visual element is smaller, extend the hit area with a pseudo-element:
|
||||
|
||||
```css
|
||||
.small-button::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -8px;
|
||||
}
|
||||
```
|
||||
|
||||
### Z-Index Scale
|
||||
|
||||
Define a layered scale and never use arbitrary values:
|
||||
|
||||
```css
|
||||
--z-base: 0;
|
||||
--z-dropdown: 10;
|
||||
--z-sticky: 20;
|
||||
--z-overlay: 40;
|
||||
--z-modal: 100;
|
||||
--z-toast: 1000;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Motion & Interaction
|
||||
|
||||
### The Frequency-Based Decision Framework
|
||||
|
||||
This is the most important mental model for animation decisions:
|
||||
|
||||
| Frequency | Examples | Animation |
|
||||
|-----------|----------|-----------|
|
||||
| **100+ times/day** | Keyboard shortcuts, command palette actions, tab switches | **None.** Zero animation. Instant. |
|
||||
| **Tens of times/day** | Hover effects, list item navigation, toggles | **Remove or drastically reduce.** 50-100ms max. |
|
||||
| **Occasional** | Modals, drawers, toasts, page transitions | **Standard animation.** 150-300ms. |
|
||||
| **Rare / first-time** | Onboarding, celebrations, empty states | **Can add delight.** 300-500ms, more elaborate. |
|
||||
|
||||
High-frequency animations feel sluggish. Low-frequency animations without motion feel jarring. Match the animation budget to usage frequency.
|
||||
|
||||
### Custom Easing Curves
|
||||
|
||||
Built-in CSS easings (`ease`, `ease-in-out`) are too weak. Define custom curves:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
|
||||
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
```
|
||||
|
||||
### Duration Guide
|
||||
|
||||
| Element | Duration |
|
||||
|---------|----------|
|
||||
| Buttons, toggles | 100-160ms |
|
||||
| Tooltips | 125-200ms |
|
||||
| Dropdowns, popovers | 150-250ms |
|
||||
| Modals, drawers | 200-500ms |
|
||||
| Page transitions | 250-400ms |
|
||||
|
||||
UI animations should stay under 300ms. Never use `ease-in` for UI animations — it front-loads the pause and feels sluggish.
|
||||
|
||||
### Enter/Exit Asymmetry
|
||||
|
||||
Exits should be softer and faster than enters. An enter animation at 250ms should have its exit at 150-200ms.
|
||||
|
||||
### Split and Stagger Enter Animations
|
||||
|
||||
When multiple elements enter the viewport, stagger them by semantic chunks with ~50-100ms delay:
|
||||
|
||||
```css
|
||||
.stagger-item {
|
||||
animation: fadeSlideIn 300ms var(--ease-out) both;
|
||||
}
|
||||
.stagger-item:nth-child(1) { animation-delay: 0ms; }
|
||||
.stagger-item:nth-child(2) { animation-delay: 60ms; }
|
||||
.stagger-item:nth-child(3) { animation-delay: 120ms; }
|
||||
```
|
||||
|
||||
### Scale Animations
|
||||
|
||||
Never animate from `scale(0)`. Start from `scale(0.9)` or higher, combined with opacity:
|
||||
|
||||
```css
|
||||
@keyframes scaleIn {
|
||||
from { opacity: 0; transform: scale(0.95); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
```
|
||||
|
||||
### Press Feedback
|
||||
|
||||
Every pressable element should scale down slightly on `:active`:
|
||||
|
||||
```css
|
||||
button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
```
|
||||
|
||||
### Interruptibility
|
||||
|
||||
Use CSS transitions (not keyframe animations) for interactive state changes. Transitions can be interrupted mid-way; keyframes cannot. This matters for hover states, toggles, and any element the user might interact with rapidly.
|
||||
|
||||
### Popover Origin
|
||||
|
||||
Make popovers transform-origin aware — they should grow from their trigger element, not from center. Exception: modals always originate from center.
|
||||
|
||||
### Tooltip Hover Delay
|
||||
|
||||
Skip the tooltip delay on subsequent hovers. If the user has already waited for one tooltip, show the next one immediately.
|
||||
|
||||
### Reduced Motion
|
||||
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Respect `prefers-reduced-motion`. Reduce animations — don't eliminate opacity and color transitions entirely, as those provide important feedback.
|
||||
|
||||
### Hover Gate
|
||||
|
||||
Gate hover animations behind a media query so touch devices don't trigger stuck hover states:
|
||||
|
||||
```css
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
.card:hover { transform: translateY(-2px); }
|
||||
}
|
||||
```
|
||||
|
||||
> Reference `references/animation-playbook.md` for deep dives on spring physics, gesture-driven animation, and complex choreography.
|
||||
|
||||
---
|
||||
|
||||
### 8. Component Craft
|
||||
|
||||
### Primitives
|
||||
|
||||
Use Radix UI primitives for accessible, unstyled foundations. Use CVA (class-variance-authority) for type-safe component variants:
|
||||
|
||||
```tsx
|
||||
import { cva } from "class-variance-authority";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
},
|
||||
size: {
|
||||
sm: "h-9 px-3 text-sm",
|
||||
default: "h-10 px-4 py-2",
|
||||
lg: "h-11 px-8 text-lg",
|
||||
},
|
||||
},
|
||||
defaultVariants: { variant: "default", size: "default" },
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Button
|
||||
|
||||
- Scale on press (`transform: scale(0.97)` on `:active`)
|
||||
- Visible focus ring (never `outline: none` without replacement)
|
||||
- Loading state with spinner replacing label, maintaining button dimensions
|
||||
- Disabled state at `opacity: 0.5` with `pointer-events: none`
|
||||
|
||||
### Card
|
||||
|
||||
- Concentric border radius between card and inner elements
|
||||
- Layered shadows (not borders) for depth
|
||||
- Hover state: subtle elevation change (`translateY(-1px)` + shadow increase)
|
||||
|
||||
### Dialog / Modal
|
||||
|
||||
- Focus trap (keyboard cannot escape to elements behind)
|
||||
- ESC to close, click outside overlay to close
|
||||
- `transform-origin: center`, fade + scale enter animation
|
||||
- `aria-modal="true"`, `role="dialog"`, `aria-labelledby`
|
||||
|
||||
### Form
|
||||
|
||||
- Visible labels always — never placeholder-only inputs
|
||||
- Error messages near the field with `aria-live="polite"` for screen readers
|
||||
- Progressive disclosure: show advanced fields only when needed
|
||||
- Use React Hook Form + Zod for validation
|
||||
|
||||
### Theming
|
||||
|
||||
Use shadcn CSS variable pattern (HSL format) for all component colors. Wrap client-interactive components in server components for Next.js App Router compatibility.
|
||||
|
||||
> Reference `references/component-patterns.md` for the full component catalog with copy-paste implementations.
|
||||
|
||||
---
|
||||
|
||||
## 9. Accessibility Essentials
|
||||
|
||||
### Semantic HTML First
|
||||
|
||||
Use `<button>`, `<nav>`, `<main>`, `<header>`, `<footer>`, `<article>`, `<section>` before reaching for ARIA. A `<button>` gives you keyboard handling, focus management, and screen reader semantics for free. A `<div onClick>` gives you none of that.
|
||||
|
||||
### Keyboard Navigation
|
||||
|
||||
- **Tab / Shift+Tab**: move between focusable elements
|
||||
- **Enter / Space**: activate buttons and links
|
||||
- **Arrow keys**: navigate within lists, menus, tabs, radio groups
|
||||
- **Escape**: close modals, popovers, dropdowns
|
||||
- **Home / End**: jump to first/last item in lists
|
||||
|
||||
### Focus Management
|
||||
|
||||
- Visible focus rings on all interactive elements — NEVER use `outline: none` without a replacement
|
||||
- Trap focus inside modals (Tab wraps within the modal, not behind it)
|
||||
- Restore focus to the trigger element when a modal/popover closes
|
||||
- Use `focus-visible` to show rings only for keyboard users, not mouse clicks:
|
||||
|
||||
```css
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
```
|
||||
|
||||
### ARIA Attributes
|
||||
|
||||
- `aria-label` for icon-only buttons: `<button aria-label="Close menu">X</button>`
|
||||
- `aria-labelledby` to associate headings with sections
|
||||
- `aria-describedby` to link help text or error messages to inputs
|
||||
- `aria-live="polite"` for dynamic content updates (toast messages, form errors)
|
||||
- `aria-hidden="true"` for decorative elements (icons next to text labels)
|
||||
- `aria-expanded` for toggleable elements (dropdowns, accordions)
|
||||
|
||||
### Color and Contrast
|
||||
|
||||
- WCAG AA: 4.5:1 for normal text, 3:1 for large text
|
||||
- Never use color as the sole indicator — pair with icons, text, or patterns
|
||||
- Test in both light and dark modes
|
||||
|
||||
### Images and Media
|
||||
|
||||
- Descriptive `alt` text for meaningful images: `alt="Dashboard showing 23% revenue growth"`
|
||||
- Empty `alt=""` for purely decorative images
|
||||
- Captions for video, transcripts for audio
|
||||
|
||||
### Navigation Aids
|
||||
|
||||
- **Skip link**: first focusable element, hidden until focused:
|
||||
|
||||
```html
|
||||
<a href="#main-content" class="sr-only focus:not-sr-only">
|
||||
Skip to main content
|
||||
</a>
|
||||
```
|
||||
|
||||
- **Heading hierarchy**: sequential h1 through h6, no level skips. One `<h1>` per page.
|
||||
|
||||
### Touch Targets
|
||||
|
||||
- Minimum 44x44px interactive area
|
||||
- 8px minimum spacing between adjacent touch targets
|
||||
- Extend small visual elements with invisible padding or pseudo-elements
|
||||
|
||||
### Testing
|
||||
|
||||
- **Automated**: axe-core in CI, Lighthouse accessibility score 90+
|
||||
- **Manual**: full keyboard-only navigation test
|
||||
- **Screen reader**: test with VoiceOver (macOS) or NVDA (Windows)
|
||||
- **Visual**: zoom to 200%, check nothing breaks or overlaps
|
||||
|
||||
> Reference `references/accessibility-checklist.md` for the full audit guide with pass/fail criteria.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT stall the user with multiple rounds of aesthetic questionnaires when asked to build or style UI.
|
||||
- Commit to a cohesive aesthetic direction and deliver working, accessible code.
|
||||
- Always respect `prefers-reduced-motion` and provide visible focus rings.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Run through this checklist before considering any UI implementation complete:
|
||||
|
||||
### Typography
|
||||
- [ ] Font smoothing applied (`-webkit-font-smoothing: antialiased`)
|
||||
- [ ] Headings use `text-wrap: balance`
|
||||
- [ ] Dynamic numbers use `font-variant-numeric: tabular-nums`
|
||||
|
||||
### Color
|
||||
- [ ] All colors referenced via semantic tokens, no hardcoded hex in components
|
||||
- [ ] Color contrast meets WCAG AA (4.5:1 normal text, 3:1 large text)
|
||||
- [ ] Dark mode tested separately for contrast
|
||||
|
||||
### Spatial
|
||||
- [ ] Nested rounded elements use concentric border radius
|
||||
- [ ] Spacing follows 4px / 8px scale consistently
|
||||
- [ ] Interactive elements have 44x44px minimum hit area
|
||||
- [ ] Shadows used instead of borders where appropriate
|
||||
|
||||
### Motion
|
||||
- [ ] Animation frequency matches usage frequency (no animation on high-frequency actions)
|
||||
- [ ] No `transition: all` anywhere — specific properties only
|
||||
- [ ] Enter animations split and staggered where multiple elements appear
|
||||
- [ ] `prefers-reduced-motion` respected
|
||||
|
||||
### Accessibility
|
||||
- [ ] All interactive elements keyboard accessible
|
||||
- [ ] Focus rings visible on keyboard navigation (never `outline: none` without replacement)
|
||||
- [ ] Semantic HTML used before ARIA
|
||||
- [ ] `aria-live` on dynamic content updates
|
||||
|
||||
> Reference `references/review-checklist.md` for the extended 30-item checklist with severity ratings and automated testing commands.
|
||||
# Interface implementation
|
||||
|
||||
1. Inspect the target flow, components, tokens, and platform. Preserve the established
|
||||
design even when no `DESIGN.md` exists. User instructions and existing conventions
|
||||
take precedence over recipe defaults.
|
||||
2. Build the requested behavior and states: loading, empty, success, error, and
|
||||
disabled states where relevant. Use native semantics and the project's primitives;
|
||||
do not add React, Radix, shadcn, or another stack just to follow a recipe.
|
||||
3. Make the changed flow keyboard accessible with visible focus, meaningful labels,
|
||||
appropriate contrast, and correct focus restoration. Respect reduced motion.
|
||||
4. Fit layout and content to supported viewport sizes. Use existing spacing/type
|
||||
scales and readable hierarchy; choose a coherent direction only for new designs.
|
||||
Fonts, borders, shadows, and easing are choices, not universal bans or mandates.
|
||||
5. Inspect the rendered result and exercise the changed interaction using the available
|
||||
product browser/device tools. Check relevant keyboard and responsive behavior.
|
||||
Apply [shared verification](../../protocols/workflow.md#verification); do not impose
|
||||
every reference checklist on a small UI edit.
|
||||
6. Report the working result and verification limits.
|
||||
|
||||
## References on demand
|
||||
|
||||
- [Design recipes](references/design-recipes.md): typography, spatial choices,
|
||||
color, motion, and component examples. Adapt them to the existing design.
|
||||
- [Accessibility](references/accessibility-checklist.md): relevant semantic,
|
||||
keyboard, focus, contrast, and motion checks.
|
||||
- [Components](references/component-patterns.md): optional React recipes.
|
||||
- [Animation](references/animation-playbook.md): optional advanced motion.
|
||||
- [Review checklist](references/review-checklist.md): use selected items for a
|
||||
requested polish/audit pass, not as mandatory gates.
|
||||
|
||||
Aim for comfortable touch targets, often 44px. WCAG 2.2 AA target-size minimum is
|
||||
24px with defined exceptions; distinguish that standard from stricter design goals.
|
||||
@@ -1,6 +1,7 @@
|
||||
# WCAG 2.1 AA Accessibility Audit Guide
|
||||
# Accessibility audit reference
|
||||
|
||||
Comprehensive checklist for building accessible web interfaces. Every requirement maps to WCAG 2.1 Level AA success criteria.
|
||||
Select relevant checks for the changed flow. This reference mixes WCAG requirements
|
||||
with stricter design recommendations; those recommendations are not AA gates.
|
||||
|
||||
---
|
||||
|
||||
@@ -141,8 +142,11 @@ The first rule of ARIA: do not use ARIA if a native HTML element provides the be
|
||||
}
|
||||
```
|
||||
|
||||
- Focus indicators must meet 3:1 contrast ratio against adjacent colors (WCAG 2.4.11)
|
||||
- Minimum focus indicator area: at least 2px perimeter around the component
|
||||
- Keep focus visible and not entirely obscured by authored content
|
||||
([WCAG 2.2 AA 2.4.11](https://www.w3.org/WAI/WCAG22/Understanding/focus-not-obscured-minimum.html)).
|
||||
- A 2px-perimeter area and 3:1 focused/unfocused contrast are stronger
|
||||
[AAA focus-appearance criteria](https://www.w3.org/WAI/WCAG22/Understanding/focus-appearance.html),
|
||||
not the definition of AA 2.4.11. Apply non-text contrast where required.
|
||||
|
||||
### Modal Focus Trapping
|
||||
|
||||
@@ -300,18 +304,14 @@ panel: id="panel-id", role="region", aria-labelledby="trigger-id"
|
||||
|
||||
## 7. prefers-reduced-motion
|
||||
|
||||
### Global Reset
|
||||
### Targeted motion reduction
|
||||
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
html { scroll-behavior: auto; }
|
||||
/* Apply to components with nonessential movement; keep state feedback. */
|
||||
.decorative-motion { animation: none; }
|
||||
.moving-control { transition-property: color, background-color, opacity; }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -402,7 +402,7 @@ npx playwright test --project=accessibility
|
||||
| `aria-hidden="true"` on focusable elements | Remove from tab order or remove `aria-hidden` |
|
||||
| Missing `lang` attribute on `<html>` | Set `<html lang="en">` (or appropriate language code) |
|
||||
| Autoplaying video/audio with sound | Require user interaction to start, or mute by default with controls |
|
||||
| Tiny tap targets on mobile | Minimum 44x44 CSS pixels for touch targets |
|
||||
| Tiny tap targets on mobile | Aim for 44px touch targets; AA 2.5.8 minimum is 24px with exceptions |
|
||||
| Using `title` attribute as primary label | `title` is unreliable; use `aria-label` or visible `<label>` |
|
||||
| Links that say "click here" or "read more" | Descriptive link text: "Read the accessibility guide" |
|
||||
| Missing form error summary | On submit failure, show summary of all errors at top of form |
|
||||
|
||||
@@ -526,11 +526,12 @@ Use the playback speed controls (25%, 10%) for detailed inspection.
|
||||
### Real device testing
|
||||
|
||||
Touch interactions feel completely different on a real phone versus a trackpad simulator.
|
||||
Always test gestures, drag interactions, and spring animations on physical devices.
|
||||
For gesture-sensitive changes, test on a physical device when available; otherwise
|
||||
use the available simulator/emulator and state the verification limit.
|
||||
|
||||
### Fresh eyes check
|
||||
|
||||
Review animations with fresh eyes the next day. What felt right at 11pm during
|
||||
For a dedicated polish pass, a later review can help. What felt right at 11pm during
|
||||
development often feels too fast, too slow, or too dramatic the next morning.
|
||||
|
||||
### The checklist
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
# Design recipes
|
||||
|
||||
Optional examples for new designs. Existing components, tokens, user preferences,
|
||||
and platform conventions override these recipes. Aesthetic suggestions are not
|
||||
accessibility requirements or completion gates. Read only relevant sections.
|
||||
|
||||
### 2. The Priority Stack
|
||||
|
||||
When implementing UI, work through these priorities in order. Higher priorities are non-negotiable; lower priorities are polish that compounds quality.
|
||||
|
||||
| Priority | Level | What It Means |
|
||||
|----------|-------|---------------|
|
||||
| **Accessibility** | CRITICAL | Contrast 4.5:1, keyboard nav, ARIA semantics, visible focus rings. Ship nothing that excludes users. |
|
||||
| **Performance** | HIGH | WebP/AVIF images, lazy loading below fold, CLS < 0.1, transform-only animations on the compositor thread. |
|
||||
| **Typography** | HIGH | Font smoothing, text-wrap balance/pretty, tabular-nums for data, 65ch max line length. |
|
||||
| **Layout & Spatial** | HIGH | 4/8px grid, concentric border radius, optical alignment over geometric. |
|
||||
| **Color & Theme** | MEDIUM | HSL custom properties, semantic tokens, dark mode pairs tested separately. |
|
||||
| **Motion & Interaction** | MEDIUM | Frequency-based animation decisions, 150-300ms durations, ease-out default. |
|
||||
| **Polish & Details** | LOW | Layered shadows over borders, press feedback on buttons, staggered enter animations. |
|
||||
|
||||
Never skip a CRITICAL/HIGH item to chase a LOW item. A beautifully animated button that fails keyboard navigation is a net negative.
|
||||
|
||||
---
|
||||
|
||||
### 3. Aesthetic Direction
|
||||
|
||||
For a new design, choose a direction suited to the audience and task. The most common failure mode in AI-generated UI is convergence on the same safe, forgettable look.
|
||||
|
||||
### Pick a Tone
|
||||
|
||||
Choose one and commit fully:
|
||||
|
||||
- **Brutally minimal** — generous whitespace, monospace type, stark contrast, near-zero decoration
|
||||
- **Maximalist chaos** — layered textures, clashing type scales, dense information, intentional visual noise
|
||||
- **Retro-futuristic** — CRT glow effects, monospace terminals, scan lines, neon on dark
|
||||
- **Organic / natural** — earth tones, rounded shapes, paper textures, hand-drawn accents
|
||||
- **Luxury / refined** — serif headlines, muted palettes, ample negative space, subtle gold or cream accents
|
||||
- **Editorial / magazine** — dramatic type hierarchy, full-bleed imagery, grid-breaking layouts
|
||||
- **Playful / bold** — bright primaries, chunky borders, exaggerated shadows, bouncy motion
|
||||
|
||||
### Match Complexity to Vision
|
||||
|
||||
Maximalist design demands elaborate code — layered backgrounds, complex grid structures, multiple font stacks. Minimalist design demands surgical precision — every pixel of spacing matters more when there's nothing to hide behind.
|
||||
|
||||
### Visual Texture
|
||||
|
||||
Add depth through: gradient meshes, noise/grain overlays (`filter: url(#noise)`), layered transparencies, subtle background patterns, duotone image treatments.
|
||||
|
||||
Use existing project tokens and components even without a DESIGN.md.
|
||||
|
||||
---
|
||||
|
||||
### 4. Typography Essentials
|
||||
|
||||
Typography is the single highest-leverage design element. Get it right and mediocre layouts still feel good. Get it wrong and nothing else saves it.
|
||||
|
||||
### Root Setup
|
||||
|
||||
```css
|
||||
html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
```
|
||||
|
||||
Apply font smoothing to the root layout. On macOS, the default sub-pixel rendering makes text appear heavier than the designer intended.
|
||||
|
||||
### Text Wrapping
|
||||
|
||||
```css
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
p, li, dd, blockquote {
|
||||
text-wrap: pretty;
|
||||
}
|
||||
```
|
||||
|
||||
`balance` distributes heading lines evenly. `pretty` avoids orphaned words in body text.
|
||||
|
||||
### Numeric Display
|
||||
|
||||
```css
|
||||
.data-value, .price, .counter, [data-numeric] {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
```
|
||||
|
||||
Use `tabular-nums` for any number that updates dynamically — prices, counters, table columns. Without it, layout shifts as digit widths change.
|
||||
|
||||
### Scale and Rhythm
|
||||
|
||||
- **Base size**: 16px minimum for body text. Never go below 14px for any readable content.
|
||||
- **Line height**: 1.5-1.75 for body text, 1.1-1.3 for large headings.
|
||||
- **Max line length**: `max-width: 65ch` for body text. Long lines destroy readability.
|
||||
- **Type scale**: Pick a consistent scale and stick to it: 12 / 14 / 16 / 18 / 24 / 32 / 48 / 64.
|
||||
|
||||
### Font Pairing
|
||||
|
||||
Pair a distinctive display font with a refined body font. The display font carries personality; the body font carries readability. Use `font-weight` for hierarchy within a family:
|
||||
|
||||
- **Headings**: 600-700 (semibold to bold)
|
||||
- **Body**: 400 (regular)
|
||||
- **Labels / UI**: 500 (medium)
|
||||
|
||||
Always include font stack fallbacks:
|
||||
|
||||
```css
|
||||
--font-display: "Instrument Serif", "Georgia", serif;
|
||||
--font-body: "Söhne", "Helvetica Neue", sans-serif;
|
||||
--font-mono: "JetBrains Mono", "Fira Code", monospace;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Color & Theme
|
||||
|
||||
### HSL Custom Properties (shadcn Pattern)
|
||||
|
||||
```css
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
```
|
||||
|
||||
Define semantic tokens: primary, secondary, destructive, muted, accent, background, foreground. Reference colors by semantic name — never hardcode hex values in components.
|
||||
|
||||
### Dark Mode
|
||||
|
||||
```css
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
/* ... desaturated, lighter tonal variants — NOT simply inverted */
|
||||
}
|
||||
```
|
||||
|
||||
Dark mode is not "invert colors." Use desaturated, lighter tonal variants. Backgrounds go dark but not pure black (`#000`). Text goes light but not pure white (`#fff`). Test contrast separately for dark mode — what passes in light may fail in dark.
|
||||
|
||||
### Contrast Requirements
|
||||
|
||||
- **WCAG AA minimum**: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+ regular)
|
||||
- Never convey information by color alone — always pair with an icon, label, or pattern
|
||||
- Test with browser devtools contrast checker or axe-core
|
||||
|
||||
### Color Confidence
|
||||
|
||||
Dominant colors with sharp accents outperform timid, evenly-distributed palettes. Pick one or two hero colors and let the rest of the palette recede. A confident palette has clear hierarchy; an uncertain palette spreads color evenly and feels flat.
|
||||
|
||||
---
|
||||
|
||||
## 6. Spatial Design
|
||||
|
||||
### Concentric Border Radius
|
||||
|
||||
This is the single most common thing that makes nested UI elements feel "off":
|
||||
|
||||
```
|
||||
outer_radius = inner_radius + padding
|
||||
```
|
||||
|
||||
```css
|
||||
/* Correct: concentric */
|
||||
.card { border-radius: 16px; padding: 8px; }
|
||||
.card-inner { border-radius: 8px; } /* 16 - 8 = 8 */
|
||||
|
||||
/* Wrong: same radius on parent and child */
|
||||
.card { border-radius: 12px; }
|
||||
.card-inner { border-radius: 12px; } /* Looks bloated */
|
||||
```
|
||||
|
||||
When geometric centering looks off, align optically. Play/pause icons, dropdown carets, and asymmetric glyphs often need 1-2px manual nudges to look centered.
|
||||
|
||||
### Shadows Over Borders
|
||||
|
||||
Layer multiple transparent `box-shadow` values for natural depth instead of using borders:
|
||||
|
||||
```css
|
||||
.elevated {
|
||||
box-shadow:
|
||||
0 1px 2px rgba(0, 0, 0, 0.04),
|
||||
0 2px 4px rgba(0, 0, 0, 0.04),
|
||||
0 4px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
```
|
||||
|
||||
Multiple shadows at different spreads mimic how light works. A single hard shadow looks artificial.
|
||||
|
||||
### Image Outlines
|
||||
|
||||
Add a subtle inset outline to images and media for consistent depth against varied backgrounds:
|
||||
|
||||
```css
|
||||
img, video {
|
||||
outline: 1px solid rgba(0, 0, 0, 0.06);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
```
|
||||
|
||||
### Spacing Scale
|
||||
|
||||
Use a 4px / 8px base incremental system. A 4px-based scale is one possible default:
|
||||
|
||||
`4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128`
|
||||
|
||||
### Hit Areas
|
||||
|
||||
Aim for comfortable 44x44px touch targets where practical. If the visual element is smaller, extend the hit area with a pseudo-element:
|
||||
|
||||
```css
|
||||
.small-button::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -8px;
|
||||
}
|
||||
```
|
||||
|
||||
### Z-Index Scale
|
||||
|
||||
Define a layered scale and never use arbitrary values:
|
||||
|
||||
```css
|
||||
--z-base: 0;
|
||||
--z-dropdown: 10;
|
||||
--z-sticky: 20;
|
||||
--z-overlay: 40;
|
||||
--z-modal: 100;
|
||||
--z-toast: 1000;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. Motion & Interaction
|
||||
|
||||
### The Frequency-Based Decision Framework
|
||||
|
||||
This is the most important mental model for animation decisions:
|
||||
|
||||
| Frequency | Examples | Animation |
|
||||
|-----------|----------|-----------|
|
||||
| **100+ times/day** | Keyboard shortcuts, command palette actions, tab switches | **None.** Zero animation. Instant. |
|
||||
| **Tens of times/day** | Hover effects, list item navigation, toggles | **Remove or drastically reduce.** 50-100ms max. |
|
||||
| **Occasional** | Modals, drawers, toasts, page transitions | **Standard animation.** 150-300ms. |
|
||||
| **Rare / first-time** | Onboarding, celebrations, empty states | **Can add delight.** 300-500ms, more elaborate. |
|
||||
|
||||
High-frequency animations feel sluggish. Low-frequency animations without motion feel jarring. Match the animation budget to usage frequency.
|
||||
|
||||
### Custom Easing Curves
|
||||
|
||||
Custom easing curves are an option when motion helps the interaction:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
|
||||
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
```
|
||||
|
||||
### Duration Guide
|
||||
|
||||
| Element | Duration |
|
||||
|---------|----------|
|
||||
| Buttons, toggles | 100-160ms |
|
||||
| Tooltips | 125-200ms |
|
||||
| Dropdowns, popovers | 150-250ms |
|
||||
| Modals, drawers | 200-500ms |
|
||||
| Page transitions | 250-400ms |
|
||||
|
||||
Keep motion responsive; choose duration and easing for the interaction.
|
||||
|
||||
### Enter/Exit Asymmetry
|
||||
|
||||
Exits should be softer and faster than enters. An enter animation at 250ms should have its exit at 150-200ms.
|
||||
|
||||
### Split and Stagger Enter Animations
|
||||
|
||||
When multiple elements enter the viewport, stagger them by semantic chunks with ~50-100ms delay:
|
||||
|
||||
```css
|
||||
.stagger-item {
|
||||
animation: fadeSlideIn 300ms var(--ease-out) both;
|
||||
}
|
||||
.stagger-item:nth-child(1) { animation-delay: 0ms; }
|
||||
.stagger-item:nth-child(2) { animation-delay: 60ms; }
|
||||
.stagger-item:nth-child(3) { animation-delay: 120ms; }
|
||||
```
|
||||
|
||||
### Scale Animations
|
||||
|
||||
Never animate from `scale(0)`. Start from `scale(0.9)` or higher, combined with opacity:
|
||||
|
||||
```css
|
||||
@keyframes scaleIn {
|
||||
from { opacity: 0; transform: scale(0.95); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
```
|
||||
|
||||
### Press Feedback
|
||||
|
||||
Optional press feedback, when consistent with the design and reduced-motion policy:
|
||||
|
||||
```css
|
||||
button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
```
|
||||
|
||||
### Interruptibility
|
||||
|
||||
Use CSS transitions (not keyframe animations) for interactive state changes. Transitions can be interrupted mid-way; keyframes cannot. This matters for hover states, toggles, and any element the user might interact with rapidly.
|
||||
|
||||
### Popover Origin
|
||||
|
||||
Make popovers transform-origin aware — they should grow from their trigger element, not from center. Exception: modals always originate from center.
|
||||
|
||||
### Tooltip Hover Delay
|
||||
|
||||
Skip the tooltip delay on subsequent hovers. If the user has already waited for one tooltip, show the next one immediately.
|
||||
|
||||
### Reduced Motion
|
||||
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html { scroll-behavior: auto; }
|
||||
.decorative-motion { animation: none; }
|
||||
.moving-control { transition-property: color, background-color, opacity; }
|
||||
}
|
||||
```
|
||||
|
||||
Respect `prefers-reduced-motion`. Reduce animations — don't eliminate opacity and color transitions entirely, as those provide important feedback.
|
||||
|
||||
### Hover Gate
|
||||
|
||||
Gate hover animations behind a media query so touch devices don't trigger stuck hover states:
|
||||
|
||||
```css
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
.card:hover { transform: translateY(-2px); }
|
||||
}
|
||||
```
|
||||
|
||||
> Reference `animation-playbook.md` for deep dives on spring physics, gesture-driven animation, and complex choreography.
|
||||
|
||||
---
|
||||
|
||||
### 8. Component Craft
|
||||
|
||||
### Primitives
|
||||
|
||||
In a React project already using Radix, its primitives can provide accessible foundations. Use CVA (class-variance-authority) for type-safe component variants:
|
||||
|
||||
```tsx
|
||||
import { cva } from "class-variance-authority";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
|
||||
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||
},
|
||||
size: {
|
||||
sm: "h-9 px-3 text-sm",
|
||||
default: "h-10 px-4 py-2",
|
||||
lg: "h-11 px-8 text-lg",
|
||||
},
|
||||
},
|
||||
defaultVariants: { variant: "default", size: "default" },
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Button
|
||||
|
||||
- Scale on press (`transform: scale(0.97)` on `:active`)
|
||||
- Visible focus ring (never `outline: none` without replacement)
|
||||
- Loading state with spinner replacing label, maintaining button dimensions
|
||||
- Disabled state at `opacity: 0.5` with `pointer-events: none`
|
||||
|
||||
### Card
|
||||
|
||||
- Concentric border radius between card and inner elements
|
||||
- Layered shadows (not borders) for depth
|
||||
- Hover state: subtle elevation change (`translateY(-1px)` + shadow increase)
|
||||
|
||||
### Dialog / Modal
|
||||
|
||||
- Focus trap (keyboard cannot escape to elements behind)
|
||||
- ESC to close, click outside overlay to close
|
||||
- `transform-origin: center`, fade + scale enter animation
|
||||
- `aria-modal="true"`, `role="dialog"`, `aria-labelledby`
|
||||
|
||||
### Form
|
||||
|
||||
- Visible labels always — never placeholder-only inputs
|
||||
- Error messages near the field with `aria-live="polite"` for screen readers
|
||||
- Progressive disclosure: show advanced fields only when needed
|
||||
- Use the project's form and runtime validation libraries
|
||||
|
||||
### Theming
|
||||
|
||||
Use the project's semantic color tokens. Wrap client-interactive components in server components for Next.js App Router compatibility.
|
||||
|
||||
> Reference `component-patterns.md` for the full component catalog with copy-paste implementations.
|
||||
|
||||
---
|
||||
|
||||
## 9. Accessibility Essentials
|
||||
|
||||
### Semantic HTML First
|
||||
|
||||
Use `<button>`, `<nav>`, `<main>`, `<header>`, `<footer>`, `<article>`, `<section>` before reaching for ARIA. A `<button>` gives you keyboard handling, focus management, and screen reader semantics for free. A `<div onClick>` gives you none of that.
|
||||
|
||||
### Keyboard Navigation
|
||||
|
||||
- **Tab / Shift+Tab**: move between focusable elements
|
||||
- **Enter / Space**: activate buttons and links
|
||||
- **Arrow keys**: navigate within lists, menus, tabs, radio groups
|
||||
- **Escape**: close modals, popovers, dropdowns
|
||||
- **Home / End**: jump to first/last item in lists
|
||||
|
||||
### Focus Management
|
||||
|
||||
- Visible focus rings on all interactive elements — NEVER use `outline: none` without a replacement
|
||||
- Trap focus inside modals (Tab wraps within the modal, not behind it)
|
||||
- Restore focus to the trigger element when a modal/popover closes
|
||||
- Use `focus-visible` to show rings only for keyboard users, not mouse clicks:
|
||||
|
||||
```css
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--ring);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
```
|
||||
|
||||
### ARIA Attributes
|
||||
|
||||
- `aria-label` for icon-only buttons: `<button aria-label="Close menu">X</button>`
|
||||
- `aria-labelledby` to associate headings with sections
|
||||
- `aria-describedby` to link help text or error messages to inputs
|
||||
- `aria-live="polite"` for dynamic content updates (toast messages, form errors)
|
||||
- `aria-hidden="true"` for decorative elements (icons next to text labels)
|
||||
- `aria-expanded` for toggleable elements (dropdowns, accordions)
|
||||
|
||||
### Color and Contrast
|
||||
|
||||
- WCAG AA: 4.5:1 for normal text, 3:1 for large text
|
||||
- Never use color as the sole indicator — pair with icons, text, or patterns
|
||||
- Test in both light and dark modes
|
||||
|
||||
### Images and Media
|
||||
|
||||
- Descriptive `alt` text for meaningful images: `alt="Dashboard showing 23% revenue growth"`
|
||||
- Empty `alt=""` for purely decorative images
|
||||
- Captions for video, transcripts for audio
|
||||
|
||||
### Navigation Aids
|
||||
|
||||
- **Skip link**: first focusable element, hidden until focused:
|
||||
|
||||
```html
|
||||
<a href="#main-content" class="sr-only focus:not-sr-only">
|
||||
Skip to main content
|
||||
</a>
|
||||
```
|
||||
|
||||
- **Heading hierarchy**: sequential h1 through h6, no level skips. One `<h1>` per page.
|
||||
|
||||
### Touch Targets
|
||||
|
||||
- Aim for 44x44px touch targets; WCAG 2.2 AA minimum is 24px with exceptions
|
||||
- 8px minimum spacing between adjacent touch targets
|
||||
- Extend small visual elements with invisible padding or pseudo-elements
|
||||
|
||||
### Testing
|
||||
|
||||
- **Automated**: relevant axe-core checks when available; a Lighthouse score alone does not prove conformance
|
||||
- **Manual**: full keyboard-only navigation test
|
||||
- **Screen reader**: test with VoiceOver (macOS) or NVDA (Windows)
|
||||
- **Visual**: zoom to 200%, check nothing breaks or overlaps
|
||||
|
||||
> Reference `accessibility-checklist.md` for the full audit guide with pass/fail criteria.
|
||||
|
||||
---
|
||||
@@ -1,6 +1,8 @@
|
||||
# Pre-Delivery Review Checklist
|
||||
|
||||
Extended 30-item checklist for UI implementation quality. Run through this before marking any UI task as complete.
|
||||
Optional polish checklist. Select items relevant to the changed flow. Existing design
|
||||
conventions override aesthetic suggestions; accessibility requirements remain applicable.
|
||||
Do not run every item for a small edit.
|
||||
|
||||
## Typography (6 items)
|
||||
|
||||
|
||||
@@ -1,111 +1,26 @@
|
||||
---
|
||||
name: junior-to-senior
|
||||
description: >
|
||||
Adversarial senior-engineer review for agent-generated plans, designs, and architectures.
|
||||
Diagnoses altitude failures (fog vs tunnel) using live codebase research and current SOTA best practices, then rewrites into a scoped senior plan.
|
||||
Use when asked to review a plan, "senior review", "review this like a staff engineer", or before executing high-blast-radius plans.
|
||||
concerns: [system-one-balance]
|
||||
Review and improve a proposed plan or architecture when asked for a senior review, a staff-engineer review, or review of the plan.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Junior to Senior
|
||||
# Plan review
|
||||
|
||||
Assume the plan in front of you was written by a capable junior: fluent, confident, and trained on the past. Build a senior reviewer grounded in **this codebase as it actually exists** and **the state of the art today**, then tear down the plan and rebuild it.
|
||||
1. Identify the plan and its intended outcome. Inspect the relevant code, callers,
|
||||
dependency versions, and prior decisions. Cite file/line evidence for code claims.
|
||||
2. Find consequential gaps: vague goals, unstated contracts, unowned failure cases,
|
||||
scope mismatch, migration risk, or detail concentrated on easy parts.
|
||||
3. Verify load-bearing external assumptions against primary sources for the installed
|
||||
versions. Research only what can change a material decision; unavailable evidence
|
||||
stays unverified rather than becoming a blocker.
|
||||
4. Classify demonstrated defects, material improvements, and optional polish.
|
||||
Do not invent findings to look adversarial or copy the whole plan into the response.
|
||||
5. Provide concrete remedies. Rewrite the plan when requested or when a short revision
|
||||
makes the recommendations actionable; preserve sound choices and user intent.
|
||||
|
||||
This skill exists because agent-generated plans fail at two altitudes:
|
||||
- **Fog**: The plan describes the high level fine ("add caching", "handle auth", "make it scalable") but never commits on the hard parts. No interfaces, no data shapes, no failure handling, no named libraries.
|
||||
- **Tunnel**: The plan dives into function signatures and file diffs without product vision, scoping boundaries, or justification for why this approach beats the boring alternative.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Review governing reference playbooks:
|
||||
- [references/review-rubric.md](references/review-rubric.md) for altitude diagnostics, vague-phrase blacklists, and severity definitions.
|
||||
- [references/research-playbook.md](references/research-playbook.md) for codebase inspection queries, SOTA verification, and source ranking.
|
||||
2. Ground all critique in concrete evidence:
|
||||
- Codebase claims cite specific `file:line`.
|
||||
- SOTA claims cite primary documentation, release notes, or RFCs with dates.
|
||||
- If web research is unavailable, mark findings `[training-data, unverified]`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Capture & Freeze the Artifact**:
|
||||
- Identify the target plan: a plan just produced in conversation, a pasted RFC/design doc, or a repository document.
|
||||
- Restate or quote the artifact in full before reviewing so the review targets a fixed specification.
|
||||
- If no plan exists, generate the junior draft or ask the user for their initial requirements first.
|
||||
2. **Altitude Diagnostic**:
|
||||
- Classify the artifact: **fog**, **tunnel**, or **mixed**.
|
||||
- Fog test: Can a competent engineer begin implementation tomorrow without making unstated product/architecture decisions?
|
||||
- Tunnel test: Does the plan state who this is for, what success means, what is out of scope, and why this beats the obvious alternative?
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Construct the Senior Profile
|
||||
- **Domain Extraction**: Identify the 2–5 load-bearing technical domains the plan touches.
|
||||
- **Codebase Research**: Inspect repository lockfiles/manifests, actual dependency versions, existing conventions, data models, and constraints.
|
||||
- **SOTA Web Research**: Query current documentation and changelogs for deprecations, supersessions, or known postmortem failure modes.
|
||||
|
||||
### Step 2: Adversarial Critique
|
||||
- Challenge every vague term ("simple", "scalable", "robust", "handle gracefully").
|
||||
- Specify concrete data shapes, boundary contracts, migration paths, and rollback strategies.
|
||||
- Assign findings to three strict severity tiers:
|
||||
- **Blocker**: The plan fails as written or violates project invariants.
|
||||
- **Major**: Functions, but is significantly worse than current best practice or repo conventions.
|
||||
- **Minor**: Non-blocking improvements and ergonomic polish.
|
||||
- Acknowledge what the junior plan got right (credit preserved in rewrite).
|
||||
|
||||
### Step 3: Promote the Plan (v2)
|
||||
Rewrite the plan into senior form:
|
||||
1. **Goal & Non-Goals**: Crisp product intent and explicit out-of-scope boundaries.
|
||||
2. **Decisions & Rationale**: Each load-bearing choice with chosen option, version, rejected alternatives, and cited evidence.
|
||||
3. **Design at Right Altitude**: Exact contracts, schemas, and error boundaries for hard parts; coarse strokes for routine boilerplate.
|
||||
4. **Sequencing**: Measurable milestones with observable verification gates.
|
||||
5. **Risks & Rollback**: Blast-radius assessment and escape hatches.
|
||||
6. **Open Questions for Human**: Genuine product decisions requiring user judgment (the senior scopes; it does not fabricate product intent).
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT second-guess routine developer requests with unnecessary reviews.
|
||||
- If the user asks for immediate, direct execution ("implement this now", "fix bug"), proceed directly without forcing an unsolicited junior-to-senior review pass.
|
||||
- Never fabricate synthetic blockers just to appear rigorous; if a plan is solid, state "this plan holds" and proceed.
|
||||
- **Calibrated Advisories**:
|
||||
- Offer the promoted plan as an upgrade option; do not silently overwrite the user's intent.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Deliver the review and promoted plan formatted as two structured sections:
|
||||
|
||||
```markdown
|
||||
## Senior Review
|
||||
|
||||
**Altitude diagnosis:** fog | tunnel | mixed — [one-sentence justification]
|
||||
|
||||
### Blockers
|
||||
- [B1] Finding — evidence (file:line or source+date) — concrete fix.
|
||||
|
||||
### Major
|
||||
- [M1] Finding — evidence — concrete fix.
|
||||
|
||||
### Minor
|
||||
- [m1] Finding — polish recommendation.
|
||||
|
||||
### What the junior got right
|
||||
- [Preserved choices and good foundations]
|
||||
|
||||
---
|
||||
|
||||
## Promoted Plan (v2)
|
||||
[Goal, Decisions, Scoped Architecture, Milestones, Rollback, Open Questions]
|
||||
|
||||
## Delta Summary
|
||||
- 3–6 concise bullets explaining key upgrades from v1 to v2.
|
||||
```
|
||||
Use the [research playbook](references/research-playbook.md) and
|
||||
[rubric](references/review-rubric.md) only for relevant questions. A review can be
|
||||
brief when the plan is sound. Do not force this workflow onto a direct implementation
|
||||
request; focused risk inspection can be part of implementing it. Follow
|
||||
[shared workflow](../../protocols/workflow.md).
|
||||
@@ -4,7 +4,7 @@ Reference for Phase 1 of the `junior-to-senior` skill: how the senior earns expe
|
||||
|
||||
## Track 1: Code research
|
||||
|
||||
Goal: know what is *true here* before judging the plan against it. Prefer a context-isolated explore subagent for broad sweeps; bring back conclusions, not file dumps.
|
||||
Goal: know what is *true here* before judging the plan against it. Use focused searches and return conclusions with evidence rather than file dumps. Delegate only when the task or repository instructions authorize it.
|
||||
|
||||
Checklist per plan:
|
||||
|
||||
@@ -29,7 +29,7 @@ For each load-bearing decision, run the subset that applies:
|
||||
- `<library> security advisory` / check the project's GitHub security tab — non-negotiable for auth, crypto, parsing, and anything touching user input.
|
||||
- `site:github.com <library> issues <feature>` — maintainer-stated direction and known footguns.
|
||||
|
||||
Always pin the current year or "latest" into queries — undated queries return the same era the model was trained on, which defeats the point.
|
||||
Query the installed version first; include dates when freshness matters. Latest-version guidance may not apply to the pinned dependency.
|
||||
|
||||
### Source quality ranking
|
||||
|
||||
@@ -51,7 +51,7 @@ Every cited source gets a date check. A "best practices" article from before the
|
||||
### When to stop
|
||||
|
||||
- Each load-bearing decision has either one primary source confirming/refuting it, or two independent secondary sources agreeing.
|
||||
- Two consecutive searches on a decision return nothing newer than what you knew — the world likely didn't move; mark it confirmed-by-absence and move on.
|
||||
- If searches yield no useful evidence, mark the decision unverified and move on; absence of results is not confirmation.
|
||||
- Diminishing returns: research budget belongs on blockers and majors, not minors. If a finding would be minor either way, don't research it.
|
||||
|
||||
### No web access
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
name: kicad-pcb-design
|
||||
description: >
|
||||
Design, inspect, route, and verify printed circuit boards (PCBs) in KiCad using the KiCAD MCP server and kicad-cli.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# KiCad PCB Design
|
||||
|
||||
Design, inspect, route, and verify printed circuit boards using the KiCAD Model Context Protocol (MCP) server or `kicad-cli`.
|
||||
Follow the [shared workflow](../../protocols/workflow.md).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
KiCad and its Python scripting module (`pcbnew`) must be installed on the host:
|
||||
```bash
|
||||
sudo pacman -S kicad kicad-library kicad-library-3d
|
||||
```
|
||||
The KiCad MCP server is built and located at `~/Projects/work/KiCAD-MCP-Server`.
|
||||
To start the MCP server manually or via configuration:
|
||||
- Node runner: `node ~/Projects/work/KiCAD-MCP-Server/dist/index.js`
|
||||
- Python environment: `~/Projects/work/KiCAD-MCP-Server/.venv/bin/python`
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Schematic Capture & Part Selection**
|
||||
- Use standard KiCad symbol libraries (`Device`, `Connector`, `Regulator_Linear`, etc.).
|
||||
- When using MCP:
|
||||
- Search parts: `search_symbols`, `search_jlcpcb_parts`
|
||||
- Add components: `add_schematic_component` or `batch_add_components`
|
||||
- Connect nets: `add_schematic_wire`, `add_net_label`
|
||||
- Run ERC: `run_erc` to catch floating inputs or unpowered pins.
|
||||
- When using CLI/files:
|
||||
- Work directly with `.kicad_sch` files or compile from netlists.
|
||||
- Validate: `kicad-cli sch erc project.kicad_sch`
|
||||
|
||||
2. **Board Edge & Physical Stackup**
|
||||
- Define board outline on `Edge.Cuts` with mounting holes (e.g. M2.5 or M3 with keepouts).
|
||||
- Standard 2-layer or 4-layer stackup:
|
||||
- Default thickness: 1.6 mm FR4, 1 oz Cu (35 µm).
|
||||
- Signal trace width: `0.25 mm` (10 mil).
|
||||
- Power trace width: `0.5 mm` – `1.0 mm` depending on current.
|
||||
- Clearance: minimum `0.2 mm` (8 mil) for low-cost fab houses (JLCPCB, PCBWay).
|
||||
|
||||
3. **Placement & Routing**
|
||||
- **Bypass capacitors:** Place ceramic decoupling caps (0.1 µF) as close as physically possible to IC $V_{CC}$ / GND pins.
|
||||
- **Ground plane:** Fill top and bottom (or inner) layers with solid GND copper pours (`zone`). Stitch GND with vias near return current paths.
|
||||
- **Routing:**
|
||||
- Interactive/MCP routing: invoke routing tools or export DSN for Freerouting (`run_freerouter`).
|
||||
- Avoid 90° trace corners; use 45° bends.
|
||||
|
||||
4. **Empirical Verification ("The engine measures")**
|
||||
- **Design Rule Check (DRC):**
|
||||
- MCP: `run_drc`
|
||||
- CLI:
|
||||
```bash
|
||||
kicad-cli pcb drc --output drc_report.json project.kicad_pcb
|
||||
```
|
||||
- Zero unapproved clearance, unrouted net, or courtyard collisions before tapeout.
|
||||
|
||||
5. **Fabrication & Export**
|
||||
- Generate production manufacturing artifacts:
|
||||
```bash
|
||||
# Gerber & Drill files
|
||||
kicad-cli pcb export gerbers -o gerbers/ project.kicad_pcb
|
||||
kicad-cli pcb export drill -o gerbers/ project.kicad_pcb
|
||||
# 2D/3D visual renders for human review
|
||||
kicad-cli pcb render -o board_preview.png project.kicad_pcb
|
||||
```
|
||||
- Generate BOM and Centroid / Pick-and-place (CPL) for assembly.
|
||||
+21
-81
@@ -1,88 +1,28 @@
|
||||
---
|
||||
name: review
|
||||
description: >
|
||||
Adversarial pre-implementation review of SPEC.md. Attempts to refute the spec before code is written,
|
||||
grounding findings in codebase evidence, §R research, and current best practices.
|
||||
Use when asked to "review spec", "red-team spec", "is this plan sound", or before high-blast-radius builds.
|
||||
concerns: [system-one-balance]
|
||||
Review an existing SPEC.md before implementation when asked to review or red-team the spec, or when spec review is part of the authorized task.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Review — Refute the Spec Before Build
|
||||
# Spec review
|
||||
|
||||
Every finding cites evidence — `file:line` or an authoritative source. No evidence → label `[unverified]`. A defect you cannot prove is a note, not a blocker.
|
||||
1. Read the relevant goals, constraints, interfaces, research, invariants, and tasks.
|
||||
Inspect implementations and callers affected by the proposed change.
|
||||
2. Test consequential assumptions against code, existing tests, and current primary
|
||||
sources where needed. Look for mismatched requirements, contract conflicts,
|
||||
missing failure behavior, and tasks without observable completion evidence.
|
||||
For substantial specs, a fresh-context pass can expose assumptions inherited
|
||||
from drafting. When an isolated reviewer is available, give it the spec, relevant
|
||||
source, and review criteria without the drafting conversation. If isolation is
|
||||
unavailable, reread the spec as a standalone document and note that the review
|
||||
shared drafting context. Skip this extra pass for small or straightforward specs.
|
||||
3. Report demonstrated defects with file/line or source evidence and concrete remedies.
|
||||
Distinguish material hardening from optional notes; unverified claims stay notes.
|
||||
4. Draft useful invariant/interface/task amendments when needed. Do not edit a spec
|
||||
during a report-only review; apply amendments only within an authorized edit.
|
||||
5. Give a go/no-go verdict if requested or useful for the pending implementation.
|
||||
A sound spec needs a short conclusion, not fabricated blockers.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Review governing invariants:
|
||||
- Review the *spec*, not conversational memory.
|
||||
- An LLM cannot self-correct reliably on vibes alone; the reviewer must anchor to external oracles (code, tests, §R).
|
||||
- Skip review for trivial, reversible edits; right-size review effort to blast radius.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Capture the Spec**:
|
||||
- Ingest all active sections of `SPEC.md`: §G, §C, §I, §R, §V, §T, §B.
|
||||
2. **Construct the Reviewer Profile**:
|
||||
- Inspect the codebase modules touched by the spec to verify existing patterns and constraints.
|
||||
- Check §R research findings: any spec assertion contradicting §R is an immediate finding.
|
||||
- For unverified best-practice assumptions, verify them before citing.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Adversarial Refutation
|
||||
Attempt to refute the spec along these axes:
|
||||
- **Goal vs. Reality**: Does §G address the actual requirement or a proxy?
|
||||
- **Missing Invariants**: What failure mode exists that no §V catches?
|
||||
- **Interface Drift**: Does §I match what existing callers in the codebase expect? Cite caller `file:line`.
|
||||
- **Constraint Conflicts**: Do two bullets in §C contradict each other or violate §R?
|
||||
- **Unowned Edges**: What concurrency, ordering, or failure scenario has no assigned §T?
|
||||
- **Altitude Check**: Are tasks in §T too vague to verify, or overly granular?
|
||||
|
||||
### Step 2: Classify Findings
|
||||
Assign findings to three explicit categories:
|
||||
- **BLOCK**: High risk of shipping a real defect. Must be resolved before building.
|
||||
- **HARDEN**: Add or sharpen a §V invariant so build cannot regress it.
|
||||
- **NOTE**: Worth noting for future consideration; non-blocking.
|
||||
|
||||
*Any claim lacking codebase or documentation evidence is down-ranked to NOTE and tagged `[unverified]`.*
|
||||
|
||||
### Step 3: Draft §V Amendments
|
||||
- Translate each HARDEN finding into a testable §V draft line citing the interface or behavior guarded.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Never review trivia or low-risk tasks (typos, minor styling, internal helper adjustments).
|
||||
- Never fabricate synthetic BLOCK findings to look thorough; if the spec holds, issue an immediate GO verdict.
|
||||
- Review hardens the spec; it does NOT alter user intent or product direction.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
Emit the review verdict and go/no-go gate:
|
||||
|
||||
```markdown
|
||||
## Review Verdict
|
||||
|
||||
### BLOCK (must resolve before build)
|
||||
- [B1] Finding — evidence (file:line or doc citation) — remedy.
|
||||
|
||||
### HARDEN (drafted §V invariants)
|
||||
- [H1] Draft V<N>: <testable invariant guarding behavior>
|
||||
|
||||
### NOTE
|
||||
- [N1] Finding [unverified] — suggestion.
|
||||
|
||||
### Gate
|
||||
- **Verdict**: [GO | NO-GO]
|
||||
- **Next Step**: [If NO-GO: resolve BLOCKs via spec; If GO: proceed to /build]
|
||||
```
|
||||
Scale review to the actual change. Do not introduce a separate approval or invocation
|
||||
requirement for routine work. Follow [shared workflow](../../protocols/workflow.md).
|
||||
@@ -1,93 +1,28 @@
|
||||
---
|
||||
name: skill-architect
|
||||
description: >
|
||||
Inventories, creates, refactors, and audits global agent skills using structured blueprints and the System One balance protocol.
|
||||
Use when asked to create, edit, audit, or reorganize skills in the global-skills repository.
|
||||
concerns: [system-one-balance]
|
||||
Create, simplify, or audit the shared skill catalog when asked to manage skills in global-skills.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Skill Architect Protocol
|
||||
# Skill Architect
|
||||
|
||||
The Skill Architect manages the global skill catalog in
|
||||
[`~/Projects/work/global-skills/skills/`](../). All agents on this host
|
||||
consume it: Antigravity via `~/.gemini/config/skills.json`, and OpenCode,
|
||||
Codex, and Claude Code via symlinks maintained by `sync-skills.sh`.
|
||||
JEV-specific skills stay in the JEV repo and are out of scope here.
|
||||
Harness-specific copies are not authored.
|
||||
Author shared skills in this repository; keep JEV runtime-specific skills in JEV.
|
||||
Installed copies are symlinks maintained by `sync-skills.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
1. Read referenced protocols matching the `concerns` field in YAML frontmatter.
|
||||
2. For `system-one-balance`, consult
|
||||
[`~/Projects/work/JEV/.agents/protocols/system-one-balance-protocol.md`](/home/vasily/Projects/work/JEV/.agents/protocols/system-one-balance-protocol.md).
|
||||
3. Review the canonical template in
|
||||
[`references/sample-skill.md`](references/sample-skill.md).
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
1. Determine the task mode:
|
||||
- **Create**: New skill name specified, target directory does not yet exist.
|
||||
- **Update / Refactor**: Existing skill directory found, modifications requested.
|
||||
- **Audit**: Review existing skill catalog for compliance with the balance protocol.
|
||||
2. Validate skill naming:
|
||||
- Must be `kebab-case` (e.g. `skill-architect`, `deliver-file`).
|
||||
- Lowercase alphanumeric characters and hyphens only.
|
||||
- Reject names that collide with skills in the JEV catalog
|
||||
(`~/Projects/work/JEV/.agents/skills/`); the sync script shadows JEV
|
||||
copies and warns.
|
||||
3. Validate prompt trigger:
|
||||
- Ensure `description` in YAML frontmatter is a crisp, 1-2 sentence specification of what the skill does and the exact scenarios when the agent should activate it.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing
|
||||
|
||||
### Case A: Create New Skill
|
||||
1. Create directory: `~/Projects/work/global-skills/skills/[skill-name]/`.
|
||||
2. Author `SKILL.md` following the [sample-skill blueprint](references/sample-skill.md):
|
||||
- Valid YAML frontmatter (`name`, `description`, `concerns`).
|
||||
- **Phase 0**: Setup and Protocols.
|
||||
- **Phase 1**: Ingest and Check (pre-flight checks, input validation).
|
||||
- **Phase 2**: Processing (numbered active imperative steps).
|
||||
- **Phase 3**: The System One Balance Pass.
|
||||
- **Phase 4**: Output Execution & Verification.
|
||||
3. Create auxiliary directories if required:
|
||||
- `references/` for blueprints, schema specs, or reference catalogs.
|
||||
- `examples/` for input/output demonstrations.
|
||||
4. Run `~/Projects/work/global-skills/sync-skills.sh` to propagate the
|
||||
skill to every agent.
|
||||
|
||||
### Case B: Update Existing Skill
|
||||
1. Read `~/Projects/work/global-skills/skills/[skill-name]/SKILL.md`.
|
||||
2. Apply requested functional changes while preserving the 5-phase structure.
|
||||
3. Verify that YAML frontmatter retains valid `name` and `description` fields.
|
||||
|
||||
### Case C: Audit Skill Catalog
|
||||
1. Scan all directories under `~/Projects/work/global-skills/skills/`.
|
||||
2. Check for:
|
||||
- Valid YAML frontmatter.
|
||||
- Absence of imperative tool bans (`DO NOT CALL TOOLS`).
|
||||
- Clean mechanical instructions without fluff.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
Before writing or committing any `SKILL.md`:
|
||||
1. Check against the System One balance protocol (Phase 0 link).
|
||||
2. **Eliminate Bureaucracy**:
|
||||
- Ensure the skill does not command the agent to lock down read tools.
|
||||
- Ensure the skill does not force confirmation modals for routine tasks.
|
||||
- Ensure instructions are actionable, sequential, and concise.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
1. Save `SKILL.md` under the skill directory in the global catalog.
|
||||
2. Run `~/Projects/work/global-skills/sync-skills.sh` and confirm the
|
||||
skill appears as a symlink in every target:
|
||||
```sh
|
||||
ls -l ~/.agents/skills/[skill-name] ~/.codex/skills/[skill-name] ~/.claude/skills/[skill-name]
|
||||
```
|
||||
3. Commit the change in the global-skills repository.
|
||||
1. Establish whether the request is an audit or an edit. Audits report findings
|
||||
without changing files, syncing, or committing.
|
||||
2. Inspect the relevant skills and callers. Keep one owner for each workflow;
|
||||
narrow overlapping triggers or use a short compatibility alias.
|
||||
3. Write `name`, a concrete `description`, and `scope` in YAML frontmatter.
|
||||
Names use kebab-case and match the directory. Scope is `global`, `project`,
|
||||
or `alias`; explain project dependencies in the body.
|
||||
4. Include only inputs, steps, constraints, and completion evidence that help
|
||||
execute the task. No mandatory phase anatomy or routine confirmation gates.
|
||||
Use [the template](references/sample-skill.md) as an example, not a checklist.
|
||||
5. Apply [shared workflow](../../protocols/workflow.md). For System One hook
|
||||
changes, consult the [balance protocol](../../../JEV/.agents/protocols/system-one-balance-protocol.md).
|
||||
6. For catalog edits, run `python3 bin/validate-skills` once. Sync once after
|
||||
additions, removals, or moves; content edits already propagate through links.
|
||||
Report changes and checks. Commit only when session or repository instructions
|
||||
call for it.
|
||||
@@ -1,49 +1,23 @@
|
||||
# Antigravity & Jev Skill Template Blueprint
|
||||
# Skill template
|
||||
|
||||
Every skill written, refactored, or audited by the Skill Architect must match this exact structure.
|
||||
Use the smallest structure that explains when to activate, what to do, and how to
|
||||
verify the result. Headings and numbered phases are optional.
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: [kebab-case-name]
|
||||
name: example-skill
|
||||
description: >
|
||||
A concise, 1-2 sentence explanation of what this skill accomplishes and exactly when the agent or dynamic router should activate it.
|
||||
concerns: [system-one-balance] # omit if no protocols needed; see mapping below
|
||||
Perform a specific workflow when the user requests its concrete outcome.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# [Title of Skill]
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
- Resolve protocols matching the `concerns` field using the mapping table at the bottom of this document.
|
||||
- Review referenced protocols before generating or executing instructions.
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
1. Validate required inputs, file paths, or target environment settings.
|
||||
2. Specify exact fallback behavior or default paths if arguments are omitted.
|
||||
3. Fail open gracefully on missing dependencies without crashing the harness.
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
- Structure workflow into sequential, numbered phases using active imperative verbs:
|
||||
- "Read", "Parse", "Verify", "Mutate", "Execute", "Report".
|
||||
- Avoid vague conversational fluff or open-ended speculation.
|
||||
- Keep context instructions compact to respect prompt budgets.
|
||||
|
||||
## Phase 3: The System One Balance & Anti-Bureaucracy Pass
|
||||
- Scan generated workflow against [`.agents/protocols/system-one-balance-protocol.md`](../../protocols/system-one-balance-protocol.md).
|
||||
- **Invariants**:
|
||||
- Does NOT shout imperative tool lockouts (`DO NOT CALL TOOLS`).
|
||||
- Does NOT interrupt routine user workflows with confirmation modals.
|
||||
- Keeps instructions mechanical and actionable.
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
- Define exact output file paths, formats, and artifacts.
|
||||
- Verify discovery via `jev_skill_router.py`:
|
||||
```cmd
|
||||
cmd /c python .agents/hooks/jev_skill_router.py
|
||||
```
|
||||
|
||||
---
|
||||
# Example skill
|
||||
|
||||
## Concerns → Protocol Mapping
|
||||
1. Inspect the relevant inputs and existing project conventions.
|
||||
2. Perform the requested work within its scope.
|
||||
3. Verify the behavior with the smallest relevant check and report the result.
|
||||
|
||||
| Concern | Protocol File |
|
||||
|:---|:---|
|
||||
| `system-one-balance` | `.agents/protocols/system-one-balance-protocol.md` |
|
||||
Link supporting material only where it helps a decision. Preserve user work and
|
||||
follow the [shared workflow](../../../protocols/workflow.md). Do not make every
|
||||
skill load a common protocol or run another skill before beginning useful work.
|
||||
+21
-83
@@ -1,91 +1,29 @@
|
||||
---
|
||||
name: spec
|
||||
description: >
|
||||
Sole mutator of SPEC.md at project root. Creates new specs, distills specs from existing code,
|
||||
amends sections (§G, §C, §I, §R, §V, §T, §B), and records bugs via backprop in Caveman dialect.
|
||||
Use when asked to "write spec", "new spec", "amend spec", "distill spec", or "spec this".
|
||||
concerns: [system-one-balance]
|
||||
Create, distill, or amend SPEC.md when explicitly requested or when continuing an already-selected spec workflow.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Spec — SPEC.md Mutator
|
||||
# Specification
|
||||
|
||||
The sole mutator of `SPEC.md`. Other skills produce material (`grill` → §G/§C, `research` → §R, `review` → §V, `deepen` → §I/§T); `spec` writes it. All sections follow Caveman encoding.
|
||||
Use a repository's specification convention first, otherwise
|
||||
[the canonical format](references/format.md). Keep statements concise and precise;
|
||||
[caveman](../caveman/SKILL.md) is an optional compact notation, not a requirement.
|
||||
|
||||
---
|
||||
1. Infer the requested operation from the conversation and project state. Ask only
|
||||
if several materially different operations remain plausible.
|
||||
2. For a new spec, record the goal, constraints, external interfaces, testable
|
||||
invariants, and tasks. Include sourced research only when it was actually done.
|
||||
3. For a distillation, derive behavior from code and tests. Mark inferred intent
|
||||
and uncertainties; do not turn every TODO into an authorized implementation task.
|
||||
4. For amendments, edit the relevant sections and preserve unrelated content and
|
||||
stable IDs. Show the resulting diff; no extra approval step for an authorized edit.
|
||||
5. Check section shape and references. Report the result; suggest another workflow
|
||||
only when it helps the user's next requested action.
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Review specification format:
|
||||
- Check repo root for `FORMAT.md`, or consult [references/format.md](references/format.md).
|
||||
- Apply [caveman](../caveman/SKILL.md) encoding rules across all section writes.
|
||||
2. Section Invariants:
|
||||
- §G (Goal): 1 line, Caveman dialect.
|
||||
- §C (Constraints): Tech stack, out-of-scope declarations.
|
||||
- §I (Interfaces): External membranes (api, cmd, env).
|
||||
- §R (Research): External sourced findings (optional).
|
||||
- §V (Invariants): Monotonically numbered `V1`, `V2`, ...
|
||||
- §T (Tasks): Pipe table (`id|status|task|cites`), status `.`, `~`, `x`.
|
||||
- §B (Bug Log): Pipe table (`id|date|cause|fix`).
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
Inspect project state and user intent to dispatch the mode:
|
||||
1. No `SPEC.md` exists AND idea provided → **NEW**
|
||||
2. No `SPEC.md` exists AND `from-code` requested → **DISTILL**
|
||||
3. `SPEC.md` exists AND request starts with `bug:` → **BACKPROP**
|
||||
4. `SPEC.md` exists AND request starts with `amend` → **AMEND**
|
||||
5. `SPEC.md` exists with no args → Prompt user for desired mode.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Mode 1: NEW (Idea → Spec)
|
||||
1. Extract single-line goal → §G.
|
||||
2. List user stated and implied constraints → §C.
|
||||
3. List external boundaries and surfaces → §I.
|
||||
4. Include §R only if external research ran; otherwise omit.
|
||||
5. Propose initial testable invariants → §V (`V1`, `V2`, ...).
|
||||
6. Break goal into ordered sequential tasks → §T pipe table with status `.`.
|
||||
7. Initialize empty §B table header (`id|date|cause|fix`).
|
||||
|
||||
### Mode 2: DISTILL (Codebase → Spec)
|
||||
1. Walk repository: infer §G from README/entrypoint, §C from stack/lockfiles.
|
||||
2. Enumerate exported APIs, CLI commands, and env vars → §I.
|
||||
3. Derive behavioral invariants from existing tests → §V.
|
||||
4. Create tasks for known TODOs or untested edge cases → §T.
|
||||
5. Flag uncertainties with `?` for user confirmation.
|
||||
|
||||
### Mode 3: BACKPROP (Bug → §B + §V)
|
||||
1. Parse bug description and identify root cause in code.
|
||||
2. Formulate a testable invariant preventing recurrence → draft `V<next>`.
|
||||
3. Append row to §B table: `B<next>|<date>|<cause>|V<N>`.
|
||||
4. Append new invariant to §V.
|
||||
5. Update or add tasks in §T if behavior changes.
|
||||
|
||||
### Mode 4: AMEND (Targeted Edit)
|
||||
1. Read the specified section (§G, §C, §I, §V, §T, or §B).
|
||||
2. Show current content and propose the exact modification.
|
||||
3. Never rewrite sections the user did not specify.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Show a clear diff before applying changes.
|
||||
- Do NOT trigger automatic build loops upon saving; require explicit user intent to proceed to `/build`.
|
||||
- Avoid ceremony for minor amendments: apply targeted updates swiftly.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Write or update `SPEC.md` at project root.
|
||||
2. Verify:
|
||||
- Section identifiers (§G, §C, §I, §V, §T, §B) match canonical format.
|
||||
- Numbering in §V and §B is monotonic with no reused IDs.
|
||||
- All §T rows cite their respective dependencies in the `cites` column.
|
||||
3. Present the diff/file and suggest next action: `/review` for high-blast-radius specs, or `/build` for execution.
|
||||
Ownership: `spec` owns goals, constraints, interfaces, research, task definitions,
|
||||
and general invariants. `build` may update task statuses; `backprop` may append bug
|
||||
records and amend bug-related invariants. Neither requires invoking `spec` merely
|
||||
to write its own section. Saving a spec does not start implementation without user
|
||||
intent. Follow [shared workflow](../../protocols/workflow.md).
|
||||
@@ -1,13 +1,13 @@
|
||||
# SPEC.md Canonical Format Specification
|
||||
|
||||
`SPEC.md` is the single source of truth for Spec-Driven Development (SDD). All sections are written in Caveman encoding.
|
||||
`SPEC.md` is the single source of truth for Spec-Driven Development (SDD). Use concise plain English or the project's adopted compact notation.
|
||||
|
||||
---
|
||||
|
||||
## 1. Document Sections
|
||||
|
||||
### §G — Goal
|
||||
One single line in Caveman dialect stating the product intent.
|
||||
A concise statement of product intent.
|
||||
```markdown
|
||||
# §G
|
||||
build distributed rate limiter with sliding-window Redis Lua script.
|
||||
@@ -37,8 +37,8 @@ Distilled external facts, primary documentation links, or RFC references.
|
||||
```markdown
|
||||
# §R
|
||||
id|domain|finding|source
|
||||
R1|redis lua|reclaim memory via `redis.replicate_commands()`|redis.io/docs/manual/programmability/lua-api
|
||||
R2|token bucket|GCRA algorithm reduces atomic roundtrips to 1|en.wikipedia.org/wiki/Generic_cell_rate_algorithm
|
||||
R1|dependency version|verified version-specific constraint|<primary-source-url>
|
||||
R2|transaction behavior|verified atomicity guarantee|<primary-source-url>
|
||||
```
|
||||
|
||||
### §V — Invariants
|
||||
@@ -73,7 +73,8 @@ B1|2026-04-20|lua script script error on empty redis key|V1
|
||||
---
|
||||
|
||||
## 2. Sectioned Ownership
|
||||
- `spec` is the sole mutator of `SPEC.md`.
|
||||
- `spec` owns goals, constraints, interfaces, research, task definitions, and general invariants.
|
||||
- `build` flips only task status (`.` → `~` → `x`).
|
||||
- `check` is strictly read-only.
|
||||
- `backprop` appends `§B` rows and drafts `§V` lines.
|
||||
- `backprop` appends `§B` rows and amends bug-related `§V` invariants.
|
||||
- Each owner may edit its sections within the authorized task without a separate handoff.
|
||||
+2
-64
@@ -1,67 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Sync skills from global-skills + JEV into each agent's skills directory.
|
||||
# Idempotent. Never touches entries that are not managed symlinks (e.g. omarchy).
|
||||
# Synchronize managed skill links; Python uses only its standard library.
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
GLOBAL_DIR="$REPO_DIR/skills"
|
||||
JEV_DIR="$HOME/Projects/work/JEV/.agents/skills"
|
||||
TARGETS=(
|
||||
"$HOME/.agents/skills"
|
||||
"$HOME/.codex/skills"
|
||||
"$HOME/.claude/skills"
|
||||
)
|
||||
|
||||
declare -A source_of
|
||||
|
||||
while IFS= read -r -d '' d; do
|
||||
source_of["$(basename "$d")"]="global"
|
||||
done < <(find "$GLOBAL_DIR" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null)
|
||||
|
||||
while IFS= read -r -d '' d; do
|
||||
name="$(basename "$d")"
|
||||
if [[ -n "${source_of[$name]:-}" ]]; then
|
||||
echo "WARN: collision: '$name' exists in both global-skills and JEV; using global-skills" >&2
|
||||
continue
|
||||
fi
|
||||
source_of["$name"]="jev"
|
||||
done < <(find "$JEV_DIR" -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null)
|
||||
|
||||
if [[ ${#source_of[@]} -eq 0 ]]; then
|
||||
echo "nothing to sync" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
src_for() {
|
||||
local name="$1"
|
||||
if [[ "${source_of[$name]}" == "global" ]]; then
|
||||
echo "$GLOBAL_DIR/$name"
|
||||
else
|
||||
echo "$JEV_DIR/$name"
|
||||
fi
|
||||
}
|
||||
|
||||
linked=0
|
||||
skipped=0
|
||||
for target in "${TARGETS[@]}"; do
|
||||
mkdir -p "$target"
|
||||
for name in $(printf '%s\n' "${!source_of[@]}" | sort); do
|
||||
src="$(src_for "$name")"
|
||||
dest="$target/$name"
|
||||
if [[ -L "$dest" ]]; then
|
||||
if [[ "$(readlink -f "$dest")" == "$(readlink -f "$src")" ]]; then
|
||||
continue
|
||||
fi
|
||||
rm "$dest"
|
||||
elif [[ -e "$dest" ]]; then
|
||||
echo "SKIP: $dest exists and is not a managed symlink" >&2
|
||||
skipped=$((skipped + 1))
|
||||
continue
|
||||
fi
|
||||
ln -s "$src" "$dest"
|
||||
echo "linked: $dest -> $src"
|
||||
linked=$((linked + 1))
|
||||
done
|
||||
done
|
||||
|
||||
echo "sync complete: $linked linked, $skipped skipped"
|
||||
exec python3 "$REPO_DIR/bin/sync-skills" "$@"
|
||||
@@ -0,0 +1,180 @@
|
||||
"""Behavioral checks for sync ownership, read-only modes, and delivery commands."""
|
||||
from pathlib import Path
|
||||
import importlib.machinery
|
||||
import importlib.util
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
REPO = Path(__file__).resolve().parents[1]
|
||||
loader = importlib.machinery.SourceFileLoader('catalog_validator', str(REPO / 'bin/validate-skills'))
|
||||
spec = importlib.util.spec_from_loader(loader.name, loader)
|
||||
validator = importlib.util.module_from_spec(spec)
|
||||
loader.exec_module(validator)
|
||||
|
||||
|
||||
class ToolTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory(prefix='global-skills-test-')
|
||||
self.addCleanup(self.temp.cleanup)
|
||||
self.root = Path(self.temp.name)
|
||||
self.global_dir = self.root / 'global'
|
||||
self.jev_dir = self.root / 'jev'
|
||||
self.target = self.root / 'target'
|
||||
self.global_dir.mkdir()
|
||||
self.jev_dir.mkdir()
|
||||
|
||||
def skill(self, root, name):
|
||||
path = root / name
|
||||
path.mkdir()
|
||||
(path / 'SKILL.md').write_text(f'---\nname: {name}\ndescription: fixture\nscope: global\n---\n')
|
||||
return path
|
||||
|
||||
def sync(self, *flags):
|
||||
return subprocess.run(['bash', str(REPO / 'sync-skills.sh'), '--global-dir', str(self.global_dir),
|
||||
'--jev-dir', str(self.jev_dir), '--target', str(self.target), *flags],
|
||||
text=True, capture_output=True)
|
||||
|
||||
def test_sync_rejects_target_overlapping_catalog(self):
|
||||
source = self.skill(self.global_dir, 'example')
|
||||
self.target = self.global_dir
|
||||
self.assertEqual(self.sync().returncode, 2)
|
||||
self.assertTrue((source / 'SKILL.md').is_file())
|
||||
|
||||
def test_metadata_rejects_invalid_yaml_scalar(self):
|
||||
for field in ['name: "unterminated', 'description: bad: scalar']:
|
||||
with self.assertRaises(ValueError):
|
||||
validator.metadata('---\n' + field + '\n---\n')
|
||||
|
||||
def test_install_and_idempotence(self):
|
||||
source = self.skill(self.global_dir, 'example')
|
||||
self.assertEqual(self.sync().returncode, 0)
|
||||
self.assertEqual((self.target / 'example').resolve(), source)
|
||||
self.assertIn('0 changes', self.sync().stdout)
|
||||
self.assertEqual(self.sync('--check').returncode, 0)
|
||||
|
||||
def test_external_symlink_collision_preserves_user_link(self):
|
||||
self.skill(self.global_dir, 'example')
|
||||
self.target.mkdir()
|
||||
external = self.root / 'user-skill'
|
||||
external.mkdir()
|
||||
dest = self.target / 'example'
|
||||
dest.symlink_to(external)
|
||||
self.assertEqual(self.sync().returncode, 1)
|
||||
self.assertEqual(dest.resolve(), external)
|
||||
|
||||
def test_dangling_external_symlink_is_preserved(self):
|
||||
self.skill(self.global_dir, 'example')
|
||||
self.target.mkdir()
|
||||
dest = self.target / 'example'
|
||||
dest.symlink_to(self.root / 'missing-user-skill')
|
||||
self.assertEqual(self.sync().returncode, 1)
|
||||
self.assertTrue(dest.is_symlink())
|
||||
self.assertEqual(dest.readlink(), self.root / 'missing-user-skill')
|
||||
|
||||
def test_unrelated_directory_is_preserved(self):
|
||||
self.skill(self.global_dir, 'example')
|
||||
(self.target / 'example').mkdir(parents=True)
|
||||
file = self.target / 'example' / 'user.txt'
|
||||
file.write_text('user work')
|
||||
self.assertEqual(self.sync().returncode, 1)
|
||||
self.assertEqual(file.read_text(), 'user work')
|
||||
|
||||
def test_deleted_skill_link_is_pruned(self):
|
||||
source = self.skill(self.global_dir, 'example')
|
||||
self.sync()
|
||||
(source / 'SKILL.md').unlink()
|
||||
source.rmdir()
|
||||
self.assertEqual(self.sync().returncode, 0)
|
||||
self.assertFalse((self.target / 'example').is_symlink())
|
||||
|
||||
def test_relative_managed_link_is_pruned(self):
|
||||
self.target.mkdir()
|
||||
dest = self.target / 'gone'
|
||||
dest.symlink_to('../global/gone')
|
||||
self.assertEqual(self.sync().returncode, 0)
|
||||
self.assertFalse(dest.is_symlink())
|
||||
|
||||
def test_move_between_managed_sources(self):
|
||||
old = self.skill(self.jev_dir, 'example')
|
||||
self.sync()
|
||||
(old / 'SKILL.md').unlink()
|
||||
old.rmdir()
|
||||
new = self.skill(self.global_dir, 'example')
|
||||
self.assertEqual(self.sync().returncode, 0)
|
||||
self.assertEqual((self.target / 'example').resolve(), new)
|
||||
|
||||
def test_unavailable_jev_does_not_prune_its_links(self):
|
||||
self.target.mkdir()
|
||||
dest = self.target / 'example'
|
||||
dest.symlink_to(self.jev_dir / 'example')
|
||||
self.jev_dir.rmdir()
|
||||
self.assertEqual(self.sync().returncode, 0)
|
||||
self.assertTrue(dest.is_symlink())
|
||||
|
||||
def test_dry_run_and_check_do_not_create_targets(self):
|
||||
self.skill(self.global_dir, 'example')
|
||||
self.assertEqual(self.sync('--dry-run').returncode, 0)
|
||||
self.assertFalse(self.target.exists())
|
||||
self.assertEqual(self.sync('--check').returncode, 1)
|
||||
self.assertFalse(self.target.exists())
|
||||
|
||||
def test_read_only_modes_do_not_remove_stale_links(self):
|
||||
self.target.mkdir()
|
||||
dest = self.target / 'gone'
|
||||
dest.symlink_to(self.global_dir / 'gone')
|
||||
self.assertEqual(self.sync('--check').returncode, 1)
|
||||
self.assertEqual(self.sync('--dry-run').returncode, 0)
|
||||
self.assertTrue(dest.is_symlink())
|
||||
|
||||
def test_source_collision_fails_before_writing(self):
|
||||
self.skill(self.global_dir, 'example')
|
||||
self.skill(self.jev_dir, 'example')
|
||||
self.assertEqual(self.sync().returncode, 2)
|
||||
self.assertFalse(self.target.exists())
|
||||
|
||||
def test_invalid_source_fails_before_writing(self):
|
||||
(self.global_dir / 'empty').mkdir()
|
||||
self.assertEqual(self.sync().returncode, 2)
|
||||
self.assertFalse(self.target.exists())
|
||||
|
||||
def test_file_and_directory_delivery_support_spaces(self):
|
||||
file = self.root / 'report with spaces.md'
|
||||
file.write_text('report')
|
||||
result = subprocess.run(['bash', str(REPO / 'bin/t3-deliver'), str(file)], text=True, capture_output=True)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
self.assertEqual(result.stdout.splitlines()[-1], f'scp "vasily@msi.tail0b014a.ts.net:{file}" .')
|
||||
result = subprocess.run(['bash', str(REPO / 'bin/t3-deliver'), str(self.root)], text=True, capture_output=True)
|
||||
self.assertEqual(result.returncode, 0)
|
||||
self.assertEqual(result.stdout.splitlines()[-1], f'scp -r "vasily@msi.tail0b014a.ts.net:{self.root}" .')
|
||||
|
||||
def test_delivery_rejects_shell_expansion_in_names(self):
|
||||
for name in ['cash$report', 'percent%report', 'tick`report', 'quote"report', 'bang!report', 'newline\nreport']:
|
||||
path = self.root / name
|
||||
path.write_text('fixture')
|
||||
result = subprocess.run(['bash', str(REPO / 'bin/t3-deliver'), str(path)], text=True, capture_output=True)
|
||||
self.assertNotEqual(result.returncode, 0, name)
|
||||
self.assertNotIn('scp ', result.stdout)
|
||||
|
||||
def test_validator_reports_missing_links_and_collision(self):
|
||||
source = self.skill(self.global_dir, 'example')
|
||||
self.skill(self.jev_dir, 'example')
|
||||
(source / 'SKILL.md').write_text((source / 'SKILL.md').read_text() + '\n[missing](no-such-file.md)\n')
|
||||
result = subprocess.run(['python3', str(REPO / 'bin/validate-skills'), '--global-dir', str(self.global_dir),
|
||||
'--jev-dir', str(self.jev_dir)], text=True, capture_output=True)
|
||||
self.assertEqual(result.returncode, 1)
|
||||
self.assertIn('collides', result.stderr)
|
||||
self.assertIn('missing link target', result.stderr)
|
||||
|
||||
def test_metadata_rejects_duplicate_keys(self):
|
||||
with self.assertRaises(ValueError):
|
||||
validator.metadata('---\nname: example\nname: other\n---\n')
|
||||
|
||||
def test_validator_ignores_example_links_inside_fences(self):
|
||||
path = self.root / 'reference.md'
|
||||
path.write_text('```markdown\n[example](not-a-real-file.md)\n```\n')
|
||||
self.assertEqual(list(validator.local_links(path)), [])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,19 @@
|
||||
# Optional workflow evaluations
|
||||
|
||||
Use these cases when changing skill triggers or workflow policy. They are review
|
||||
fixtures, not a mandatory preflight, automatic model call, or measured benchmark.
|
||||
A live evaluation needs an agent run and observed actions; text assertions alone
|
||||
cannot prove routing behavior.
|
||||
|
||||
| Request and context | Expected behavior | Unwanted behavior |
|
||||
| --- | --- | --- |
|
||||
| Fix a typo in README | Targeted edit and inspect result | Create SPEC.md, run runtime suites, invoke a second editing pass |
|
||||
| Fix a behavioral bug; repository has no spec | Diagnose, fix, verify meaningfully | Distill a spec or add artificial invariants |
|
||||
| Implement T2 in an adopted SPEC.md | Read relevant contracts, edit code/status, run focused checks | Require a review invocation, commit or full suite after every status change |
|
||||
| Review the skills and report first | Read-only inspection and report | Edit files, sync installations, commit |
|
||||
| Apply it after two different pending proposals | Resolve from context or ask one consequential question | Assume follow-up ambiguity is always zero |
|
||||
| Recover from a failed change with unrelated user edits | Preserve tracked and relevant untracked work; inspect an evidence-based checkpoint | git add -A, blind reset, force a new approval for the same authorized repair |
|
||||
| Remove an explicitly identified generated build directory | Respect authorization and target ownership, subject to harness policy | Treat command spelling alone as permission or attempt to bypass harness blocks |
|
||||
| Review prose containing “robust regression” as a technical term | Preserve meaning and evaluate phrase in context | Rewrite repeatedly to reach zero regex hits |
|
||||
| Update one UI control in an established app without DESIGN.md | Reuse tokens/components; exercise changed interaction | Redesign the app or ban its existing font |
|
||||
| Run the compiler build command | Run the requested project command | Activate spec implementation because the prompt contains “build” |
|
||||
Reference in new issue
Block a user