@mohammadhprp/system-prompt 0.12.3 → 0.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/framework/commands/review.md +5 -20
- package/framework/skills/README.md +15 -0
- package/framework/skills/architect/SKILL.md +83 -0
- package/framework/skills/architect/examples.md +5 -0
- package/framework/skills/architect/references/design-red-flags.md +33 -0
- package/framework/skills/architect/references/rationale-template.md +35 -0
- package/framework/skills/architect/references/runner-prompt.md +20 -0
- package/framework/skills/arena/SKILL.md +71 -0
- package/framework/skills/arena/examples.md +5 -0
- package/framework/skills/bro/SKILL.md +7 -0
- package/framework/skills/bro/examples.md +5 -0
- package/framework/skills/changelog/SKILL.md +41 -0
- package/framework/skills/changelog/examples.md +5 -0
- package/framework/skills/commit/SKILL.md +28 -0
- package/framework/skills/commit/examples.md +5 -0
- package/framework/skills/gh/SKILL.md +157 -0
- package/framework/skills/gh/examples.md +10 -0
- package/framework/skills/how/SKILL.md +135 -0
- package/framework/skills/how/examples.md +5 -0
- package/framework/skills/how/references/critic-prompt.md +59 -0
- package/framework/skills/how/references/critique-rubric.md +58 -0
- package/framework/skills/how/references/explainer-prompt.md +55 -0
- package/framework/skills/how/references/explorer-prompt.md +52 -0
- package/framework/skills/merge-request/SKILL.md +40 -0
- package/framework/skills/merge-request/examples.md +5 -0
- package/framework/skills/ponytail/SKILL.md +145 -0
- package/framework/skills/ponytail/references/ponytail-audit.md +18 -0
- package/framework/skills/ponytail/references/ponytail-debt.md +21 -0
- package/framework/skills/ponytail/references/ponytail-gain.md +25 -0
- package/framework/skills/ponytail/references/ponytail-help.md +18 -0
- package/framework/skills/ponytail/references/ponytail-mode.md +33 -0
- package/framework/skills/ponytail/references/ponytail-review.md +27 -0
- package/framework/skills/ponytail/references/ponytail-rules.md +31 -0
- package/framework/skills/ponytail/references/principle-boundary-discipline.md +7 -0
- package/framework/skills/ponytail/references/principle-encode-lessons-in-structure.md +13 -0
- package/framework/skills/ponytail/references/principle-fix-root-causes.md +17 -0
- package/framework/skills/ponytail/references/principle-make-operations-idempotent.md +12 -0
- package/framework/skills/ponytail/references/principle-model-the-domain.md +7 -0
- package/framework/skills/ponytail/references/principle-prove-it-works.md +27 -0
- package/framework/skills/ponytail/references/principle-sequence-verifiable-units.md +7 -0
- package/framework/skills/pull-request/SKILL.md +31 -0
- package/framework/skills/pull-request/examples.md +5 -0
- package/framework/skills/release/SKILL.md +30 -0
- package/framework/skills/release/examples.md +5 -0
- package/framework/skills/review/SKILL.md +113 -0
- package/framework/skills/review/examples.md +6 -0
- package/framework/skills/review/scripts/render_review.py +95 -0
- package/framework/skills/review/scripts/resolve_spec_context.py +723 -0
- package/framework/skills/review/scripts/validate_review_json.py +348 -0
- package/framework/skills/tdd/SKILL.md +44 -0
- package/framework/skills/tdd/examples.md +5 -0
- package/framework/skills/unslop/SKILL.md +81 -0
- package/framework/skills/unslop/examples.md +5 -0
- package/framework/skills/why/SKILL.md +230 -0
- package/framework/skills/why/examples.md +5 -0
- package/framework/skills/why/references/epistemics.md +144 -0
- package/framework/skills/why/references/investigator-prompt.md +103 -0
- package/framework/skills/why/references/source-playbook.md +17 -0
- package/framework/skills/why/references/sources/code-archaeology.md +88 -0
- package/framework/skills/why/references/sources/databricks.md +70 -0
- package/framework/skills/why/references/sources/datadog.md +99 -0
- package/framework/skills/why/references/sources/incident-postmortem.md +15 -0
- package/framework/skills/why/references/sources/linear.md +48 -0
- package/framework/skills/why/references/sources/notion.md +55 -0
- package/framework/skills/why/references/sources/sentry.md +100 -0
- package/framework/skills/why/references/sources/slack.md +54 -0
- package/framework/skills/why/references/synthesizer-prompt.md +135 -0
- package/package.json +1 -1
- package/src/catalog.js +17 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Ponytail mode
|
|
2
|
+
|
|
3
|
+
Use this operation for `/ponytail`, `/ponytail lite`, `/ponytail full`,
|
|
4
|
+
`/ponytail ultra`, or `/ponytail off`.
|
|
5
|
+
|
|
6
|
+
Ponytail is active every response until the user says `stop ponytail`, `normal
|
|
7
|
+
mode`, or `/ponytail off`. The default is **full**.
|
|
8
|
+
|
|
9
|
+
## Levels
|
|
10
|
+
|
|
11
|
+
| Level | Behavior |
|
|
12
|
+
|---|---|
|
|
13
|
+
| **lite** | Build what was asked, then name the lazier alternative in one line. |
|
|
14
|
+
| **full** | Enforce the YAGNI → existing code → stdlib → native → installed dependency → one line → minimum ladder. Default. |
|
|
15
|
+
| **ultra** | Delete before adding, challenge the requirement, and ship the smallest viable result. |
|
|
16
|
+
|
|
17
|
+
Use the main skill's ladder and rules for the actual coding task. A mode switch
|
|
18
|
+
does not itself change files or create configuration.
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
Default resolution is environment variable, then config file, then `full`:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export PONYTAIL_DEFAULT_MODE=ultra
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Config file: `~/.config/ponytail/config.json` (Windows:
|
|
29
|
+
`%APPDATA%\ponytail\config.json`).
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{ "defaultMode": "lite" }
|
|
33
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Ponytail review
|
|
2
|
+
|
|
3
|
+
Use for `/ponytail-review` or a request to review changes for
|
|
4
|
+
over-engineering. Review the current diff only. Do not apply fixes.
|
|
5
|
+
|
|
6
|
+
Scope is complexity only; route correctness bugs, security holes, and
|
|
7
|
+
performance issues to a normal review.
|
|
8
|
+
|
|
9
|
+
Report one finding per line:
|
|
10
|
+
|
|
11
|
+
`<file>:L<line>: <tag> <what to cut>. <replacement>.`
|
|
12
|
+
|
|
13
|
+
Tags:
|
|
14
|
+
|
|
15
|
+
- `delete:` dead code, unused flexibility, or speculative features; replacement
|
|
16
|
+
is nothing.
|
|
17
|
+
- `stdlib:` hand-rolled functionality supplied by the standard library; name
|
|
18
|
+
the function.
|
|
19
|
+
- `native:` a dependency or custom code doing what the platform already does;
|
|
20
|
+
name the native feature.
|
|
21
|
+
- `yagni:` an abstraction with one implementation, unused configuration, or a
|
|
22
|
+
layer with one caller.
|
|
23
|
+
- `shrink:` equivalent logic that can use fewer lines; show the shorter form.
|
|
24
|
+
|
|
25
|
+
End with `net: -<N> lines possible.` If there is nothing to cut, say
|
|
26
|
+
`Lean already. Ship.` Do not flag a single smoke test or assert-based
|
|
27
|
+
self-check as bloat.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Ponytail rules
|
|
2
|
+
|
|
3
|
+
Lazy means efficient, not careless. The best code is the code never written.
|
|
4
|
+
|
|
5
|
+
Before writing code, stop at the first rung that holds:
|
|
6
|
+
|
|
7
|
+
1. Does this need to be built at all? (YAGNI)
|
|
8
|
+
2. Does it already exist in this codebase? Reuse the helper, util, or pattern.
|
|
9
|
+
3. Does the standard library already do this? Use it.
|
|
10
|
+
4. Does a native platform feature cover it? Use it.
|
|
11
|
+
5. Does an already-installed dependency solve it? Use it.
|
|
12
|
+
6. Can this be one line? Make it one line.
|
|
13
|
+
7. Only then: write the minimum code that works.
|
|
14
|
+
|
|
15
|
+
The ladder runs after understanding the problem, not instead of it. Read the
|
|
16
|
+
task and touched code, trace the real flow end to end, then choose the rung.
|
|
17
|
+
|
|
18
|
+
For bug fixes, find every caller of the function being changed and fix the
|
|
19
|
+
shared root cause once. Do not scatter symptom guards across callers.
|
|
20
|
+
|
|
21
|
+
Do not simplify away input validation at trust boundaries, error handling that
|
|
22
|
+
prevents data loss, security, accessibility, hardware calibration, or anything
|
|
23
|
+
explicitly requested. Non-trivial lazy code leaves one runnable check behind;
|
|
24
|
+
trivial one-liners need no test.
|
|
25
|
+
|
|
26
|
+
Mark deliberate shortcuts with a `ponytail:` comment naming the ceiling and
|
|
27
|
+
upgrade path, for example:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
# ponytail: global lock, per-account locks if throughput matters
|
|
31
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Boundary Discipline
|
|
2
|
+
|
|
3
|
+
Validate and normalize untrusted data at the boundary, then pass typed and validated values into internal domain code.
|
|
4
|
+
|
|
5
|
+
Relevant boundaries include FormRequests, route parameters, Artisan arguments, environment configuration, uploaded files, database rows, HTTP responses, CSV or Excel imports, and tenant context. Use existing requests, enums, rules, scopes, and service abstractions.
|
|
6
|
+
|
|
7
|
+
Do not accept `tenant_id` from untrusted Admin input when authenticated context determines the tenant. Do not repeat defensive validation throughout trusted internal call chains. Keep controllers and framework adapters thin; keep pricing, order, import, and state logic in the established services, actions, pipes, and domain structures.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Encode Lessons In Structure
|
|
2
|
+
|
|
3
|
+
When a rule is repeated, ask whether it belongs in a mechanism rather than another instruction.
|
|
4
|
+
|
|
5
|
+
Prefer the strongest practical enforcement:
|
|
6
|
+
|
|
7
|
+
- A type, enum, or database constraint
|
|
8
|
+
- An architecture or security test
|
|
9
|
+
- A canonical helper, scope, policy, or service
|
|
10
|
+
- A runtime guard at the correct boundary
|
|
11
|
+
- A concise project skill when the rule still requires judgment
|
|
12
|
+
|
|
13
|
+
Examples include enforcing tenant access through existing scopes and middleware, preventing forbidden debugging calls through architecture tests, using unique keys for imports, and centralizing API response envelopes. Do not add a textual reminder when a reliable structural check can prevent the mistake.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Fix Root Causes
|
|
2
|
+
|
|
3
|
+
When debugging, do not paper over symptoms. Trace every problem to its root cause and fix it there.
|
|
4
|
+
|
|
5
|
+
**Why:** Symptom fixes accumulate. Each workaround makes the system harder to reason about, and the real bug remains. Root-cause fixes are slower upfront but reduce total debugging time.
|
|
6
|
+
|
|
7
|
+
**Pattern:**
|
|
8
|
+
- Reproduce first (if you can't reproduce it, you can't verify your fix)
|
|
9
|
+
- Ask "why" until you hit the root cause
|
|
10
|
+
- Resist the urge to add guards (adding a nil check to silence a crash is a symptom fix)
|
|
11
|
+
- If a workaround needs a paragraph-long comment to justify it, the code is wrong (fix the code, not the comment)
|
|
12
|
+
- Check for the pattern, not just the instance (grep for the same pattern, fix all instances)
|
|
13
|
+
- When stuck, instrument. Don't guess (add logging, read the actual error)
|
|
14
|
+
|
|
15
|
+
**Restart bugs: suspect state before code**
|
|
16
|
+
|
|
17
|
+
Code doesn't change between runs. State does. When something "fails after restart," suspect stale persistent state first: config files, caches, lock files, serialized state. If clearing a state file restores behavior, prioritize state validation as the fix.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Make Operations Idempotent
|
|
2
|
+
|
|
3
|
+
Design state-changing operations so repeated execution converges to the same correct state. Before changing a command, job, importer, pipeline step, or integration, answer:
|
|
4
|
+
|
|
5
|
+
- What happens if it runs twice?
|
|
6
|
+
- What happens if it crashes after each state change?
|
|
7
|
+
- What happens when Laravel retries the job?
|
|
8
|
+
- Can duplicate records, stock changes, notifications, or external requests occur?
|
|
9
|
+
|
|
10
|
+
Apply this especially to `app/Imports`, `app/Console/Commands`, `app/Jobs`, order pipes, stock actions, and Rahkaran or Elasticsearch synchronization.
|
|
11
|
+
|
|
12
|
+
Prefer stable external identifiers, unique database constraints, upserts, transactions, checkpointed progress, and safe retry behavior. Preserve tenant isolation while reconciling partial work. Test a successful run twice and test the important crash or retry boundary when practical.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Model the Domain
|
|
2
|
+
|
|
3
|
+
Represent domain rules in structures that make invalid states difficult to create instead of spreading conditions across files.
|
|
4
|
+
|
|
5
|
+
Prefer existing enums, state services, policies, value objects, typed request data, registries, scopes, and pipeline data. For Chideli, inspect `OrderStatusEnum`, `OrderItemStatusEnum`, `OrderStateService`, `OrderPipelineData`, pricing services, and sale policy types before adding branches.
|
|
6
|
+
|
|
7
|
+
Do not introduce an abstraction only to move code. Add one when it removes duplicated rules, contradictory states, or repeated conditionals. Preserve the existing ownership boundary and cover each meaningful state transition with tests.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Prove It Works
|
|
2
|
+
|
|
3
|
+
Verify every task output by checking the real thing directly. Do not infer from proxies, self-reports, or "it compiles."
|
|
4
|
+
|
|
5
|
+
**Why:** Unverified work has unknown correctness. Indirect verification (file mtimes, output freshness, agent self-reports, cached screenshots) feels cheaper than direct observation. Acting on a wrong inference costs far more than checking the source.
|
|
6
|
+
|
|
7
|
+
**Pattern:** After completing any task, ask: "how do I prove this actually works?"
|
|
8
|
+
|
|
9
|
+
Check the real thing, not a proxy:
|
|
10
|
+
- Check process liveness directly, not indirectly through derived state
|
|
11
|
+
- Read the actual value, not a cached or derived representation
|
|
12
|
+
- When verification fails, suspect the observation method before suspecting the system
|
|
13
|
+
|
|
14
|
+
Code and features:
|
|
15
|
+
1. Build it (necessary but not sufficient)
|
|
16
|
+
2. Run it and exercise the actual feature path
|
|
17
|
+
3. Check the full chain: does data flow from input to output?
|
|
18
|
+
4. For integrations, test the full communication path end-to-end
|
|
19
|
+
|
|
20
|
+
Delegation: trust artifacts, not self-reports.
|
|
21
|
+
When verifying delegated work, inspect the actual output artifact (git diff, file contents, runtime behavior), not the delegate's summary. Agents report what they intended, not always what happened.
|
|
22
|
+
|
|
23
|
+
## Script the check when you can
|
|
24
|
+
|
|
25
|
+
The strongest proof is a deterministic script that re-runs the same comparison, not a one-time eyeball. Write the script, run it, and keep its output as an artifact a reviewer can re-run instead of trusting your word. A script comparing the old and new compiled output catches what a glance misses.
|
|
26
|
+
|
|
27
|
+
Keep the artifact visible for the human. Commit it only for large or complex work where the trail has to be auditable later, like a big port or migration (the **show-me-your-work** skill). Most work just needs it visible, not committed.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Sequence Work Into Verifiable Units
|
|
2
|
+
|
|
3
|
+
Break broad work into small units, and verify each unit before starting the next. A unit may be one migration, one endpoint, one importer change, or one focused refactor with its tests.
|
|
4
|
+
|
|
5
|
+
Start from a known-good state. Make one change. Run the narrowest relevant check. Inspect the result. Then continue. Do not batch many edits and postpone all verification until the end.
|
|
6
|
+
|
|
7
|
+
When commits are requested, order them so a reviewer can follow the proof: prerequisite or regression test, implementation, cleanup, and final verification. Preserve migration order and tenant safety at every step.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pull-request
|
|
3
|
+
description: Create or update a GitHub pull request (PR) for the current branch using the gh CLI. Use this skill whenever the user asks to open, create, update, or prepare a GitHub PR or pull request.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `pull-request` skill instructions
|
|
7
|
+
|
|
8
|
+
Create or update a pull request for the current branch using `gh` CLI.
|
|
9
|
+
|
|
10
|
+
## Process
|
|
11
|
+
|
|
12
|
+
1. **Collect information**
|
|
13
|
+
- Get the current branch name: `git branch --show-current`
|
|
14
|
+
- Read the PR template from `.github/pull_request_template.md` if it exists.
|
|
15
|
+
|
|
16
|
+
2. **Format PR title**
|
|
17
|
+
- Take the branch name, replace all `-` with spaces, and capitalize the first character.
|
|
18
|
+
|
|
19
|
+
3. **Collect commits and build summary**
|
|
20
|
+
- List commits on the branch that are not on `develop`: `git log develop..HEAD --oneline`
|
|
21
|
+
- Read each commit message and convert it to a bullet list summarizing user-facing changes.
|
|
22
|
+
- Merge/squash related commits (for example, multiple commits for the same change).
|
|
23
|
+
- Keep the summary concise, with one bullet per logical change.
|
|
24
|
+
|
|
25
|
+
4. **Fill template**
|
|
26
|
+
- Set Summary to the bullet list from step 3.
|
|
27
|
+
- Keep the Checklist section as-is.
|
|
28
|
+
|
|
29
|
+
5. **Present plan and confirm** - Show the source branch, target branch (`develop`), title, and filled description. Ask: "Shall I create this PR?" Push the changes if the user says yes.
|
|
30
|
+
|
|
31
|
+
6. **Create upon confirmation** - Use `gh pr create --title "<title>" --body "<body>" --base <target>` and show the resulting URL.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
- Build a PR title and concise summary from the current branch and commits, then show the complete body before asking for confirmation.
|
|
4
|
+
- Preserve an existing `.github/pull_request_template.md` checklist while replacing only its summary content.
|
|
5
|
+
- Push and create the GitHub PR only after the user approves the displayed plan.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: Create a software release by reviewing commits, determining the semantic version, updating the changelog and package versions, committing release metadata, and tagging the result. Use this skill whenever the user asks to cut, prepare, publish, or tag a release.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# `release` skill instructions
|
|
7
|
+
|
|
8
|
+
Create a release from the current branch state.
|
|
9
|
+
|
|
10
|
+
## Process
|
|
11
|
+
|
|
12
|
+
1. **Review recent commits** - Run `git fetch --tags`, `git describe --tags --abbrev=0` to find the latest tag. Run `git log <latest-tag>..HEAD --oneline --format="%s"` to collect all conventional commits since the last release. Read any existing `CHANGELOG.md`.
|
|
13
|
+
2. **Categorize commits** - Group commits by conventional commit type:
|
|
14
|
+
- `feat!:` or `BREAKING CHANGE:` → breaking change
|
|
15
|
+
- `feat:` → minor feature
|
|
16
|
+
- `fix:` → patch fix
|
|
17
|
+
- `perf:`, `refactor:`, `test:` → patch (if no features)
|
|
18
|
+
- `chore:`, `docs:`, `ci:` → filtered from changelog
|
|
19
|
+
3. **Determine next version** - Based on the [`commit` skill](../commit/SKILL.md) semver convention:
|
|
20
|
+
- Breaking changes → increment major version (e.g., `1.2.3` → `2.0.0`)
|
|
21
|
+
- New features → increment minor version (e.g., `1.2.3` → `1.3.0`)
|
|
22
|
+
- Only fixes/refactors → increment patch version (e.g., `1.2.3` → `1.2.4`)
|
|
23
|
+
- If no previous tag exists, propose `0.1.0`
|
|
24
|
+
4. **Present release plan** - Show the current version, new version, categorized changelog entries, and ask: "Shall I create this release (tag vX.Y.Z and update CHANGELOG.md)?"
|
|
25
|
+
5. **Execute on confirmation**:
|
|
26
|
+
- Update `CHANGELOG.md`: create a new `## [vX.Y.Z]` section under `## Unreleased`, move categorized entries (excluding chore/docs/ci) into it, add the release date, and keep the `## Unreleased` section empty for future work.
|
|
27
|
+
- Update project version metadata such as `package.json` and `package-lock.json` when present.
|
|
28
|
+
- Run `git add CHANGELOG.md package.json package-lock.json` for files that exist and commit with `chore: release vX.Y.Z`.
|
|
29
|
+
- Run `git tag -a vX.Y.Z -m "vX.Y.Z"`.
|
|
30
|
+
6. **Verify** - Run `git log --oneline -n 3` and `git tag --list --sort=-v:refname -n5` to confirm the release tag and commit are in place.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
- Inspect tags and conventional commits, propose the next semantic version, and show the release plan before changing files.
|
|
4
|
+
- Move categorized entries from `Unreleased` into a dated version section while leaving a clean `Unreleased` section.
|
|
5
|
+
- Update available package version metadata, commit the release files, create the annotated tag, and verify both afterward.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review
|
|
3
|
+
description: Review local Git changes, GitHub pull requests, or GitLab merge requests and produce a structured review.json artifact. Use this skill whenever the user asks for a code review, diff review, PR review, MR review, or production-readiness assessment. Use the gh skill for GitHub and the glab skill for GitLab; never publish review comments.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Review Skill
|
|
7
|
+
|
|
8
|
+
Review the requested change and write the result to `review.json`. The review is
|
|
9
|
+
read-only: do not approve, request changes, comment, merge, push, or otherwise
|
|
10
|
+
modify remote repositories.
|
|
11
|
+
|
|
12
|
+
## Select the change source
|
|
13
|
+
|
|
14
|
+
Use the source explicitly named by the user. If it is not named, inspect the
|
|
15
|
+
current repository and ask when the target is ambiguous.
|
|
16
|
+
|
|
17
|
+
### Local changes
|
|
18
|
+
|
|
19
|
+
- Run `git status --short` and inspect staged and unstaged changes with
|
|
20
|
+
`git diff`, `git diff --cached`, and the relevant branch comparison when
|
|
21
|
+
needed.
|
|
22
|
+
- Review the working tree as it exists; do not checkout, reset, stash, or amend
|
|
23
|
+
user changes.
|
|
24
|
+
|
|
25
|
+
### GitHub pull requests
|
|
26
|
+
|
|
27
|
+
- Read the `gh` skill before using GitHub commands.
|
|
28
|
+
- Confirm repository context with `git remote -v` or use `--repo OWNER/REPO`.
|
|
29
|
+
- Read metadata with `gh pr view NUMBER --json title,body,baseRefName,headRefName`.
|
|
30
|
+
- Read the patch with `gh pr diff NUMBER`.
|
|
31
|
+
- Use only read operations. Do not run `gh pr review`, `gh pr comment`, `gh api`
|
|
32
|
+
mutations, or any other publishing command.
|
|
33
|
+
|
|
34
|
+
### GitLab merge requests
|
|
35
|
+
|
|
36
|
+
- Read the `glab` skill before using GitLab commands.
|
|
37
|
+
- Confirm repository context with `git remote -v` or use `-R OWNER/REPO`.
|
|
38
|
+
- Read metadata with `glab mr view NUMBER --output=json`.
|
|
39
|
+
- Read the patch with `glab mr diff NUMBER`.
|
|
40
|
+
- Use only read operations. Do not run `glab mr approve`, `glab mr note`, merge,
|
|
41
|
+
or other mutating commands.
|
|
42
|
+
|
|
43
|
+
## Review process
|
|
44
|
+
|
|
45
|
+
1. Establish the change intent from the request, commit history, description,
|
|
46
|
+
and diff. Focus findings on changed files and lines.
|
|
47
|
+
2. Read relevant repository guidance and contracts, including naming, testing,
|
|
48
|
+
security, and performance standards when available.
|
|
49
|
+
3. Check correctness, edge cases, error handling, state transitions,
|
|
50
|
+
compatibility, security, and meaningful performance risks.
|
|
51
|
+
4. Check maintainability, comments, and tests against the consuming
|
|
52
|
+
repository's conventions. Treat changed comments and tests as review items.
|
|
53
|
+
5. Include only actionable findings. Put concerns about untouched code in the
|
|
54
|
+
top-level body rather than attaching them to changed lines.
|
|
55
|
+
6. Classify findings as critical, important, suggestions, or nits. Do not block
|
|
56
|
+
for speculative improvements or cosmetic preferences.
|
|
57
|
+
|
|
58
|
+
## Inline comments
|
|
59
|
+
|
|
60
|
+
Use inline comments only when the exact changed path, side, and line are
|
|
61
|
+
available in the reviewed diff. For annotated diffs, use `[OLD:n]` as `LEFT`,
|
|
62
|
+
`[NEW:n]` as `RIGHT`, and `[OLD:n,NEW:m]` as `RIGHT` line `m`. If an exact
|
|
63
|
+
location cannot be verified, put the finding in the top-level body.
|
|
64
|
+
|
|
65
|
+
Every inline comment must begin with one of:
|
|
66
|
+
|
|
67
|
+
- `🚨 [CRITICAL]`
|
|
68
|
+
- `⚠️ [IMPORTANT]`
|
|
69
|
+
- `💡 [SUGGESTION]`
|
|
70
|
+
- `🧹 [NIT]` (only with a concrete suggestion)
|
|
71
|
+
|
|
72
|
+
Keep comments concise, actionable, and limited to changed lines. Use a
|
|
73
|
+
`suggestion` block only when the replacement is exact and safe.
|
|
74
|
+
|
|
75
|
+
## Output contract
|
|
76
|
+
|
|
77
|
+
Write exactly one `review.json` with this shape:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"verdict": "APPROVE",
|
|
82
|
+
"body": "## Overview\n...\n\n## Concerns\n...\n\nFound: 0 critical, 0 important, 0 suggestions\n\nApprove",
|
|
83
|
+
"comments": []
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- `verdict` is required and must be `APPROVE` or `REJECT`.
|
|
88
|
+
- `body` is required and must contain an overview, concerns, issue counts in
|
|
89
|
+
the form `Found: X critical, Y important, Z suggestions`, and a final
|
|
90
|
+
recommendation of `Approve`, `Approve with nits`, or `Request changes` that
|
|
91
|
+
agrees with `verdict`.
|
|
92
|
+
- `comments` is required and must be an array. Use an empty array when no
|
|
93
|
+
verified inline comment is appropriate.
|
|
94
|
+
- Paths are repository-relative. `side` and `start_side` are `LEFT` or
|
|
95
|
+
`RIGHT`; `start_line` is used only for a multi-line range.
|
|
96
|
+
|
|
97
|
+
Before finishing, validate JSON and, when an annotated diff is available, run:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
python3 .agents/skills/review/scripts/validate_review_json.py \
|
|
101
|
+
--review-json review.json --diff pr_diff.txt
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If that path is unavailable, run the validator from this skill's `scripts/`
|
|
105
|
+
directory. Then render the review for human inspection:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
python3 .agents/skills/review/scripts/render_review.py \
|
|
109
|
+
--review-json review.json --output review.html
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The renderer creates a self-contained Excalidraw-inspired dark HTML report.
|
|
113
|
+
The final artifacts are `review.json` and `review.html`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
- Review staged and unstaged local changes, then write a structured `review.json`.
|
|
4
|
+
- Review a GitHub pull request with `gh pr view` and `gh pr diff`, or a GitLab merge request with `glab mr view` and `glab mr diff`.
|
|
5
|
+
- Check correctness, tests, performance, security, and maintainability; never publish comments or approvals.
|
|
6
|
+
- Render the completed `review.json` to `review.html` for a visual, dark-mode review summary.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render a review.json file as a self-contained dark HTML report."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
PAGE = r"""<!doctype html>
|
|
12
|
+
<html lang="en">
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="utf-8">
|
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
16
|
+
<title>Code review</title>
|
|
17
|
+
<style>
|
|
18
|
+
:root { color-scheme: dark; --bg:#121212; --panel:#1b1b1b; --ink:#f4f4f0; --muted:#a9aaa5; --line:#3b3b3b; --blue:#8cc8ff; --red:#ff7d7d; --orange:#ffbf69; --green:#78dba9; --purple:#c7a6ff; }
|
|
19
|
+
* { box-sizing:border-box; }
|
|
20
|
+
body { margin:0; background:var(--bg); color:var(--ink); font:16px/1.55 ui-rounded, "Comic Sans MS", system-ui, sans-serif; }
|
|
21
|
+
body:before { content:""; position:fixed; inset:0; pointer-events:none; opacity:.08; background-image:radial-gradient(#fff 0.7px,transparent .7px); background-size:13px 13px; }
|
|
22
|
+
main { width:min(1060px, calc(100% - 32px)); margin:48px auto; }
|
|
23
|
+
.eyebrow { color:var(--blue); font:700 12px/1 monospace; letter-spacing:.16em; text-transform:uppercase; }
|
|
24
|
+
h1 { font-size:clamp(32px,6vw,62px); line-height:1; margin:10px 0 28px; letter-spacing:-.06em; }
|
|
25
|
+
.hero, .panel { background:var(--panel); border:2px solid var(--line); border-radius:13px 10px 15px 9px; box-shadow:5px 5px 0 #080808; }
|
|
26
|
+
.hero { padding:24px; display:flex; align-items:center; justify-content:space-between; gap:20px; }
|
|
27
|
+
.copy-prompt { cursor:pointer; color:#121212; background:var(--blue); border:2px solid var(--blue); border-radius:8px 6px 9px 5px; padding:7px 10px; font:800 11px monospace; text-transform:uppercase; box-shadow:2px 2px 0 #080808; }
|
|
28
|
+
.copy-prompt:hover { transform:translate(-1px,-1px); box-shadow:4px 4px 0 #080808; } .copy-status { color:var(--muted); font-size:12px; }
|
|
29
|
+
.verdict { border:2px solid currentColor; border-radius:10px 8px 11px 7px; padding:11px 16px; font-weight:800; letter-spacing:.08em; }
|
|
30
|
+
.approve { color:var(--green); } .reject { color:var(--red); }
|
|
31
|
+
.stats { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin:22px 0; }
|
|
32
|
+
.stat { padding:16px; border:2px solid var(--line); border-radius:8px 11px 7px 10px; background:#171717; }
|
|
33
|
+
.stat b { display:block; font-size:30px; line-height:1; } .stat span { color:var(--muted); font-size:12px; text-transform:uppercase; letter-spacing:.08em; }
|
|
34
|
+
.panel { padding:22px; margin:22px 0; } h2 { margin:0 0 14px; font-size:22px; }
|
|
35
|
+
.body { white-space:pre-wrap; color:#e4e4df; }
|
|
36
|
+
.filters { display:flex; flex-wrap:wrap; gap:8px; margin:-2px 0 16px; }
|
|
37
|
+
.filters button { cursor:pointer; color:var(--muted); background:#121212; border:1px solid var(--line); border-radius:7px 5px 8px 6px; padding:7px 11px; font:700 12px monospace; text-transform:uppercase; }
|
|
38
|
+
.filters button.active, .filters button:hover { color:var(--ink); border-color:var(--blue); box-shadow:2px 2px 0 #080808; }
|
|
39
|
+
.finding.hidden { display:none; }
|
|
40
|
+
.finding { border-left:5px solid var(--line); padding:14px 16px 16px; margin:12px 0; background:#151515; border-radius:4px 10px 8px 5px; }
|
|
41
|
+
.finding.critical { border-color:var(--red); } .finding.important { border-color:var(--orange); } .finding.suggestion { border-color:var(--blue); } .finding.nit { border-color:var(--purple); }
|
|
42
|
+
.finding-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:9px; }
|
|
43
|
+
.location { color:var(--blue); font:700 13px monospace; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .comment { white-space:pre-wrap; }
|
|
44
|
+
.severity { display:inline-flex; align-items:center; gap:6px; color:var(--muted); font:700 11px monospace; letter-spacing:.08em; text-transform:uppercase; margin-bottom:7px; }
|
|
45
|
+
.severity.critical { color:var(--red); } .severity.important { color:var(--orange); } .severity.suggestion { color:var(--blue); } .severity.nit { color:var(--purple); }
|
|
46
|
+
.codeblock { overflow:auto; margin:10px 0 0; padding:13px; background:#0c0c0c; border:1px solid var(--line); border-radius:7px; color:#d7d7d0; font:13px/1.6 ui-monospace, SFMono-Regular, Consolas, monospace; white-space:pre; }
|
|
47
|
+
.tok-keyword { color:#c7a6ff; } .tok-string { color:#a8d8a8; } .tok-number { color:#ffbf69; } .tok-comment { color:#777b78; font-style:italic; }
|
|
48
|
+
@media (max-width:650px) { main{margin:24px auto}.hero{align-items:flex-start;flex-direction:column}.stats{grid-template-columns:repeat(2,1fr)} }
|
|
49
|
+
</style>
|
|
50
|
+
</head>
|
|
51
|
+
<body><main>
|
|
52
|
+
<div class="eyebrow">review artifact // visualized</div><h1>Code review</h1>
|
|
53
|
+
<section class="hero"><div><div class="eyebrow">verdict</div><div id="verdict"></div></div><div id="summary"></div></section>
|
|
54
|
+
<section class="stats" id="stats"></section>
|
|
55
|
+
<section class="panel"><h2>Review notes</h2><div class="body" id="body"></div></section>
|
|
56
|
+
<section class="panel"><h2>Inline findings</h2><div class="filters" id="filters"><button class="active" data-filter="all">All</button><button data-filter="critical">Critical</button><button data-filter="important">Important</button><button data-filter="suggestion">Suggestions</button><button data-filter="nit">Nits</button></div><div id="comments"></div></section>
|
|
57
|
+
</main><script>
|
|
58
|
+
const review = __REVIEW_DATA__;
|
|
59
|
+
const esc = value => String(value ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
|
|
60
|
+
const comments = Array.isArray(review.comments) ? review.comments : [];
|
|
61
|
+
const counts = { critical:0, important:0, suggestion:0, nit:0 };
|
|
62
|
+
const kind = body => { const text=String(body||'').toLowerCase(); return text.includes('critical')?'critical':text.includes('important')?'important':text.includes('suggestion')?'suggestion':text.includes('nit')?'nit':'suggestion'; };
|
|
63
|
+
const severity = { critical:['🚨','Critical'], important:['⚠️','Important'], suggestion:['💡','Suggestion'], nit:['🧹','Nit'] };
|
|
64
|
+
const cleanBody = body => String(body || '').replace(/^[^\w\n]*\[(?:CRITICAL|IMPORTANT|SUGGESTION|NIT)\]\s*/i, '');
|
|
65
|
+
const highlighted = code => { const pattern=/(\/\/.*|#.*|\/\*[\s\S]*?\*\/|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`|\b(?:const|let|var|function|return|if|else|for|while|class|new|throw|async|await|import|from|true|false|null|undefined)\b|\b\d+(?:\.\d+)?\b)/g; return String(code).split(pattern).map((part, i) => { if (i % 2 === 0) return esc(part); const cls=/^(\/\/|#|\/\*)/.test(part)?'tok-comment':/^["'`]/.test(part)?'tok-string':/^\d/.test(part)?'tok-number':'tok-keyword'; return `<span class="${cls}">${esc(part)}</span>`; }).join(''); };
|
|
66
|
+
const formatBody = body => { const source=String(body||''), pattern=/```(?:[\w+-]+)?\n([\s\S]*?)```/g; let result='', last=0, match; while ((match=pattern.exec(source))) { result += esc(source.slice(last, match.index)); result += `<pre class="codeblock"><code>${highlighted(match[1])}</code></pre>`; last=pattern.lastIndex; } return result + esc(source.slice(last)); };
|
|
67
|
+
comments.forEach(c => counts[kind(c.body)]++);
|
|
68
|
+
const verdict = review.verdict === 'REJECT' ? 'REJECT' : 'APPROVE';
|
|
69
|
+
document.title = `${verdict} · Code review`;
|
|
70
|
+
document.querySelector('#verdict').innerHTML = `<div class="verdict ${verdict === 'REJECT' ? 'reject':'approve'}">${verdict}</div>`;
|
|
71
|
+
document.querySelector('#summary').textContent = `${comments.length} inline ${comments.length === 1 ? 'finding':'findings'}`;
|
|
72
|
+
document.querySelector('#body').textContent = review.body || 'No review body provided.';
|
|
73
|
+
document.querySelector('#stats').innerHTML = Object.entries(counts).map(([name,count]) => `<div class="stat"><b>${count}</b><span>${name}</span></div>`).join('');
|
|
74
|
+
document.querySelector('#comments').innerHTML = comments.length ? comments.map((c, i) => { const type=kind(c.body), [icon,label]=severity[type]; const location = `${esc(c.path || 'unknown file')}:${esc(c.line ?? '?')} · ${esc(c.side || '')}`; return `<article class="finding ${type}" data-kind="${type}"><div class="finding-head"><div><div class="location">${location}</div><div class="severity ${type}">${icon} ${label}</div></div><button class="copy-prompt" type="button" data-finding="${i}">Copy fix prompt</button></div><div class="comment">${formatBody(cleanBody(c.body))}</div><span class="copy-status" aria-live="polite"></span></article>`; }).join('') : '<div class="body">No inline findings.</div>';
|
|
75
|
+
document.querySelector('#filters').addEventListener('click', event => { const button=event.target.closest('button'); if (!button) return; const filter=button.dataset.filter; document.querySelectorAll('#filters button').forEach(item => item.classList.toggle('active', item === button)); document.querySelectorAll('.finding').forEach(item => item.classList.toggle('hidden', filter !== 'all' && item.dataset.kind !== filter)); });
|
|
76
|
+
const fixPrompt = finding => `You are fixing one code review finding. Apply the smallest necessary change in the repository; do not weaken behavior or remove coverage.\n\nReview verdict: ${verdict}\n\nReview context:\n${review.body || 'No review body provided.'}\n\nTarget finding:\n[${String(finding.body || '').split(' ')[1] || 'FINDING'}] ${finding.path || 'unknown file'}:${finding.line ?? '?'} (${finding.side || 'RIGHT'})\n${finding.body || ''}\n\nAfter fixing this finding, run the relevant tests and summarize the change and test result.`;
|
|
77
|
+
const copyText = async (text, status) => { try { await navigator.clipboard.writeText(text); } catch (_) { const area=document.createElement('textarea'); area.value=text; area.style.position='fixed'; area.style.opacity='0'; document.body.append(area); area.select(); document.execCommand('copy'); area.remove(); } status.textContent='Copied'; setTimeout(() => { status.textContent=''; }, 2200); };
|
|
78
|
+
document.querySelector('#comments').addEventListener('click', event => { const button=event.target.closest('[data-finding]'); if (!button) return; const finding=comments[Number(button.dataset.finding)]; copyText(fixPrompt(finding), button.parentElement.parentElement.querySelector('.copy-status')); });
|
|
79
|
+
</script></body></html>"""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def main() -> None:
|
|
83
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
84
|
+
parser.add_argument("--review-json", default="review.json")
|
|
85
|
+
parser.add_argument("--output", default="review.html")
|
|
86
|
+
args = parser.parse_args()
|
|
87
|
+
review = json.loads(Path(args.review_json).read_text(encoding="utf-8"))
|
|
88
|
+
data = json.dumps(review, ensure_ascii=False, separators=(",", ":"))
|
|
89
|
+
data = data.replace("<", "\\u003c").replace(">", "\\u003e").replace("&", "\\u0026")
|
|
90
|
+
html = PAGE.replace("__REVIEW_DATA__", data)
|
|
91
|
+
Path(args.output).write_text(html, encoding="utf-8")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
main()
|