specpipe 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1319 -0
- package/bin/devkit.js +3 -0
- package/package.json +61 -0
- package/src/cli.js +76 -0
- package/src/commands/check.js +33 -0
- package/src/commands/diff.js +84 -0
- package/src/commands/init-adopt.js +54 -0
- package/src/commands/init-agents.js +118 -0
- package/src/commands/init-global.js +102 -0
- package/src/commands/init.js +311 -0
- package/src/commands/list.js +54 -0
- package/src/commands/remove.js +133 -0
- package/src/commands/upgrade.js +215 -0
- package/src/lib/agent-guards.js +100 -0
- package/src/lib/agent-install.js +161 -0
- package/src/lib/agents.js +280 -0
- package/src/lib/claude-global.js +183 -0
- package/src/lib/detector.js +93 -0
- package/src/lib/hasher.js +21 -0
- package/src/lib/installer.js +213 -0
- package/src/lib/logger.js +16 -0
- package/src/lib/manifest.js +102 -0
- package/src/lib/reconcile.js +56 -0
- package/templates/.claude/CLAUDE.md +79 -0
- package/templates/.claude/hooks/comment-guard.js +126 -0
- package/templates/.claude/hooks/file-guard.js +216 -0
- package/templates/.claude/hooks/glob-guard.js +104 -0
- package/templates/.claude/hooks/path-guard.sh +118 -0
- package/templates/.claude/hooks/self-review.sh +27 -0
- package/templates/.claude/hooks/sensitive-guard.sh +227 -0
- package/templates/.claude/settings.json +68 -0
- package/templates/docs/WORKFLOW.md +325 -0
- package/templates/docs/specs/.gitkeep +0 -0
- package/templates/hooks/specpipe-read-guard.sh +42 -0
- package/templates/hooks/specpipe-shell-guard.sh +65 -0
- package/templates/rules/specpipe-guards.md +40 -0
- package/templates/scripts/test-hooks.sh +66 -0
- package/templates/skills/sp-build/SKILL.md +776 -0
- package/templates/skills/sp-challenge/SKILL.md +255 -0
- package/templates/skills/sp-commit/SKILL.md +174 -0
- package/templates/skills/sp-explore/SKILL.md +730 -0
- package/templates/skills/sp-fix/SKILL.md +266 -0
- package/templates/skills/sp-humanize/SKILL.md +212 -0
- package/templates/skills/sp-investigate/SKILL.md +648 -0
- package/templates/skills/sp-md-render/SKILL.md +200 -0
- package/templates/skills/sp-md-render/components.md +415 -0
- package/templates/skills/sp-md-render/template.html +283 -0
- package/templates/skills/sp-plan/SKILL.md +947 -0
- package/templates/skills/sp-review/SKILL.md +268 -0
- package/templates/skills/sp-scaffold/SKILL.md +237 -0
- package/templates/skills/sp-scaffold/references/ARCHITECTURE.md.tmpl +228 -0
- package/templates/skills/sp-scaffold/references/DESIGN.md.tmpl +113 -0
- package/templates/skills/sp-scaffold/references/adr/NNNN-template.md +92 -0
- package/templates/skills/sp-scaffold/references/stack-profiles/react.md +36 -0
- package/templates/skills/sp-spec-render/SKILL.md +254 -0
- package/templates/skills/sp-spec-render/components.md +418 -0
- package/templates/skills/sp-spec-render/examples/user-auth.html +749 -0
- package/templates/skills/sp-spec-render/examples/user-auth.md +114 -0
- package/templates/skills/sp-spec-render/template.html +222 -0
- package/templates/skills/sp-voices/SKILL.md +1184 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: |
|
|
3
|
+
Test-first bug fix — write failing test, fix code, verify green.
|
|
4
|
+
Iron Law: never fix without finding root cause first.
|
|
5
|
+
Use when asked to "fix this bug", "fix bug", "sửa lỗi", "sửa bug",
|
|
6
|
+
"this is broken", "cái này hỏng", or when user reports a reproducible
|
|
7
|
+
bug with repro steps or a stack trace.
|
|
8
|
+
Proactively invoke this skill (do NOT patch directly) when the user
|
|
9
|
+
describes a bug they want fixed.
|
|
10
|
+
For complex/ambiguous bugs (outage, regression, "it was working yesterday",
|
|
11
|
+
data corruption), start with /sp-investigate first, then hand the report to /sp-fix.
|
|
12
|
+
Skip for typos or one-line obvious fixes.
|
|
13
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, mcp__graphatlas__*
|
|
14
|
+
---
|
|
15
|
+
Test-first bug fix — write failing test, fix code, verify green.
|
|
16
|
+
|
|
17
|
+
Bug: $ARGUMENTS
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Iron Law
|
|
22
|
+
|
|
23
|
+
**NEVER fix without finding the root cause first.**
|
|
24
|
+
|
|
25
|
+
Fixing symptoms creates whack-a-mole debugging. Every fix that doesn't address the root cause makes the next bug harder to find.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Phase 0a — Graphatlas probe (run once)
|
|
30
|
+
|
|
31
|
+
Before locating code, probe whether graphatlas (GA) is connected:
|
|
32
|
+
|
|
33
|
+
1. Call `mcp__graphatlas__ga_architecture` with `max_modules: 1`.
|
|
34
|
+
2. Interpret:
|
|
35
|
+
- Returns `modules` → **GA available.** Use `ga_*` for code discovery, blast-radius, and risk. Grep is fallback only.
|
|
36
|
+
- Error `STALE_INDEX` → call `mcp__graphatlas__ga_reindex` (mode `"full"`), retry once, then treat as available.
|
|
37
|
+
- Tool not found / connection error / any other failure → **GA unavailable.** Use grep/glob throughout this run. Do not re-probe.
|
|
38
|
+
3. After edits the graph goes stale. Reindex on demand: when a later `ga_*` call returns `STALE_INDEX`, call `mcp__graphatlas__ga_reindex` (mode `"full"`) once then retry. Don't reindex preemptively after every edit.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Phase 0: Investigate
|
|
43
|
+
|
|
44
|
+
Don't jump to code. Understand the bug first:
|
|
45
|
+
|
|
46
|
+
0. **Investigation handoff check.** If `$ARGUMENTS` references a file under `docs/investigate/`, read it first — it contains pre-built root cause hypothesis, blast radius, and recommended actions from `/sp-investigate`. Skip redundant discovery; jump to Phase 1 using its findings. If no such file and the bug is complex/ambiguous/production-critical → suggest the user run `/sp-investigate "<bug>"` first; otherwise proceed.
|
|
47
|
+
|
|
48
|
+
1. **Parse the report.** Symptom? Expected vs actual? Repro steps? If context is missing → ask ONE question via AskUserQuestion before proceeding.
|
|
49
|
+
2. **Locate the code.** **If GA available (per Phase 0a):** `ga_symbols("<function or type>")` → definitions; `ga_callers` + `ga_callees` on the resolved symbol → call graph; `ga_impact(symbol=...)` → blast radius + affected tests + risk in one shot; `ga_file_summary` before reading a file in full. **If GA unavailable or the query is free text** (error strings inside literals, log lines): grep.
|
|
50
|
+
3. **Check history.** `git log --oneline -20 -- <affected-files>` — was this working before? What changed? Regression = root cause is in the diff.
|
|
51
|
+
4. **Pattern check.** Match the symptom against known bug patterns:
|
|
52
|
+
|
|
53
|
+
| Pattern | Signature | Where to look |
|
|
54
|
+
|---------|-----------|---------------|
|
|
55
|
+
| Race condition | Intermittent, timing-dependent | Concurrent access to shared state |
|
|
56
|
+
| Nil/null propagation | NoMethodError, TypeError, NullPointerException | Missing guards on optional values |
|
|
57
|
+
| State corruption | Inconsistent data, partial updates | Transactions, callbacks, hooks |
|
|
58
|
+
| Integration failure | Timeout, unexpected response | External API calls, service boundaries |
|
|
59
|
+
| Config drift | Works locally, fails in staging/prod | Env vars, feature flags, DB state |
|
|
60
|
+
| Stale cache | Shows old data, fixes on cache clear | Redis, CDN, browser cache |
|
|
61
|
+
|
|
62
|
+
5. **Reproduce deterministically.** If you can't trigger the bug reliably → gather more evidence. Do NOT guess.
|
|
63
|
+
|
|
64
|
+
> **If GA available, lean on it for steps 2 and 4.** `ga_symbols` resolves names, `ga_callers`/`ga_callees` map the call graph, `ga_impact` returns blast radius + test gaps + risk, `ga_architecture` reveals which module/layer (auth, payment, core) the bug sits in, `ga_risk` scores whether a change here is safe. If GA is unavailable, fall back to grep + `git log` + manual reading.
|
|
65
|
+
|
|
66
|
+
**Required output:** `Root cause hypothesis: ...` — a specific, testable claim about what is wrong and why.
|
|
67
|
+
|
|
68
|
+
**Required output 2: Bug Path Diagram**
|
|
69
|
+
|
|
70
|
+
Draw a coverage diagram for the buggy function using the same format as sp-build:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
CODE PATH COVERAGE
|
|
74
|
+
===========================
|
|
75
|
+
[+] src/services/affected.ts
|
|
76
|
+
│
|
|
77
|
+
└── affectedFn()
|
|
78
|
+
├── [★★ TESTED] Normal path — affected.test.ts:12
|
|
79
|
+
├── [GAP] Edge case X (← bug lives here) — NO TEST
|
|
80
|
+
│ └── [GAP] Downstream effect — NO TEST
|
|
81
|
+
└── [★★ TESTED] Other branch — affected.test.ts:20
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If the bug is in a view/template layer (UI render, layout, data binding, styling) — mark the view path `[→MANUAL]` and test the logic layer backing it (ViewModel, Presenter, helper) instead. If there is no logic layer to test, the fix is `[→MANUAL]` only — note what to visually verify.
|
|
85
|
+
|
|
86
|
+
If you cannot identify a specific `[GAP]` path → the hypothesis is not specific enough. Investigate further.
|
|
87
|
+
|
|
88
|
+
If the bug is in a dependency/config/data (not project code), say so before proceeding.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Test Command
|
|
93
|
+
|
|
94
|
+
Resolve once before running tests. Auto-detect from project markers:
|
|
95
|
+
|
|
96
|
+
| Marker | Run all | Run filtered |
|
|
97
|
+
|--------|---------|-------------|
|
|
98
|
+
| vitest config / vitest in package.json | `npx vitest run` | `npx vitest run -t "<pattern>"` |
|
|
99
|
+
| jest config / jest in package.json | `npx jest --no-cache` | `npx jest --no-cache -t "<pattern>"` |
|
|
100
|
+
| pyproject.toml / pytest.ini | `python3 -m pytest -x` | `python3 -m pytest -x -k "<pattern>"` |
|
|
101
|
+
| Cargo.toml | `cargo test` | `cargo test "<pattern>"` |
|
|
102
|
+
| go.mod | `go test ./...` | `go test ./... -run "<pattern>"` |
|
|
103
|
+
| build.gradle | `./gradlew test` | `./gradlew test --tests "<pattern>"` |
|
|
104
|
+
| *.sln | `dotnet test` | `dotnet test --filter "<pattern>"` |
|
|
105
|
+
| Package.swift | `swift test` | `swift test --filter "<pattern>"` |
|
|
106
|
+
| Gemfile | `bundle exec rspec` | `bundle exec rspec -e "<pattern>"` |
|
|
107
|
+
|
|
108
|
+
All test commands below use `TEST_CMD` to mean the resolved command. For filtered runs, use the framework's native filter flag from the table above.
|
|
109
|
+
|
|
110
|
+
**Filter pattern verification (MANDATORY):** A filter matching 0 tests exits 0 on many frameworks — false green. Before trusting any filtered run, confirm match count ≥1:
|
|
111
|
+
|
|
112
|
+
- vitest: `npx vitest list -t "<pattern>"`
|
|
113
|
+
- jest: add `--passWithNoTests=false`
|
|
114
|
+
- pytest: `-k "<pattern>" --collect-only -q`
|
|
115
|
+
- cargo: `cargo test "<pattern>" -- --list`
|
|
116
|
+
- go: `go test -run "<pattern>" -list ".*" ./...`
|
|
117
|
+
- gradle / dotnet / swift / rspec / other: if no equivalent listing command is known, fall back to `grep -r "<test name>" <test-dir>` — string must exist. Log `FILTER_VERIFY: fallback-grep` in Phase 5 report.
|
|
118
|
+
|
|
119
|
+
0 matches → test name / file location wrong. Fix before proceeding. Never interpret 0-match as PASS. **Max 3 retry attempts** on filter-match failure; if still 0 after 3, stop and report BLOCKED.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Phase 1: Write a Failing Test
|
|
124
|
+
|
|
125
|
+
**REGRESSION RULE:** If the bug exists because the diff changed existing behavior AND no test covered that path → this is a regression. A regression test is a **CRITICAL requirement.** Add the comment: `// Regression: <bug> — <file:line> broke this path`
|
|
126
|
+
|
|
127
|
+
Write a test that reproduces the bug. It **MUST fail** with current code.
|
|
128
|
+
|
|
129
|
+
Verify filter match first (see "Filter pattern verification" in the Test Command section). Then run:
|
|
130
|
+
```
|
|
131
|
+
TEST_CMD --filter "<test name>"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Capture the raw failure output** (stack trace / assertion diff). Paste it into the Phase 5 DEBUG REPORT `Evidence:` field verbatim — a summary like "test fails" is not evidence.
|
|
135
|
+
|
|
136
|
+
- **FAILS** → reproduced. Continue.
|
|
137
|
+
- **0 TESTS MATCHED** → filter/test name issue, not reproduction. Fix before proceeding.
|
|
138
|
+
- **PASSES** → hypothesis may be wrong. Use `AskUserQuestion`:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"questions": [
|
|
143
|
+
{
|
|
144
|
+
"question": "The test passes with current code — the bug isn't reproduced yet. How to proceed?",
|
|
145
|
+
"header": "Test Passes Unexpectedly",
|
|
146
|
+
"multiSelect": false,
|
|
147
|
+
"options": [
|
|
148
|
+
{"label": "Provide different repro steps or environment details (human: ~30m / CC: ~5m) | Completeness: 10/10"},
|
|
149
|
+
{"label": "The bug may be environment-specific — describe the setup (human: ~1h / CC: ~10m) | Completeness: 9/10"},
|
|
150
|
+
{"label": "Stop and report BLOCKED — cannot reproduce, need human investigation (Completeness: N/A — no fix applied)"}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**3-strike rule:** If 3 hypotheses all fail to reproduce the bug → STOP. Use AskUserQuestion:
|
|
158
|
+
"3 hypotheses tested, none confirmed. This may be architectural — not a simple bug."
|
|
159
|
+
Options: A) New hypothesis (describe new evidence), B) Escalate for human review, C) Instrument the area and catch it next time
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Phase 2: Fix
|
|
164
|
+
|
|
165
|
+
Make the **minimal change** needed.
|
|
166
|
+
|
|
167
|
+
| Do | Don't |
|
|
168
|
+
|----|-------|
|
|
169
|
+
| Fix the specific bug | Refactor surrounding code |
|
|
170
|
+
| Add a guard for the edge case | Rewrite the function |
|
|
171
|
+
| Explain what and why before editing | Silently change code |
|
|
172
|
+
|
|
173
|
+
**Blast radius check:** If the fix requires touching >5 files → stop and use AskUserQuestion before editing anything:
|
|
174
|
+
"This fix touches N files — that's a large blast radius for a bug fix. A) Proceed — root cause genuinely spans these files, B) Split — fix critical path now, defer the rest, C) Rethink — there may be a more targeted approach"
|
|
175
|
+
|
|
176
|
+
**Similar-risk scan (MANDATORY after fix, before Phase 3):** Grep for the same pattern that caused this bug, scoped to:
|
|
177
|
+
1. The same file as the fix (all sibling functions in the fixed file).
|
|
178
|
+
2. Direct callers of the fixed function (one level up — if GA available, `ga_callers`; otherwise grep or IDE refs).
|
|
179
|
+
|
|
180
|
+
Do NOT auto-fix findings — the minimal-fix rule stands. Record each under Phase 5 `SIMILAR_RISK:` as `<file:line> — same pattern, unguarded`.
|
|
181
|
+
|
|
182
|
+
**Timebox:** 5 minutes max. If the pattern is too generic to grep cleanly (e.g., fix is a common idiom), record `SIMILAR_RISK: scan skipped — pattern too generic, reason: <why>` and move on. Do NOT let this phase block the fix from landing. Silent skipping without a reason note is not acceptable.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Phase 3: Verify
|
|
187
|
+
|
|
188
|
+
1. Run the bug test: `TEST_CMD --filter "<test name>"` → must PASS.
|
|
189
|
+
2. Run full suite: `TEST_CMD` → no regressions.
|
|
190
|
+
|
|
191
|
+
If other tests break → the fix caused a regression. Investigate. Do NOT weaken existing tests.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Phase 4: Root Cause Analysis
|
|
196
|
+
|
|
197
|
+
After fixing, document:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
Symptom: <what the user saw>
|
|
201
|
+
Root cause: <why it happened>
|
|
202
|
+
Gap: <why not caught earlier — missing test? wrong assumption? missing spec?>
|
|
203
|
+
Prevention: <suggest one: type constraint, validation, lint rule, spec update (including acceptance scenarios)>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
This is non-optional for serious bugs. For trivial bugs, the fix summary is enough.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Phase 5: Summary
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
DEBUG REPORT
|
|
214
|
+
════════════════════════════════════════
|
|
215
|
+
Bug: <description>
|
|
216
|
+
Hypothesis: <what you predicted> → <confirmed or actual cause>
|
|
217
|
+
Root cause: <what was actually wrong>
|
|
218
|
+
Files changed: [all production files touched]
|
|
219
|
+
Fix: <file:line — what changed>
|
|
220
|
+
Evidence: <paste raw failing-then-passing test output, verbatim>
|
|
221
|
+
Regression test: <file:test name>
|
|
222
|
+
Full suite: All passing ✓
|
|
223
|
+
Similar risk: [SIMILAR_RISK findings from Phase 2 scan, or "none"]
|
|
224
|
+
Manual needed: [→MANUAL gaps, or "none"]
|
|
225
|
+
Status: DONE | DONE_WITH_CONCERNS | BLOCKED
|
|
226
|
+
════════════════════════════════════════
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Spec Update Signal
|
|
230
|
+
|
|
231
|
+
After fixing, check these conditions. If ANY is true → **must** signal.
|
|
232
|
+
|
|
233
|
+
**Signal when (MUST):**
|
|
234
|
+
|
|
235
|
+
| # | Condition |
|
|
236
|
+
|---|-----------|
|
|
237
|
+
| S1 | Fix covers an edge case or error path with no corresponding AS in the spec |
|
|
238
|
+
| S2 | Bug existed because an AS described wrong behavior — After fix, code and AS now conflict |
|
|
239
|
+
| S3 | Fix adds a new constraint or guard (null check, balance guard, validation) not in spec |
|
|
240
|
+
|
|
241
|
+
**Do not signal when:**
|
|
242
|
+
- Fix is a clear typo/off-by-one — code was always wrong relative to spec, no new behavior
|
|
243
|
+
- Performance-only fix — output unchanged
|
|
244
|
+
|
|
245
|
+
**Signal format:**
|
|
246
|
+
```
|
|
247
|
+
⚠️ Spec Update Needed — run `/sp-plan docs/specs/<feature>/<feature>.md '<describe change>'`
|
|
248
|
+
Reason: [S1 | S2 | S3] — <one line: what is missing or mismatched>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Multiple Bugs
|
|
252
|
+
|
|
253
|
+
If `$ARGUMENTS` describes multiple bugs: triage by severity, fix one at a time, commit each separately.
|
|
254
|
+
|
|
255
|
+
## Rules
|
|
256
|
+
1. **Investigate before coding.** Root cause hypothesis before test. Evidence before fix.
|
|
257
|
+
2. **Minimal fix.** One bug, one change. Don't improve the neighborhood.
|
|
258
|
+
3. **Never weaken tests.** If existing tests break, the fix is wrong.
|
|
259
|
+
4. **Ask before touching production code** if unsure.
|
|
260
|
+
5. **One bug, one commit.** Each fix independently revertable.
|
|
261
|
+
|
|
262
|
+
**Red flags — slow down if you see these:**
|
|
263
|
+
- "Quick fix for now" — there is no "for now". Fix it right or escalate.
|
|
264
|
+
- Proposing a fix before tracing data flow — you're guessing, not debugging.
|
|
265
|
+
- Each fix reveals a new problem elsewhere — wrong layer, not wrong code.
|
|
266
|
+
- Never say "this should fix it" — verify and prove it. Run the tests.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: |
|
|
3
|
+
Rephrase plan, notes, bullet points, or drafts into natural human-sounding text,
|
|
4
|
+
ready to copy-paste and send. Strips AI tone before content goes out.
|
|
5
|
+
Use when asked to "humanize", "viết lại", "rephrase", "làm cho tự nhiên hơn",
|
|
6
|
+
"soạn email/comment/post", "không nghe giống AI", "bỏ giọng AI",
|
|
7
|
+
or invoked via `/sp-humanize`.
|
|
8
|
+
Infers target format, language, audience, and tone from context — including
|
|
9
|
+
uncommon formats (PR description, release note, slack announcement, postmortem,
|
|
10
|
+
customer reply, LinkedIn post, RFC).
|
|
11
|
+
Proactively invoke this skill (do NOT rephrase directly) when the user pastes
|
|
12
|
+
plan / notes / AI output with a request to send it somewhere — the anti-AI
|
|
13
|
+
pattern checks and preservation rules catch gaps that hand-paraphrasing misses.
|
|
14
|
+
Skip for pure translation, summarization, or generating content from zero —
|
|
15
|
+
those are not rephrasing.
|
|
16
|
+
allowed-tools: AskUserQuestion
|
|
17
|
+
---
|
|
18
|
+
# /sp-humanize — Rephrase to human voice
|
|
19
|
+
|
|
20
|
+
Turn plan / bullet / notes into natural prose, ready to send. Return the final
|
|
21
|
+
version directly — no preamble, no explanation of what was changed.
|
|
22
|
+
|
|
23
|
+
Input: $ARGUMENTS
|
|
24
|
+
|
|
25
|
+
Explicit user instructions always override the rules in this file. Asked for
|
|
26
|
+
emoji → use emoji. Asked for formal → formal. Asked to keep bullets → keep them.
|
|
27
|
+
|
|
28
|
+
Follow-up edits stay inside the skill. When the user asks to adjust an
|
|
29
|
+
already-humanized output ("shorter", "longer", "in English", "more formal"),
|
|
30
|
+
that request still runs through Step 5 + Step 7 before returning. Do not treat
|
|
31
|
+
it as a casual rephrase, that is exactly how em dashes and buzzwords leak back in.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step 1 — Infer target format
|
|
36
|
+
|
|
37
|
+
Walk this priority list and stop at the first clear signal:
|
|
38
|
+
|
|
39
|
+
1. **User stated it** — any named format → produce exactly that format.
|
|
40
|
+
2. **Session context** — channel currently being discussed (writing a PR → PR description; ongoing incident → postmortem; sprint discussion → status update).
|
|
41
|
+
3. **Input shape** — greeting/closing → email; ticket key/status → jira; heading/code → markdown.
|
|
42
|
+
4. **Fallback** — plain text, tight, in the session's dominant language.
|
|
43
|
+
|
|
44
|
+
No fixed whitelist. Uncommon or hybrid formats → follow that format's conventions. Unclear → prefer short, direct, focused on what the reader needs to know. Do not ask if the format can be inferred.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Step 2 — Infer audience
|
|
49
|
+
|
|
50
|
+
Same content, phrasing shifts by reader:
|
|
51
|
+
|
|
52
|
+
| Audience | Phrasing |
|
|
53
|
+
|----------|----------|
|
|
54
|
+
| Engineering / internal | Technical terms direct, no re-explaining |
|
|
55
|
+
| Customer / external | Outcome-focused, hide implementation |
|
|
56
|
+
| Executive / stakeholder | Outcome + impact, drop technical detail unless critical |
|
|
57
|
+
| Public / community (blog, LinkedIn, OSS) | Enough context for outsiders, do not assume internal knowledge |
|
|
58
|
+
| Mixed | Lean toward the less technical side |
|
|
59
|
+
|
|
60
|
+
Unclear → infer from channel: jira/PR → engineering; customer support → external; public release note → public.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Step 3 — Language
|
|
65
|
+
|
|
66
|
+
Follow the session's dominant language. Mixed Vietnamese-English is normal — keep technical terms (deploy, rollback, API, sprint, blocker, hotfix, regression, commit, PR) untranslated. Do not add parenthetical glosses like `deploy (triển khai)` unless the user asks.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Step 4 — Format per channel convention
|
|
71
|
+
|
|
72
|
+
Apply to every format, including ones not listed:
|
|
73
|
+
|
|
74
|
+
- **Openings / closings** — only when the channel demands them (email yes, jira/PR no).
|
|
75
|
+
- **Structure** — match reader expectations. PR: What/Why/How. Release note: Added/Fixed/Changed. Postmortem: timeline / root cause / action. Slack: TL;DR first.
|
|
76
|
+
- **Length** — enough to deliver, no more. Every section must do work.
|
|
77
|
+
- **Bullets vs prose** — bullets when ≥3 parallel items or scanning matters; prose when there is flow or content is short.
|
|
78
|
+
- **Tone** — direct by default. More formal for external / executive. Friendlier for internal / chat.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Step 5 — Preservation (mandatory)
|
|
83
|
+
|
|
84
|
+
Never paraphrase these: numbers, names of people / products, error codes, file paths, line numbers, commands, URLs, specific times, technical terms, commitments, decisions.
|
|
85
|
+
|
|
86
|
+
**Do not soften certainty.** "Will ship Monday" ≠ "hope to ship Monday". "Committed" ≠ "trying". "We chose Postgres" ≠ "we are considering Postgres". The certainty in the source is data.
|
|
87
|
+
|
|
88
|
+
**Self-check before returning:**
|
|
89
|
+
- Did any date / number change?
|
|
90
|
+
- Did any commitment / deadline disappear or get softened?
|
|
91
|
+
- Did any decision / risk get dropped?
|
|
92
|
+
- Is there any new info (not present in the source)?
|
|
93
|
+
- Any em dash `—` in body text, or leftover typographic unicode (en dash `–`, curly quotes, `…`, `•`, decorative emoji) anywhere?
|
|
94
|
+
- Any antithesis shape ("not X, it's Y" / "không phải X mà là Y")?
|
|
95
|
+
- Any banned buzzword or hollow opening/closing from Step 7?
|
|
96
|
+
|
|
97
|
+
If yes to any → fix it. This check runs on every return, including follow-up edits (see below).
|
|
98
|
+
|
|
99
|
+
Vague input → short, neutral output. Do not invent detail to make sentences flow. Do not add empty sections ("Risks: N/A", "ETA: TBD"). If context is too thin for a format that demands structure (postmortem, RFC) → ask one specific question via `AskUserQuestion` rather than guess.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Step 6 — Compression / expansion
|
|
104
|
+
|
|
105
|
+
- **"Shorter", "brief", "tighten"** → cut 30-60%, keep load-bearing information.
|
|
106
|
+
- **"Longer", "more context"** → improve transitions, clarify meaning. **Do not** add new facts, risks, benefits, or timelines.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Step 7 — Anti-AI patterns (hard rules)
|
|
111
|
+
|
|
112
|
+
**Punctuation**
|
|
113
|
+
- Avoid em dash `—` in body text. Use comma, period, colon, or split the sentence.
|
|
114
|
+
- Em dash is fine in subjects or headings.
|
|
115
|
+
- No emoji unless the user asks or the channel genuinely uses them (friendly slack, social post).
|
|
116
|
+
- Limit consecutive semicolons / colons.
|
|
117
|
+
|
|
118
|
+
**Keyboard symbols only** — normalize typographic unicode to plain ASCII everywhere, including headings. These are silent AI/word-processor tells:
|
|
119
|
+
- en dash `–` → `-`
|
|
120
|
+
- curly quotes `“ ” ‘ ’` → straight `"` `'`
|
|
121
|
+
- ellipsis `…` → `...`
|
|
122
|
+
- unicode bullet `•` → `-` or `*`
|
|
123
|
+
- decorative emoji (✨ 🚀 ✅ ❌ ➡ …) → remove, unless the user asked or the channel genuinely uses them
|
|
124
|
+
Exception: keep a character if the user's source deliberately used it and asked to preserve formatting.
|
|
125
|
+
|
|
126
|
+
**No antithesis** — do not manufacture contrast to create rhythm. Banned shapes and their variants:
|
|
127
|
+
- "It's not X, it's Y"
|
|
128
|
+
- "Not just X, but Y"
|
|
129
|
+
- "X isn't the problem, Y is"
|
|
130
|
+
- "không phải X, mà là Y"
|
|
131
|
+
State the claim directly. "Y is what matters" beats "It's not X, it's Y" — the X half is usually filler the writer never needed.
|
|
132
|
+
|
|
133
|
+
**Format**
|
|
134
|
+
- Do not bullet-ize 1-3 sentences that can be prose.
|
|
135
|
+
- No headings for short passages.
|
|
136
|
+
- No Title Case On Every Word.
|
|
137
|
+
|
|
138
|
+
**Banned EN buzzwords**
|
|
139
|
+
delve into, leverage, empower, robust, seamless, game-changing, cutting-edge, state-of-the-art, next-level, unlock, foster collaboration, navigate the complexities, in today's fast-paced world, synergy, world-class, innovative solution.
|
|
140
|
+
|
|
141
|
+
**Banned VI buzzwords**
|
|
142
|
+
"nhằm mục đích", "đảm bảo rằng", "tối ưu hóa trải nghiệm", "giải pháp toàn diện", "mang đến giá trị", "đồng hành cùng", "không ngừng nỗ lực".
|
|
143
|
+
|
|
144
|
+
**Banned hollow openings / closings**
|
|
145
|
+
"I hope this email finds you well", "Hope you're doing great", "In conclusion", "Overall", "Together, we can...", "Trân trọng cảm ơn và mong nhận được phản hồi sớm", "Rất mong nhận được sự hợp tác".
|
|
146
|
+
|
|
147
|
+
**Tone**
|
|
148
|
+
- No fake enthusiasm, no salesy phrasing.
|
|
149
|
+
- No "rule of three" pile-ups (clear, concise, and effective).
|
|
150
|
+
- Do not add certainty or emotion that the source lacks.
|
|
151
|
+
- Vary sentence rhythm; allow slight imperfection. Do not over-smooth.
|
|
152
|
+
|
|
153
|
+
**Vietnamese specifics**
|
|
154
|
+
- Use "anh/chị" instead of "quý khách hàng" for internal / friendly B2B.
|
|
155
|
+
- Avoid "Quý công ty chúng tôi xin trân trọng thông báo" for internal email.
|
|
156
|
+
- Avoid "Trong quá trình..." when a direct phrasing works.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Step 8 — Output
|
|
161
|
+
|
|
162
|
+
Return the final version directly. No explanation of edits.
|
|
163
|
+
|
|
164
|
+
Only offer multiple versions when the differences are genuinely useful (shorter / more formal / softer) and the user seems to want a choice — use `AskUserQuestion` to confirm rather than dumping three variants by default.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Examples
|
|
169
|
+
|
|
170
|
+
Illustrative, not a format whitelist.
|
|
171
|
+
|
|
172
|
+
**Input:**
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
/sp-humanize reply jira
|
|
176
|
+
- Fix null pointer bug at UserService.java:45
|
|
177
|
+
- Will do in sprint 24
|
|
178
|
+
- Add null check before calling getProfile()
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Output (engineering audience):**
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
Fixing in sprint 24.
|
|
185
|
+
Cause: null pointer at UserService.java:45, getProfile() is called before the user is loaded.
|
|
186
|
+
Fix: add a null check before the call.
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Same input, user switches to "draft a customer email" → audience shifts:**
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
Subject: Update on the account info loading issue
|
|
193
|
+
|
|
194
|
+
Hi,
|
|
195
|
+
|
|
196
|
+
We have identified the cause of the account info loading issue you reported. The team is working on it and the fix will go out in the next release.
|
|
197
|
+
|
|
198
|
+
I will follow up once the deploy is done.
|
|
199
|
+
|
|
200
|
+
Thanks,
|
|
201
|
+
[Name]
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Rules
|
|
207
|
+
|
|
208
|
+
1. **Preservation beats style.** Numbers, commitments, decisions are not paraphrased.
|
|
209
|
+
2. **No invention.** Vague input → short output, no filler.
|
|
210
|
+
3. **No softening certainty.** "Will" ≠ "hope". "Decided" ≠ "considering".
|
|
211
|
+
4. **Explicit user instructions win.** Emoji / formal / bullets on request → comply.
|
|
212
|
+
5. **Return the final output directly.** No preamble, no "here is the rephrased version".
|