omegon 0.8.0 → 0.8.2

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 CHANGED
@@ -42,7 +42,7 @@ omegon # start Omegon in any project directory
42
42
 
43
43
  ![Omegon Architecture](docs/img/architecture.png)
44
44
 
45
- Omegon extends `@styrene-lab/pi-coding-agent` with **27 extensions**, **12 skills**, and **4 prompt templates** — loaded automatically on session start.
45
+ Omegon extends `@styrene-lab/pi-coding-agent` with **31 extensions**, **12 skills**, and **4 prompt templates** — loaded automatically on session start.
46
46
 
47
47
  ### Development Methodology
48
48
 
@@ -87,8 +87,10 @@ Structured design exploration with persistent markdown documents — the upstrea
87
87
  - **Blocked audit**: `design_tree(action="blocked")` returns all stalled nodes with each blocking dependency's id, title, and status
88
88
  - **Priority**: `set_priority` (1 = critical → 5 = trivial) on any node; `ready` auto-sorts by it
89
89
  - **Issue types**: `set_issue_type` classifies nodes as `epic | feature | task | bug | chore` — bugs and chores are now first-class tracked work
90
- - **OpenSpec bridge**: `design_tree_update` with `action: "implement"` scaffolds `openspec/changes/<node-id>/` from a decided node's content; `/cleave` executes it
91
- - **Full pipeline**: design decide implement `/cleave` `/assess spec` archive
90
+ - **Auto-transition**: Adding research or decisions to a `seed` node automatically transitions it to `exploring` and scaffolds the design spec no manual ceremony
91
+ - **Substance-over-ceremony gates**: `set_status(decided)` checks for open questions and recorded decisions instead of artifact directory existence. Design specs are auto-extracted from doc content and archived
92
+ - **OpenSpec bridge**: `design_tree_update` with `action: "implement"` scaffolds `openspec/changes/<node-id>/` from a decided node's content, auto-checkouts the directive branch, forks a scoped memory mind, and sets design focus; `/cleave` executes it
93
+ - **Full pipeline**: design → decide → implement (auto-checkout + mind fork) → `/cleave` → `/assess spec` → archive (mind merge-back + cleanup)
92
94
 
93
95
  ### 🧠 Project Memory
94
96
 
@@ -98,8 +100,9 @@ Persistent, cross-session knowledge stored in SQLite. Accumulates architectural
98
100
  - **Semantic retrieval**: Embedding-based search via Ollama (`qwen3-embedding`), falls back to FTS5 keyword search
99
101
  - **Background extraction**: Auto-discovers facts from tool output without interrupting work
100
102
  - **Episodic memory**: Generates session narratives at shutdown for "what happened last time" context
103
+ - **Directive minds**: `implement` forks a scoped memory mind from `default`; all fact reads/writes auto-scope to the directive. `archive` ingests discoveries back to `default` and cleans up. Zero-copy fork with parent-chain inheritance — no fact duplication, parent embeddings and edges are reused
101
104
  - **Global knowledge base**: Cross-project facts at `~/.pi/memory/global.db`
102
- - **Git sync**: Exports to JSONL for version-controlled knowledge sharing across machines
105
+ - **Git sync**: Exports to JSONL for version-controlled knowledge sharing across machines; volatile runtime scoring metadata (confidence, reinforcement counts, decay scores) omitted from exports for stable diffs
103
106
 
104
107
  ![Memory Lifecycle](docs/img/memory-lifecycle.png)
105
108
 
@@ -112,6 +115,7 @@ Live status panel showing design tree, OpenSpec changes, cleave dispatch, and gi
112
115
  - **Raised mode**: Full-width expanded view (toggle with `/dash`)
113
116
  - Git branch tree rooted at repo name, annotated with linked design nodes
114
117
  - Two-column split at ≥120 terminal columns: design tree + cleave left, OpenSpec right
118
+ - Directive indicator: shows `▸ directive: name ✓` (branch match) or `▸ directive: name ⚠ main` (mismatch) when a directive mind is active
115
119
  - Context gauge · model · thinking level in shared footer zone
116
120
  - No line cap — renders as much content as needed
117
121
  - **Keyboard**: `Ctrl+Shift+B` toggles raised/compact
