Repository navigation
feat(code): adopt ponytail's ponytail: marker convention as // sin-debt: <ceiling>, upgrade: <trigger> #177
Description
Summary
Übernimm ponytail's wichtigste Innovation: die ponytail:-Marker-Konvention (DietrichGebert/ponytail v4.7.0, 20.7k stars, https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md:50-53) als sin-debt:-Konvention für SIN-Code. Jeder Shortcut im Code wird mit // sin-debt: <ceiling>, upgrade: <trigger> markiert. Die Marker sind first-class Information und werden von einem neuen cmd/sin-code/debt_cmd.go (analog zu ponytail-debt) gescannt, geledgert, auditiert.
Format:
// sin-debt: <ceiling>, upgrade: <trigger>
// sin-debt: this existsBeispiele:
// sin-debt: global mutex, upgrade: per-account locks when throughput > 1k req/s
// sin-debt: O(n²) scan, upgrade: switch to map lookup when n > 100
// sin-debt: hand-rolled retry, upgrade: use cenkalti/backoff when context cancellation mattersMotivation
ponytail's ponytail:-Marker-Konvention ist die Innovation des Projekts. Sie löst ein Problem, das jeder kennt, aber niemand systematisch löst: technische Schulden sichtbar und nachverfolgbar machen.
Aus https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md:50-53:
Mark intentional simplifications with a
ponytail:comment — a shortcut with a known ceiling names the ceiling and the upgrade path in the comment.
Aus https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail-debt/SKILL.md:1-40:
Every deliberate ponytail shortcut is marked with a
ponytail:comment naming its ceiling and upgrade path. This collects them into one ledger so a deferral can't quietly become permanent.
SIN-Code hat aktuell:
cmd/sin-code/internal/lessons/(Closed Learning Loop) – für Tool-Error-Patternscmd/sin-code/internal/ledger/(Session Ledger) – für Session-Events- Keinen Code-Level-Debt-Tracker
Das // sin-debt:-Format schließt diese Lücke. Die Schulden sind im Code selbst sichtbar und über sin-code debt abfragbar.
Current State in SIN-Code
| Bereich | Datei | Zeilen | Was da ist |
|---|---|---|---|
| Lessons | cmd/sin-code/internal/lessons/store.go |
– | SQLite-Store für gelernte Patterns. Kein Code-Scan. |
| Ledger | cmd/sin-code/internal/ledger/store.go |
87-100 | SQLite-Store für Session-Events. Kein Code-Scan. |
| Codebase-Konventionen | AGENTS.md:359+ |
– | ### Bundled skill naming rules, aber keine Debt-Marker-Konvention. |
| Bestehende Shortcuts | cmd/sin-code/internal/orchestrator/dispatcher.go |
– | // ponytail: this exists (zufällig vorhanden) – wir adoptieren diese Konvention. |
| Coverage-Tests | cmd/sin-code/internal/.../stcov_test.go |
4591 | Hinter //go:build coverage (von uns gegated). Keine ponytail:-Marker. |
Was fehlt: Ein systematischer Mechanismus, um bewusste technische Schulden zu markieren, zu zählen, und in den Code-Review-Loop zu integrieren.
Was ponytail genau macht
Aus https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail-debt/SKILL.md:1-40:
Scan: Grep the repo for comment markers, skipping
node_modules,.git, and build output:
grep -rnE '(#|//) ?ponytail:' .(add other comment prefixes if your stack uses them)Output: One row per marker, grouped by file:
<file>:<line> — <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit.The convention is
ponytail: <ceiling>, <upgrade path>, so pull the ceiling and the trigger straight from the comment.Flag the rot risk: any
ponytail:comment that names no upgrade path or trigger gets ano-triggertag, those are the ones that silently rot.End with
<N> markers, <M> with no trigger.
Die ponytail-debt-Skill ist read-only – er scannt, harvested, und reportet. Kein Schreiben. Optional: ask and it writes the ledger to a file (e.g. PONYTAIL-DEBT.md).
Detailed Implementation Plan
Phase 1 — Scanner & Format-Spec
-
Erstelle
docs/sin-debt-convention.mdmit:- Format:
// sin-debt: <ceiling>, upgrade: <trigger> - Erlaubte Kommentar-Syntaxe:
//,#,/*,--,<!--(HTML in Markdown) - Pflichtfelder:
ceiling(Was ist limitiert),upgrade(Wann nachrüsten) - Beispiele (mindestens 5 reale aus dem Code)
- Format:
-
Erstelle
cmd/sin-code/internal/sindept/scanner.go(Go-Single-Pass-Scanner):type Marker struct { Path string Line int Comment string // roh, z.B. "// sin-debt: ..." Ceiling string Upgrade string // leer = no-trigger HasUpgrade bool } func Scan(root string, opts ScanOptions) ([]Marker, error)
ScanOptions.Skip=[]string{"node_modules", ".git", "dist", "vendor", ".venv", "build"}- Regex:
(?m)(?:#|//|/\*|--|<!--) ?sin-debt:\s*(?P<ceiling>[^,]+?)(?:,\s*upgrade:\s*(?P<upgrade>.+?))?$
-
Validierung:
cmd/sin-code/internal/sindept/scanner_test.go:- 5 reale Beispiele parsen korrekt
no-trigger-Erkennung- Multi-Line-Kommentare werden ignoriert
- Markdown-Comments (
<!--) werden erkannt
Phase 2 — Ledger & Persistence
-
Erstelle
cmd/sin-code/internal/sindept/ledger.go(Integration mit bestehendem Ledger):- Neue
EntryType:TypeDebtMarker = "debt_marker" - Felder:
{path, line, ceiling, upgrade, has_upgrade} - Persistiert pro Session:
sin-code debt listzeigt aktuelle + historische Marker
- Neue
-
Aggregation pro Repo:
cmd/sin-code/internal/sindept/aggregate.go:AggregateStatsmittotal,no_trigger_count,by_tag,by_pathby_tagmappt aufdelete | stdlib | native | yagni | shrink(von ponytail-review)by_pathmappt aufcmd/sin-code/internal/<pkg>/*.go
Phase 3 — CLI
-
Erstelle
cmd/sin-code/debt_cmd.gomit:sin-code debt list [--path <path>] [--no-trigger]– listet alle Markersin-code debt audit– zeigtno-triggerMarker, ranked by agesin-code debt stats– Total/Trigger-Verteilung/By-Tag/By-Pathsin-code debt export <file.md>– exportiert alsSIN-DEBT.md(analog zuPONYTAIL-DEBT.md)sin-code debt fix <path:line>– öffnet Editor an der Stelle, um den Trigger zu ergänzen
-
Integration mit
sin-code review --complexity(siehe Issue feat(skill): add skill-code-lazy bundled skill (SIN-Code variant of ponytail, respects M3 verify-first) #178):- Wenn ein Review-Finding einen
delete:-Tag hat und der Code einensin-debt:-Marker hat → als "approved shortcut" markieren, nicht als zu löschendes Issue. - Wenn ein Review-Finding keinen Marker hat → als "neues Issue" markieren.
- Wenn ein Review-Finding einen
Phase 4 — Auto-Marker (optional, Phase 2)
-
Automatische Marker-Erkennung im Learning-Subsystem:
- Wenn der Critic (
internal/orchestrator/critic.go:1-101) feststellt, dassv.Diagnosis()auf einen bewussten Shortcut hinweist, schlägt das System vor: "Add// sin-debt: <x>, upgrade: <y>here? [y/n]" - Bei
ywird der Marker incmd/sin-code/internal/instinct/extract.goextrahiert und in die Lessons-DB geschrieben
- Wenn der Critic (
-
CI-Integration (Phase 5):
scripts/ci-precheck.shruftsin-code debt auditauf- CI fail, wenn
no_trigger_count > N(Schwelle konfigurierbar viadebt.max_no_trigger)
Phase 5 — Tests
-
Unit-Tests (Coverage-Ziel ≥ 80%):
scanner_test.go: 5 reale Beispieleledger_test.go: Round-trip, Aggregationdebt_cmd_test.go: alle 5 Subcommands
-
Integration-Tests:
- Erstelle ein Test-Repo mit 10 bekannten Markern (5 mit Trigger, 5 ohne)
sin-code debt auditlistet exakt die 5 ohne Triggersin-code debt exporterzeugt eine korrekte Markdown-Tabelle
-
Race-Test:
go test -race -count=1 ./cmd/sin-code/internal/sindept/...
Phase 6 — Docs
- Erstelle
docs/sin-debt.md: Format-Spec, Beispiele, Best Practices. - Update
AGENTS.md§10 (Naming and stability rules): fügesin-debt:-Konvention hinzu. - Update
BACKLOG.md: markiere als done. - Update
CHANGELOG.mdUnreleased-Section.
Acceptance Criteria
-
cmd/sin-code/internal/sindept/Paket existiert mit Scanner, Ledger, Aggregator -
cmd/sin-code/debt_cmd.goexistiert mit 5 Subcommands (list, audit, stats, export, fix) -
// sin-debt: <ceiling>, upgrade: <trigger>Format wird in mind. 95 % der Fälle korrekt geparst -
no-triggerErkennung funktioniert - Marker werden im
internal/ledger/mitTypeDebtMarkerpersistiert -
sin-code debt exporterzeugt eine Markdown-Datei -
docs/sin-debt-convention.mdexistiert - Mindestens 5 reale Beispiele in
cmd/sin-code/internal/mit// sin-debt:-Marker ergänzt (vom PR-Author) - Alle Tests passen mit
-race -
golangci-lint,govulncheck,gosec(SARIF) grün -
BACKLOG.mdundCHANGELOG.mdaktualisiert
Risk and Rollback
- Risk: Scanner zu aggressiv – erkennt
ponytail:alssin-debt:(false positive). Mitigation: präziser Regex mit explizitemsin-debt:Token. - Risk: Marker ohne Trigger – das System sammelt sie, aber niemand fixt sie. Mitigation: CI-Threshold + Slack-Notification (geplant für separater Issue).
- Risk: Marker-Drift – der Code ändert sich, aber der Marker bleibt. Mitigation: periodischer Re-Scan mit
sin-code debt audit(cron-ähnlich). - Rollback: Revert PR. Die Marker im Code bleiben inert (Comments).
References
- ponytail SKILL.md: https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail/SKILL.md:50-53
- ponytail-debt SKILL.md: https://github.com/DietrichGebert/ponytail/blob/main/skills/ponytail-debt/SKILL.md:1-40
- SIN-Code Lessons: cmd/sin-code/internal/lessons/
- SIN-Code Ledger: cmd/sin-code/internal/ledger/store.go:87-100
- SIN-Code AGENTS.md §10: AGENTS.md:359+
- SIN-Code orchestrator: cmd/sin-code/internal/orchestrator/
- SIN-Code issue feat(agent): add verbosity/compression mode (terse/ultra) with system-prompt injection #167 (Verbosity): feat(agent): add verbosity/compression mode (terse/ultra) with system-prompt injection #167
- SIN-Code issue feat(memory): add sin-code compress (deterministic + LLM) for instincts, summaries, lessons, AGENTS.md #172 (Memory-Compression): feat(memory): add sin-code compress (deterministic + LLM) for instincts, summaries, lessons, AGENTS.md #172
Activity
Delqhi commentedon Jun 16, 2026
Closed: implementation in PR #207 (feat(debt): adopt // sin-debt: , upgrade: marker convention). When PR #207 merges, the feature is live.
merge: resolve main conflicts in PR #207 (issue #177)
feat(debt): adopt // sin-debt: <ceiling>, upgrade: <trigger> marker c…
feat(debt): adopt // sin-debt: <ceiling>, upgrade: <trigger> marker c…