@mohammadhprp/system-prompt 0.12.4 → 0.12.6
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/README.md +2 -6
- package/framework/commands/audit-your-codebase.md +47 -0
- package/framework/commands/explain-codebase.md +101 -0
- package/framework/commands/learn.md +1 -1
- package/framework/plugins/ponytail/README.md +1 -1
- package/framework/plugins/ponytail/capabilities.md +1 -1
- package/framework/references/standards/pull-requests.md +1 -1
- package/framework/skills/README.md +1 -0
- package/framework/skills/adhd/SKILL.md +141 -0
- package/framework/skills/adhd/examples.md +77 -0
- package/framework/skills/gh/SKILL.md +157 -0
- package/framework/skills/gh/examples.md +10 -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/review/SKILL.md +106 -11
- package/framework/skills/review/examples.md +4 -3
- 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/unslop/SKILL.md +34 -3
- package/framework/skills/unslop/examples.md +2 -0
- package/framework/skills/unslop/references/eval.md +44 -0
- package/package.json +1 -1
- package/src/catalog.js +6 -7
- package/framework/commands/changelog.md +0 -44
- package/framework/commands/commit.md +0 -28
- package/framework/commands/mr.md +0 -45
- package/framework/commands/pr.md +0 -39
- package/framework/commands/release.md +0 -34
- package/framework/commands/review.md +0 -24
|
@@ -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()
|