@@ -194,21 +194,22 @@ export const PATTERNS: Record<string, PatternDefinition> = {
194
194
  modifiersDefault: ["breaking_changes"],
195
195
  splitStrategy: ["New versioned endpoint", "Deprecation + dual-support", "Client migration"],
196
196
  },
197
- simple_refactor: {
198
- name: "Simple Refactor",
199
- description: "Code cleanup, renaming, or structural changes without functional modifications",
197
+ refactor: {
198
+ name: "Refactor",
199
+ description: "Code cleanup, renaming, restructuring, or replacing implementations while preserving behavior",
200
200
  keywords: [
201
201
  "refactor", "rename", "reorganize", "cleanup", "extract", "inline", "move",
202
- "restructure", "mechanical", "no functional",
202
+ "restructure", "mechanical", "no functional", "replace", "rewrite",
203
+ "swap", "substitute", "modernize",
203
204
  ],
204
- requiredAny: ["refactor", "rename", "cleanup", "extract", "reorganize"],
205
+ requiredAny: ["refactor", "rename", "cleanup", "extract", "reorganize", "replace", "rewrite", "swap", "substitute"],
205
206
  expectedComponents: {
206
- operation: ["rename", "extract", "inline", "move", "reorganize"],
207
- scope: ["function", "class", "file", "module", "component", "method"],
207
+ operation: ["rename", "extract", "inline", "move", "reorganize", "replace", "rewrite", "swap", "substitute"],
208
+ scope: ["function", "class", "file", "module", "component", "method", "implementation", "approach", "library", "framework", "pattern"],
208
209
  },
209
210
  systemsBase: 1,
210
211
  modifiersDefault: [],
211
- splitStrategy: ["By module/scope", "Update tests"],
212
+ splitStrategy: ["Implement replacement / perform refactor", "Update call sites + tests", "Remove old implementation"],
212
213
  },
213
214
  bug_fix: {
214
215
  name: "Bug Fix",
@@ -282,21 +283,27 @@ export const PATTERNS: Record<string, PatternDefinition> = {
282
283
  modifiersDefault: ["state_coordination"],
283
284
  splitStrategy: ["Core data model", "Rendering/UI layer", "Event handling + state management", "Application shell"],
284
285
  },
285
- refactor: {
286
- name: "Refactor",
287
- description: "Replace or rewrite implementation while preserving behavior",
286
+ infrastructure_tooling: {
287
+ name: "Infrastructure & Tooling",
288
+ description: "Extension development, CLI tooling, internal infrastructure, build systems, or agentic framework work",
288
289
  keywords: [
289
- "refactor", "replace", "rewrite", "improve", "clean", "restructure", "reorganize",
290
- "swap", "substitute", "modernize",
290
+ "extension", "plugin", "tool", "command", "cli", "config", "configuration",
291
+ "pipeline", "build", "deploy", "ci", "cd", "workflow", "script", "hook",
292
+ "provider", "routing", "dispatch", "handler", "registry", "loader",
293
+ "prompt", "agent", "inference",
294
+ "dashboard", "diagnostic", "telemetry", "logging",
295
+ "skill", "template", "scaffold", "generate", "emit",
291
296
  ],
292
- requiredAny: ["replace", "rewrite", "swap", "substitute", "refactor"],
297
+ requiredAny: ["extension", "plugin", "provider", "routing",
298
+ "dispatch", "registry", "agent", "skill"],
293
299
  expectedComponents: {
294
- operation: ["replace", "rewrite", "swap", "substitute"],
295
- target: ["implementation", "approach", "library", "framework", "pattern"],
300
+ core: ["extension", "plugin", "tool", "command", "handler", "provider", "registry"],
301
+ integration: ["config", "pipeline", "workflow", "routing", "dispatch", "loader"],
302
+ surface: ["cli", "dashboard", "status", "prompt", "template", "diagnostic"],
296
303
  },
297
- systemsBase: 1.0,
304
+ systemsBase: 1,
298
305
  modifiersDefault: [],
299
- splitStrategy: ["Implement replacement", "Update call sites", "Remove old implementation"],
306
+ splitStrategy: ["Core implementation", "Integration + wiring", "Tests + documentation"],
300
307
  },
301
308
  };
302
309
 
@@ -462,11 +469,18 @@ export function detectModifiers(directive: string): string[] {
462
469
  }
463
470
 
464
471
  /**
465
- * Calculate complexity: (1 + systems) × (1 + 0.5 × modifiers).
472
+ * Calculate complexity: systems × (1 + 0.5 × modifiers).
473
+ *
474
+ * Previous formula was (1 + systems) which gave a floor of 2.0 even for
475
+ * single-system, zero-modifier directives — making the heuristic path
476
+ * always exceed the default threshold of 2.0. Using bare `systems`
477
+ * allows trivial directives (1 system, 0 modifiers) to score 1.0,
478
+ * so they correctly get `needs_assessment` instead of `cleave`.
479
+ *
466
480
  * Capped at 100.0.
467
481
  */
468
482
  export function calculateComplexity(systems: number, modifiers: string[]): number {
469
- const raw = (1 + systems) * (1 + 0.5 * modifiers.length);
483
+ const raw = systems * (1 + 0.5 * modifiers.length);
470
484
  return Math.round(Math.min(raw, 100.0) * 10) / 10;
471
485
  }
472
486
 
@@ -536,7 +550,7 @@ export function assessDirective(
536
550
  reasoning:
537
551
  `Pattern '${match.name}' matched with ${(match.confidence * 100).toFixed(0)}% confidence. ` +
538
552
  `Systems: ${systemsForDisplay}, Modifiers: ${allModifiers.length}. ` +
539
- `Formula: (1 + ${systemsForCalc}) × (1 + 0.5 × ${allModifiers.length}) = ${complexity}. ` +
553
+ `Formula: ${systemsForCalc} × (1 + 0.5 × ${allModifiers.length}) = ${complexity}. ` +
540
554
  `Effective (validate=${validate}): ${effComplexity}`,
541
555
  skipInterrogation: false,
542
556
  };
@@ -545,7 +559,7 @@ export function assessDirective(
545
559
  if (
546
560
  match.confidence >= 0.90 &&
547
561
  effComplexity <= threshold &&
548
- match.name === "Simple Refactor"
562
+ match.name === "Refactor"
549
563
  ) {
550
564
  result.skipInterrogation = true;
551
565
  }
@@ -1586,7 +1586,7 @@ export default function cleaveExtension(pi: ExtensionAPI) {
1586
1586
  "Every non-trivial code change must include tests in co-located *.test.ts files. Untested code is incomplete — do not commit without tests for new functions and changed behavior.",
1587
1587
  "Call cleave_assess before starting any multi-system or cross-cutting task to determine if decomposition is needed",
1588
1588
  "If decision is 'execute', proceed directly. If 'cleave', use /cleave to decompose. If 'needs_assessment', proceed directly — it means no pattern matched but the task is likely simple enough for in-session execution.",
1589
- "Complexity formula: (1 + systems) × (1 + 0.5 × modifiers). Threshold default: 2.0.",
1589
+ "Complexity formula: systems × (1 + 0.5 × modifiers). Threshold default: 2.0.",
1590
1590
  "The /assess command provides code assessment: `/assess cleave` (adversarial review + auto-fix), `/assess diff [ref]` (review only), `/assess spec [change]` (validate against OpenSpec scenarios), `/assess design [node-id]` (evaluate design-tree node readiness before set_status(decided)).",
1591
1591
  "When the repo has openspec/ with active changes, suggest `/assess spec` after implementation and before `/opsx:archive`.",
1592
1592
  "Run `/assess design <node-id>` before calling design_tree_update with set_status(decided) to verify acceptance criteria are satisfied.",
@@ -427,9 +427,13 @@ export function computeAssessmentSnapshot(repoPath: string, changeName: string):
427
427
  const gitHead = safeReadGit(repoPath, ["rev-parse", "HEAD"]);
428
428
  const dirty = detectGitDirty(repoPath, snapshotPaths);
429
429
 
430
+ // Fingerprint represents implementation file content — NOT git HEAD.
431
+ // Including gitHead would create a chicken-and-egg: committing the
432
+ // assessment.json (which lives in-repo) changes HEAD, which invalidates
433
+ // the fingerprint, making the assessment permanently stale.
434
+ // Git HEAD is stored separately in the snapshot for informational use.
430
435
  const fingerprintSeed = JSON.stringify({
431
436
  changeName,
432
- gitHead,
433
437
  dirty,
434
438
  files,
435
439
  });
@@ -1,6 +1,9 @@
1
1
  import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
2
2
 
3
3
  const verbs = [
4
+ // ═══════════════════════════════════════════════════
5
+ // Adeptus Mechanicus — Rites of the Omnissiah
6
+ // ═══════════════════════════════════════════════════
4
7
  "Communing with the Machine Spirit",
5
8
  "Appeasing the Omnissiah",
6
9
  "Reciting the Litany of Ignition",
@@ -19,54 +22,17 @@ const verbs = [
19
22
  "Burning sacred incense over the server",
20
23
  "Whispering the Cant of Maintenance",
21
24
  "Genuflecting before the datacron",
22
- "Consulting the Oracle at Delphi",
23
- "Reading the auguries",
24
- "Descending into the labyrinth",
25
- "Weaving on Athena's loom",
26
- "Deciphering the Rosetta Stone",
27
- "Consulting the Norns",
28
- "Reading the runes",
29
- "Forging on Hephaestus's anvil",
30
- "Navigating the River Styx",
31
- "Unraveling Ariadne's thread",
32
- "Stealing fire from Olympus",
33
- "Divining from the entrails",
34
- "Reciting the Litany of Hate",
35
- "Appeasing the Machine Spirit",
36
- "Performing the Rite of Percussive Maintenance",
37
- "Purging the heretical code",
38
- "Suffering not the unclean merge to live",
39
- "Deploying the Exterminatus on tech debt",
40
- "Consulting the Codex Astartes",
41
- "Exorcising the daemon process",
42
- "Anointing the deployment manifest",
43
- "Sanctifying the build pipeline",
44
25
  "Cataloguing the STC fragments",
45
26
  "Venerating the sacred repository",
46
27
  "Decrypting the Archaeotech",
47
28
  "Supplicating before the Altar of Technology",
48
29
  "Conducting the Binary Psalm",
49
- "Fortifying the firewall bastions",
50
30
  "Interrogating the data-looms",
51
31
  "Purifying the corrupted sectors",
52
32
  "Awakening the dormant forge",
53
33
  "Petitioning the Fabricator-General",
54
- "Scourging the technical debt",
55
- "Flagellating the failing tests",
56
- "Martyring the deprecated functions",
57
- "Crusading through the backlog",
58
- "Performing battlefield triage on the codebase",
59
- "Debugging with extreme prejudice",
60
- "Servicing the servitors",
61
- "Transcribing the sacred schematics",
62
- "Committing the Holy Diff",
63
- "Invoking the Emperor's Protection",
64
- "Loading the bolter rounds",
65
- "Administering the Sacred Oils",
66
34
  "Propitiating the wrathful forge-spirit",
67
- "Affixing the Purity Seal to the commit",
68
35
  "Performing the Thirteen Rituals of Compilation",
69
- "Routing the xenos from the dependency tree",
70
36
  "Reconsecrating the tainted module",
71
37
  "Imploring the Titan's logic core",
72
38
  "Soothing the belligerent plasma coil",
@@ -74,6 +40,170 @@ const verbs = [
74
40
  "Grafting the sacred augmetic",
75
41
  "Offering a binary prayer to the void",
76
42
  "Inscribing the litany upon the circuit board",
43
+ "Consulting the Electro-Priests",
44
+ "Rotating the sacred engrams",
45
+ "Downloading wisdom from the data-vaults of Triplex Phall",
46
+ "Genuflecting before the Censer of Compilation",
47
+ "Parsing the Machine Cant in trinary",
48
+ "Applying the Unguent of Optimal Throughput",
49
+ "Reciting the Canticle of the Blessed Diff",
50
+ "Interfacing with the ancient dataslab",
51
+
52
+ // ═══════════════════════════════════════════════════
53
+ // Imperium of Man — Warfare & Devotion
54
+ // ═══════════════════════════════════════════════════
55
+ "Reciting the Litany of Hate",
56
+ "Performing the Rite of Percussive Maintenance",
57
+ "Purging the heretical code",
58
+ "Suffering not the unclean merge to live",
59
+ "Deploying the Exterminatus on tech debt",
60
+ "Consulting the Codex Astartes",
61
+ "Exorcising the daemon process",
62
+ "Anointing the deployment manifest",
63
+ "Sanctifying the build pipeline",
64
+ "Fortifying the firewall bastions",
65
+ "Loading the bolter rounds",
66
+ "Administering the Sacred Oils",
67
+ "Affixing the Purity Seal to the commit",
68
+ "Routing the xenos from the dependency tree",
69
+ "Invoking the Emperor's Protection",
70
+ "Committing the Holy Diff",
71
+ "Scourging the technical debt",
72
+ "Flagellating the failing tests",
73
+ "Martyring the deprecated functions",
74
+ "Crusading through the backlog",
75
+ "Performing battlefield triage on the codebase",
76
+ "Debugging with extreme prejudice",
77
+ "Servicing the servitors",
78
+ "Transcribing the sacred schematics",
79
+ "Dispatching the Officio Assassinorum against the regression",
80
+ "Filing the grievance with the Administratum",
81
+ "Awaiting parchmentwork from the Adeptus Terra",
82
+ "Consulting the Tarot of the Emperor",
83
+ "Fortifying this position (the Codex Astartes supports this action)",
84
+ "Mounting a Drop Pod assault on the issue tracker",
85
+ "Declaring Exterminatus on the node_modules",
86
+ "Summoning the Grey Knights to purge the warp-tainted test suite",
87
+
88
+ // ═══════════════════════════════════════════════════
89
+ // Classical Antiquity — Greek & Roman
90
+ // ═══════════════════════════════════════════════════
91
+ "Consulting the Oracle at Delphi",
92
+ "Reading the auguries",
93
+ "Descending into the labyrinth",
94
+ "Weaving on Athena's loom",
95
+ "Deciphering the Rosetta Stone",
96
+ "Unraveling Ariadne's thread",
97
+ "Stealing fire from Olympus",
98
+ "Divining from the entrails",
99
+ "Navigating the River Styx",
100
+ "Forging on Hephaestus's anvil",
101
+ "Bargaining with the Sphinx",
102
+ "Pouring libations to Hermes, patron of automation",
103
+ "Petitioning Athena for architectural wisdom",
104
+ "Cleaning the Augean stables of legacy code",
105
+ "Consulting Tiresias about the deprecation warnings",
106
+ "Binding the code with Odysseus's cunning",
107
+ "Awaiting judgment from the Areopagus",
108
+ "Constructing the Antikythera mechanism",
109
+ "Charting a course between Scylla and Charybdis",
110
+
111
+ // ═══════════════════════════════════════════════════
112
+ // Norse — Sagas & Runes
113
+ // ═══════════════════════════════════════════════════
114
+ "Consulting the Norns",
115
+ "Reading the runes",
116
+ "Asking Mímir's head for guidance",
117
+ "Hanging from Yggdrasil for wisdom",
118
+ "Forging in the heart of Niðavellir",
119
+ "Sailing the Bifrost to the deployment realm",
120
+ "Summoning the Einherjar for code review",
121
+ "Sharpening Gram upon the whetstone of tests",
122
+ "Consulting the Völva about the sprint forecast",
123
+ "Feeding Huginn and Muninn the latest telemetry",
124
+ "Braving the Fimbulwinter of dependency hell",
125
+
126
+ // ═══════════════════════════════════════════════════
127
+ // Arthurian & Medieval
128
+ // ═══════════════════════════════════════════════════
129
+ "Questing for the Holy Grail of zero bugs",
130
+ "Pulling the sword from the CI/CD stone",
131
+ "Convening the Round Table for design review",
132
+ "Consulting Merlin's grimoire",
133
+ "Defending the castle walls against merge conflicts",
134
+ "Dispatching knights-errant into the codebase",
135
+ "Illuminating the manuscript of requirements",
136
+
137
+ // ═══════════════════════════════════════════════════
138
+ // Lovecraftian — Cosmic Horror
139
+ // ═══════════════════════════════════════════════════
140
+ "Gazing into the non-Euclidean geometry of the type system",
141
+ "Consulting the Necronomicon of legacy documentation",
142
+ "Invoking That Which Should Not Be Refactored",
143
+ "Descending into the R'lyeh of nested callbacks",
144
+ "Bargaining with Nyarlathotep for more compute",
145
+ "Performing rites that would drive lesser compilers mad",
146
+ "Glimpsing truths that the garbage collector dare not reclaim",
147
+
148
+ // ═══════════════════════════════════════════════════
149
+ // Dune — Arrakis & the Imperium
150
+ // ═══════════════════════════════════════════════════
151
+ "Walking without rhythm to avoid the sandworm",
152
+ "Consulting the Mentat about computational complexity",
153
+ "Folding space through the Holtzman drive",
154
+ "Navigating the Golden Path of the refactor",
155
+ "Deploying the hunter-seeker against the flaky test",
156
+ "Consuming the spice of stack traces",
157
+ "Reciting the Litany Against Fear (of production deploys)",
158
+ "Awaiting the Kwisatz Haderach of frameworks",
159
+ "Surviving the Gom Jabbar of code review",
160
+
161
+ // ═══════════════════════════════════════════════════
162
+ // Tolkien — Middle-earth
163
+ // ═══════════════════════════════════════════════════
164
+ "Consulting the palantír",
165
+ "Speaking 'friend' and entering the API",
166
+ "Casting the One Ring into the fires of refactoring",
167
+ "Seeking the counsel of Elrond",
168
+ "Delving too greedily and too deep into the codebase",
169
+ "Riding the Eagles to production",
170
+ "Reading the inscription by the light of Ithildin",
171
+ "Following the Fellowship through the mines of Moria",
172
+
173
+ // ═══════════════════════════════════════════════════
174
+ // Eastern — Sun Tzu, Miyamoto Musashi, Zen
175
+ // ═══════════════════════════════════════════════════
176
+ "Contemplating the sound of one hand coding",
177
+ "Applying the thirty-six stratagems to the architecture",
178
+ "Achieving mushin no shin — mind without mind",
179
+ "Striking with the void, per the Book of Five Rings",
180
+ "Knowing the enemy (the bug) and knowing thyself (the fix)",
181
+ "Sitting with the kōan of the failing assertion",
182
+ "Raking the sand garden of the test suite",
183
+
184
+ // ═══════════════════════════════════════════════════
185
+ // Alchemy & Occult
186
+ // ═══════════════════════════════════════════════════
187
+ "Transmuting the base code into gold",
188
+ "Distilling the quintessence from the logs",
189
+ "Consulting the Emerald Tablet of Hermes Trismegistus",
190
+ "Performing the Great Work upon the monolith",
191
+ "Seeking the Philosopher's Stone of zero downtime deploys",
192
+ "Drawing the sigil of binding upon the interface contract",
193
+ "Invoking the egregore of the open source community",
194
+
195
+ // ═══════════════════════════════════════════════════
196
+ // Sci-Fi Miscellany
197
+ // ═══════════════════════════════════════════════════
198
+ "Reversing the polarity of the neutron flow",
199
+ "Aligning the deflector dish to emit a solution beam",
200
+ "Rerouting auxiliary power to the build server",
201
+ "Engaging the probability drive",
202
+ "Computing the Answer (it's always 42)",
203
+ "Checking if the cake is a lie",
204
+ "Bypassing the Kobayashi Maru",
205
+ "Opening the pod bay doors",
206
+ "Reticulating splines",
77
207
  ];
78
208
 
79
209
  function randomVerb(): string {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omegon",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Omegon — an opinionated distribution of pi (by Mario Zechner) with extensions for lifecycle management, memory, orchestration, and visualization",
5
5
  "bin": {
6
6
  "omegon": "bin/omegon.mjs",
@@ -58,7 +58,6 @@
58
58
  "./extensions/cleave",
59
59
  "./extensions/openspec",
60
60
  "./extensions/defaults.ts",
61
- "./extensions/distill.ts",
62
61
  "./extensions/render",
63
62
  "./extensions/local-inference",
64
63
  "./extensions/mcp-bridge",
@@ -77,8 +76,7 @@
77
76
  "./extensions/tool-profile",
78
77
  "./extensions/vault",
79
78
  "./extensions/version-check.ts",
80
- "./extensions/web-ui",
81
- "./extensions/clipboard-diag/index.ts"
79
+ "./extensions/web-ui"
82
80
  ],
83
81
  "skills": [
84
82
  "./skills"
@@ -91,15 +91,21 @@ This status is injected into the agent context (not just displayed).
91
91
  ## Complexity Formula
92
92
 
93
93
  ```
94
- complexity = (1 + systems) × (1 + 0.5 × modifiers)
94
+ complexity = systems × (1 + 0.5 × modifiers)
95
95
  effective = complexity + 1 (when validation enabled)
96
96
  ```
97
97
 
98
- ## Patterns (9)
98
+ The formula uses bare `systems` (not `1 + systems`) so that single-system,
99
+ zero-modifier directives score 1.0 (effective 2.0) — at the default threshold
100
+ of 2.0, they get `needs_assessment` rather than being falsely recommended
101
+ for decomposition.
102
+
103
+ ## Patterns (12)
99
104
 
100
105
  Full-Stack CRUD, Authentication System, External Service Integration,
101
106
  Database Migration, Performance Optimization, Breaking API Change,
102
- Simple Refactor, Bug Fix, Refactor.
107
+ Refactor, Bug Fix, Greenfield Project, Multi-Module Library,
108
+ Application Bootstrap, Infrastructure & Tooling.
103
109
 
104
110
  ## Adversarial Review Loop
105
111
 
@@ -1,64 +0,0 @@
1
- /**
2
- * clipboard-diag — Diagnostic command for clipboard image paste.
3
- *
4
- * Registers /cliptest to diagnose why Ctrl+V image paste may fail.
5
- */
6
- import type { ExtensionAPI } from "../../vendor/pi-mono/packages/coding-agent/src/core/extensions/types.js";
7
-
8
- export default function clipboardDiag(pi: ExtensionAPI) {
9
- pi.registerCommand("cliptest", {
10
- description: "Test clipboard image access (diagnostic)",
11
- async handler() {
12
- const lines: string[] = ["**Clipboard Image Diagnostic**", ""];
13
-
14
- // 1. Check native module
15
- let clipModule: string | null = null;
16
- let clipboard: { hasImage: () => boolean; getImageBinary: () => Promise<unknown> } | null = null;
17
- const candidates = ["@cwilson613/clipboard", "@mariozechner/clipboard"];
18
- for (const name of candidates) {
19
- try {
20
- // eslint-disable-next-line @typescript-eslint/no-require-imports
21
- const mod = require(name);
22
- clipboard = mod;
23
- clipModule = name;
24
- break;
25
- } catch {
26
- // next
27
- }
28
- }
29
-
30
- if (!clipboard) {
31
- lines.push("❌ No clipboard native module found");
32
- lines.push(` Tried: ${candidates.join(", ")}`);
33
- } else {
34
- lines.push(`✓ Module: ${clipModule}`);
35
-
36
- // 2. Check hasImage
37
- try {
38
- const has = clipboard.hasImage();
39
- lines.push(`${has ? "✓" : "❌"} hasImage(): ${has}`);
40
-
41
- // 3. Try reading
42
- if (has) {
43
- try {
44
- const data = await clipboard.getImageBinary();
45
- const len = Array.isArray(data) ? data.length : (data as Uint8Array)?.length ?? 0;
46
- lines.push(`${len > 0 ? "✓" : "❌"} getImageBinary(): ${len} bytes`);
47
- } catch (e) {
48
- lines.push(`❌ getImageBinary() threw: ${e instanceof Error ? e.message : String(e)}`);
49
- }
50
- }
51
- } catch (e) {
52
- lines.push(`❌ hasImage() threw: ${e instanceof Error ? e.message : String(e)}`);
53
- }
54
- }
55
-
56
- // 4. Platform info
57
- lines.push("");
58
- lines.push(`Platform: ${process.platform}, TERM: ${process.env.TERM ?? "unset"}`);
59
- lines.push(`DISPLAY: ${process.env.DISPLAY ?? "unset"}, WAYLAND: ${process.env.WAYLAND_DISPLAY ?? "unset"}`);
60
-
61
- pi.sendMessage({ customType: "view", content: lines.join("\n"), display: true });
62
- },
63
- });
64
- }
@@ -1,127 +0,0 @@
1
- /**
2
- * distill — Context distillation for session handoff
3
- *
4
- * Registers `/distill` command that analyzes the current conversation context
5
- * and produces a portable distillation summary for bootstrapping a fresh session.
6
- *
7
- * The extension handles the mechanical parts (directory creation, file writing,
8
- * git status collection) and delegates the summarization to the LLM via
9
- * sendUserMessage.
10
- */
11
-
12
- import { existsSync, mkdirSync } from "node:fs";
13
- import { join, basename } from "node:path";
14
- import type { ExtensionAPI } from "@styrene-lab/pi-coding-agent";
15
-
16
- export default function distillExtension(pi: ExtensionAPI) {
17
-
18
- pi.registerCommand("distill", {
19
- description: "Create a portable session distillation for fresh context bootstrap",
20
- handler: async (_args, ctx) => {
21
- // Gather mechanical context the LLM will need
22
- const cwd = ctx.cwd;
23
- const repoName = basename(cwd);
24
-
25
- // Git status
26
- let branch = "unknown";
27
- let recentCommits = "";
28
- let uncommitted = "";
29
- try {
30
- const branchResult = await pi.exec("git", ["branch", "--show-current"], { timeout: 5_000, cwd });
31
- branch = branchResult.stdout.trim() || "HEAD detached";
32
- } catch { /* ignore */ }
33
- try {
34
- const logResult = await pi.exec(
35
- "git", ["log", "--oneline", "-10", "--no-decorate"],
36
- { timeout: 5_000, cwd },
37
- );
38
- recentCommits = logResult.stdout.trim();
39
- } catch { /* ignore */ }
40
- try {
41
- const statusResult = await pi.exec("git", ["status", "--porcelain"], { timeout: 5_000, cwd });
42
- uncommitted = statusResult.stdout.trim() || "(clean)";
43
- } catch { /* ignore */ }
44
-
45
- // Ensure distillation directory exists
46
- const distillDir = join(cwd, ".pi", "distillations");
47
- mkdirSync(distillDir, { recursive: true });
48
-
49
- // Generate a timestamp-based filename
50
- const now = new Date();
51
- const ts = now.toISOString().replace(/[:.]/g, "-").slice(0, 19);
52
-
53
- // Build the prompt for the LLM to do the actual summarization
54
- const prompt = [
55
- "Analyze the full conversation context and create a session distillation.",
56
- "",
57
- "**Repository context (already gathered):**",
58
- `- Working directory: ${cwd}`,
59
- `- Repository: ${repoName}`,
60
- `- Branch: ${branch}`,
61
- `- Recent commits:`,
62
- "```",
63
- recentCommits || "(no commits)",
64
- "```",
65
- `- Uncommitted changes:`,
66
- "```",
67
- uncommitted,
68
- "```",
69
- "",
70
- "**Instructions:**",
71
- "",
72
- `Write a distillation file to \`${distillDir}/${ts}-<slug>.md\` where <slug> is a 2-3 word kebab-case description of the session topic.`,
73
- "",
74
- "Use this structure:",
75
- "",
76
- "```markdown",
77
- "# Session Distillation: <brief-title>",
78
- "",
79
- "Generated: <timestamp>",
80
- `Working Directory: ${cwd}`,
81
- `Repository: ${repoName}`,
82
- "",
83
- "## Session Overview",
84
- "<2-3 sentence summary of what was accomplished>",
85
- "",
86
- "## Technical State",
87
- "### Repository Status",
88
- `- Branch: ${branch}`,
89
- "- Recent commits: <summarize>",
90
- "- Uncommitted changes: <summarize>",
91
- "",
92
- "### Key Changes This Session",
93
- "<bulleted list of significant modifications>",
94
- "",
95
- "## Decisions Made",
96
- "<numbered list with brief rationale>",
97
- "",
98
- "## Pending Items",
99
- "### Incomplete Work",
100
- "### Known Issues",
101
- "### Planned Next Steps",
102
- "",
103
- "## Critical Context",
104
- "<information that would be difficult to reconstruct>",
105
- "",
106
- "## File Reference",
107
- "Key files for continuation:",
108
- "- <path>: <purpose>",
109
- "```",
110
- "",
111
- "After writing the file, output a handoff block like:",
112
- "",
113
- "```",
114
- "Distillation saved to: <path>",
115
- "",
116
- "To continue in a fresh session, copy this prompt:",
117
- "---",
118
- "Continue from distillation: <path>",
119
- "Read the distillation file and confirm you understand the context before proceeding.",
120
- "---",
121
- "```",
122
- ].join("\n");
123
-
124
- pi.sendUserMessage(prompt, { deliverAs: "followUp" });
125
- },
126
- });
127
- }