ultimate-pi 0.13.0 → 0.14.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.
Files changed (39) hide show
  1. package/{.pi → .agents}/skills/ccc/SKILL.md +1 -7
  2. package/.agents/skills/ccc/references/settings.md +126 -0
  3. package/.agents/skills/harness-debate-plan/SKILL.md +61 -21
  4. package/.agents/skills/harness-orchestration/SKILL.md +1 -1
  5. package/.pi/agents/harness/planning/plan-adversary.md +2 -2
  6. package/.pi/agents/harness/planning/plan-evaluator.md +3 -1
  7. package/.pi/agents/harness/planning/review-integrator.md +4 -2
  8. package/.pi/extensions/debate-orchestrator.ts +39 -435
  9. package/.pi/extensions/harness-debate-tools.ts +519 -0
  10. package/.pi/extensions/harness-plan-approval.ts +41 -17
  11. package/.pi/extensions/harness-run-context.ts +18 -0
  12. package/.pi/extensions/lib/debate-bus-core.ts +434 -0
  13. package/.pi/extensions/lib/debate-bus-state.ts +58 -0
  14. package/.pi/extensions/lib/harness-spawn-budget.ts +5 -25
  15. package/.pi/extensions/lib/plan-approval/dialog.ts +33 -272
  16. package/.pi/extensions/lib/plan-approval/format-plan.ts +12 -85
  17. package/.pi/extensions/lib/plan-approval/plan-review.ts +6 -6
  18. package/.pi/extensions/lib/plan-approval/render.ts +6 -0
  19. package/.pi/extensions/lib/plan-approval/validate.ts +1 -1
  20. package/.pi/extensions/lib/plan-debate-envelope.ts +2 -0
  21. package/.pi/extensions/lib/plan-debate-gate.ts +155 -0
  22. package/.pi/extensions/lib/plan-debate-id.ts +39 -0
  23. package/.pi/extensions/lib/plan-debate-lane.ts +220 -0
  24. package/.pi/extensions/lib/plan-debate-round-status.ts +94 -0
  25. package/.pi/extensions/lib/plan-debate-write-guard.ts +20 -0
  26. package/.pi/extensions/lib/plan-messenger.ts +276 -0
  27. package/.pi/extensions/lib/plan-review-integrator-rules.ts +119 -0
  28. package/.pi/extensions/lib/plan-scope-guard.ts +89 -0
  29. package/.pi/harness/agents.manifest.json +7 -7
  30. package/.pi/prompts/harness-plan.md +22 -12
  31. package/CHANGELOG.md +18 -0
  32. package/THIRD_PARTY_NOTICES.md +1 -1
  33. package/package.json +3 -3
  34. package/.agents/skills/ck-search/SKILL.md +0 -23
  35. package/.agents/skills/cocoindex-search/SKILL.md +0 -35
  36. package/.agents/skills/obsidian-bases/SKILL.md +0 -299
  37. package/.agents/skills/obsidian-markdown/SKILL.md +0 -237
  38. package/.pi/extensions/lib/plan-approval/fallback.ts +0 -50
  39. /package/{.pi → .agents}/skills/ccc/references/management.md +0 -0
@@ -1,299 +0,0 @@
1
- ---
2
- name: obsidian-bases
3
- description: "Create and edit Obsidian Bases (.base files): Obsidian's native database layer for dynamic tables, card views, list views, filters, formulas, and summaries over vault notes. Triggers on: create a base, add a base file, obsidian bases, base view, filter notes, formula, database view, dynamic table, task tracker base, reading list base."
4
- allowed-tools: Read Write
5
- ---
6
-
7
- # obsidian-bases: Obsidian's Database Layer
8
-
9
- Obsidian Bases (launched 2025) turns vault notes into queryable, dynamic views. Tables, cards, lists, maps. Defined in `.base` files. No plugin required; it is a core Obsidian feature.
10
-
11
- **Authoritative reference**: If the kepano/obsidian-skills plugin is installed, prefer its canonical obsidian-bases skill. Otherwise, use the reference below. Official docs: https://help.obsidian.md/bases/syntax
12
-
13
- ---
14
-
15
- ## Wiki Path Resolution
16
-
17
- All `wiki/` paths in this skill (in `.base` filter expressions like `file.inFolder("wiki/")`) are relative to the wiki directory inside the Obsidian vault. Obsidian Bases operate on the vault directly; the `wiki/` prefix in filter expressions reflects the folder name within the vault. If your wiki folder has a different name, adjust filter paths accordingly.
18
-
19
- ---
20
-
21
- ## File Format
22
-
23
- `.base` files contain valid YAML. The root keys are `filters`, `formulas`, `properties`, `summaries`, and `views`.
24
-
25
- ```yaml
26
- # Global filters: apply to ALL views
27
- filters:
28
- and:
29
- - file.hasTag("wiki")
30
- - 'status != "archived"'
31
-
32
- # Computed properties
33
- formulas:
34
- age_days: '(now() - file.ctime).days.round(0)'
35
- status_icon: 'if(status == "mature", "✅", "🔄")'
36
-
37
- # Display name overrides for properties panel
38
- properties:
39
- status:
40
- displayName: "Status"
41
- formula.age_days:
42
- displayName: "Age (days)"
43
-
44
- # One or more views
45
- views:
46
- - type: table
47
- name: "All Pages"
48
- order:
49
- - file.name
50
- - type
51
- - status
52
- - updated
53
- - formula.age_days
54
- ```
55
-
56
- ---
57
-
58
- ## Filters
59
-
60
- Filters select which notes appear. Applied globally or per-view.
61
-
62
- ```yaml
63
- # Single string filter
64
- filters: 'status == "current"'
65
-
66
- # AND: all must be true
67
- filters:
68
- and:
69
- - 'status != "archived"'
70
- - file.hasTag("wiki")
71
-
72
- # OR: any can be true
73
- filters:
74
- or:
75
- - file.hasTag("concept")
76
- - file.hasTag("entity")
77
-
78
- # NOT: exclude matches
79
- filters:
80
- not:
81
- - file.inFolder("wiki/meta")
82
-
83
- # Nested
84
- filters:
85
- and:
86
- - file.inFolder("wiki/")
87
- - or:
88
- - 'type == "concept"'
89
- - 'type == "entity"'
90
- ```
91
-
92
- ### Filter operators
93
-
94
- `==` `!=` `>` `<` `>=` `<=`
95
-
96
- ### Useful filter functions
97
-
98
- | Function | Example |
99
- |----------|---------|
100
- | `file.hasTag("x")` | Notes with tag `x` |
101
- | `file.inFolder("path/")` | Notes in folder |
102
- | `file.hasLink("Note")` | Notes linking to Note |
103
-
104
- ---
105
-
106
- ## Properties
107
-
108
- Three types:
109
- - **Note properties**: from frontmatter: `status`, `type`, `updated`
110
- - **File properties**: metadata: `file.name`, `file.mtime`, `file.size`, `file.ctime`, `file.tags`, `file.folder`
111
- - **Formula properties**: computed: `formula.age_days`
112
-
113
- ---
114
-
115
- ## Formulas
116
-
117
- Defined in `formulas:`. Referenced as `formula.name` in `order:` and `properties:`.
118
-
119
- ```yaml
120
- formulas:
121
- # Days since created
122
- age_days: '(now() - file.ctime).days.round(0)'
123
-
124
- # Days until a date property
125
- days_until: 'if(due_date, (date(due_date) - today()).days, "")'
126
-
127
- # Conditional label
128
- status_icon: 'if(status == "mature", "✅", if(status == "developing", "🔄", "🌱"))'
129
-
130
- # Word count estimate
131
- word_est: '(file.size / 5).round(0)'
132
- ```
133
-
134
- **Key rule**: Subtracting two dates returns a `Duration`. Not a number. Always access `.days` first:
135
- ```yaml
136
- # CORRECT
137
- age: '(now() - file.ctime).days'
138
-
139
- # WRONG: crashes
140
- age: '(now() - file.ctime).round(0)'
141
- ```
142
-
143
- **Always guard nullable properties with `if()`**:
144
- ```yaml
145
- # CORRECT
146
- days_left: 'if(due_date, (date(due_date) - today()).days, "")'
147
- ```
148
-
149
- ---
150
-
151
- ## View Types
152
-
153
- ### Table
154
- ```yaml
155
- views:
156
- - type: table
157
- name: "Wiki Index"
158
- limit: 100
159
- order:
160
- - file.name
161
- - type
162
- - status
163
- - updated
164
- groupBy:
165
- property: type
166
- direction: ASC
167
- ```
168
-
169
- ### Cards
170
- ```yaml
171
- views:
172
- - type: cards
173
- name: "Gallery"
174
- order:
175
- - file.name
176
- - tags
177
- - status
178
- ```
179
-
180
- ### List
181
- ```yaml
182
- views:
183
- - type: list
184
- name: "Quick List"
185
- order:
186
- - file.name
187
- - status
188
- ```
189
-
190
- ---
191
-
192
- ## Wiki Vault Templates
193
-
194
- ### Wiki content dashboard (all non-meta pages)
195
-
196
- ```yaml
197
- filters:
198
- and:
199
- - file.inFolder("wiki/")
200
- - not:
201
- - file.inFolder("wiki/meta")
202
-
203
- formulas:
204
- age: '(now() - file.ctime).days.round(0)'
205
-
206
- properties:
207
- formula.age:
208
- displayName: "Age (days)"
209
-
210
- views:
211
- - type: table
212
- name: "All Wiki Pages"
213
- order:
214
- - file.name
215
- - type
216
- - status
217
- - updated
218
- - formula.age
219
- groupBy:
220
- property: type
221
- direction: ASC
222
- ```
223
-
224
- ### Entity index (people, orgs, repos)
225
-
226
- ```yaml
227
- filters:
228
- and:
229
- - file.inFolder("wiki/entities/")
230
- - 'file.ext == "md"'
231
-
232
- views:
233
- - type: table
234
- name: "Entities"
235
- order:
236
- - file.name
237
- - entity_type
238
- - status
239
- - updated
240
- groupBy:
241
- property: entity_type
242
- direction: ASC
243
- ```
244
-
245
- ### Recent ingests
246
-
247
- ```yaml
248
- filters:
249
- and:
250
- - file.inFolder("wiki/sources/")
251
-
252
- views:
253
- - type: table
254
- name: "Sources"
255
- order:
256
- - file.name
257
- - source_type
258
- - created
259
- - status
260
- groupBy:
261
- property: source_type
262
- direction: ASC
263
- ```
264
-
265
- ---
266
-
267
- ## Embedding in Notes
268
-
269
- ```markdown
270
- ![[MyBase.base]]
271
-
272
- ![[MyBase.base#View Name]]
273
- ```
274
-
275
- ---
276
-
277
- ## Where to Save
278
-
279
- Store `.base` files in `wiki/meta/` for vault dashboards:
280
- - `wiki/meta/dashboard.base`: main content view
281
- - `wiki/meta/entities.base`: entity tracker
282
- - `wiki/meta/sources.base`: ingestion log
283
-
284
- ---
285
-
286
- ## YAML Quoting Rules
287
-
288
- - Formulas with double quotes → wrap in single quotes: `'if(done, "Yes", "No")'`
289
- - Strings with colons or special chars → wrap in double quotes: `"Status: Active"`
290
- - Unquoted strings with `:` break YAML parsing
291
-
292
- ---
293
-
294
- ## What Not to Do
295
-
296
- - Do not use `from:` or `where:`: those are Dataview syntax, not Obsidian Bases
297
- - Do not use `sort:` at the root level: sorting is per-view via `order:` and `groupBy:`
298
- - Do not put `.base` files outside the vault: they only render inside Obsidian
299
- - Do not reference `formula.X` in `order:` without defining `X` in `formulas:`
@@ -1,237 +0,0 @@
1
- ---
2
- name: obsidian-markdown
3
- description: "Write correct Obsidian Flavored Markdown: wikilinks, embeds, callouts, properties, tags, highlights, math, and canvas syntax. Reference this when creating or editing any wiki page. Triggers on: write obsidian note, obsidian syntax, wikilink, callout, embed, obsidian markdown, wikilink format, callout syntax, embed syntax, obsidian formatting, how to write obsidian markdown."
4
- allowed-tools: Read Write Edit
5
- ---
6
-
7
- # obsidian-markdown: Obsidian Flavored Markdown
8
-
9
- Reference this skill when writing any wiki page. Obsidian extends standard Markdown with wikilinks, embeds, callouts, and properties. Getting syntax wrong causes broken links, invisible callouts, or malformed frontmatter.
10
-
11
- **Cross-reference**: If the kepano/obsidian-skills plugin is installed, prefer its canonical obsidian-markdown skill for authoritative Obsidian syntax reference. Otherwise, use the reference below. See also [github.com/kepano/obsidian-skills](https://github.com/kepano/obsidian-skills).
12
-
13
- ---
14
-
15
- ## Wiki Path Resolution
16
-
17
- This skill provides Obsidian syntax reference. It does NOT perform file operations itself. When invoked by other skills (wiki-ingest, wiki-save, etc.), those skills handle wiki path resolution via `VAULT_WIKI_PATH`.
18
-
19
- ---
20
-
21
- ## Wikilinks
22
-
23
- Internal links use double brackets. The filename without extension.
24
-
25
- | Syntax | What it does |
26
- |---|---|
27
- | `[[Note Name]]` | Basic link |
28
- | `[[Note Name\|Display Text]]` | Aliased link (shows "Display Text") |
29
- | `[[Note Name#Heading]]` | Link to a specific heading |
30
- | `[[Note Name#^block-id]]` | Link to a specific block |
31
-
32
- Rules:
33
- - Case-sensitive on some systems. Match the exact filename.
34
- - No path needed: Obsidian resolves by filename uniqueness.
35
- - If two files have the same name, use `[[Folder/Note Name]]` to disambiguate.
36
-
37
- ---
38
-
39
- ## Embeds
40
-
41
- Embeds use `!` before the wikilink. They display the content inline.
42
-
43
- | Syntax | What it does |
44
- |---|---|
45
- | `![[Note Name]]` | Embed a full note |
46
- | `![[Note Name#Heading]]` | Embed a section |
47
- | `![[image.png]]` | Embed an image |
48
- | `![[image.png\|300]]` | Embed image with width 300px |
49
- | `![[document.pdf]]` | Embed a PDF (Obsidian renders natively) |
50
- | `![[audio.mp3]]` | Embed audio |
51
-
52
- ---
53
-
54
- ## Callouts
55
-
56
- Callouts are blockquotes with a type keyword. They render as styled alert boxes.
57
-
58
- ```markdown
59
- > [!note]
60
- > Default informational callout.
61
-
62
- > [!note] Custom Title
63
- > Callout with a custom title.
64
-
65
- > [!note]- Collapsible (closed by default)
66
- > Click to expand.
67
-
68
- > [!note]+ Collapsible (open by default)
69
- > Click to collapse.
70
- ```
71
-
72
- ### All callout types
73
-
74
- | Type | Aliases | Use for |
75
- |------|---------|---------|
76
- | `note` |: | General notes |
77
- | `abstract` | `summary`, `tldr` | Summaries |
78
- | `info` |: | Information |
79
- | `todo` |: | Action items |
80
- | `tip` | `hint`, `important` | Tips and highlights |
81
- | `success` | `check`, `done` | Positive outcomes |
82
- | `question` | `help`, `faq` | Open questions |
83
- | `warning` | `caution`, `attention` | Warnings |
84
- | `failure` | `fail`, `missing` | Errors or failures |
85
- | `danger` | `error` | Critical issues |
86
- | `bug` |: | Known bugs |
87
- | `example` |: | Examples |
88
- | `quote` | `cite` | Quotations |
89
- | `contradiction` |: | Conflicting information (wiki convention) |
90
-
91
- ---
92
-
93
- ## Properties (Frontmatter)
94
-
95
- Obsidian renders YAML frontmatter as a Properties panel. Rules:
96
-
97
- ```yaml
98
- ---
99
- type: concept # plain string
100
- title: "Note Title" # quoted if it contains special chars
101
- created: 2026-04-08 # date as YYYY-MM-DD (not ISO datetime)
102
- updated: 2026-04-08
103
- tags:
104
- - tag-one # list items use - format
105
- - tag-two
106
- status: developing
107
- related:
108
- - "[[Other Note]]" # wikilinks must be quoted in YAML
109
- sources:
110
- - "[[source-page]]"
111
- ---
112
- ```
113
-
114
- Rules:
115
- - Flat YAML only. Never nest objects.
116
- - Dates as `YYYY-MM-DD`, not `2026-04-08T00:00:00`.
117
- - Lists as `- item`, not inline `[a, b, c]`.
118
- - Wikilinks in YAML must be quoted: `"[[Page]]"`.
119
- - `tags` field: Obsidian reads this as the tag list, searchable in vault.
120
-
121
- ---
122
-
123
- ## Tags
124
-
125
- Two valid forms:
126
-
127
- ```markdown
128
- #tag-name : inline tag anywhere in the body
129
- #parent/child-tag : nested tag (shows hierarchy in tag pane)
130
- ```
131
-
132
- In frontmatter:
133
- ```yaml
134
- tags:
135
- - research
136
- - ai/obsidian
137
- ```
138
-
139
- Do not use `#` inside frontmatter tag lists. Just the tag name.
140
-
141
- ---
142
-
143
- ## Text Formatting
144
-
145
- Standard Markdown plus Obsidian extensions:
146
-
147
- | Syntax | Result |
148
- |---|---|
149
- | `**bold**` | Bold |
150
- | `*italic*` | Italic |
151
- | `~~strikethrough~~` | Strikethrough |
152
- | `==highlight==` | Highlighted text (yellow in Obsidian) |
153
- | `` `inline code` `` | Inline code |
154
-
155
- ---
156
-
157
- ## Math
158
-
159
- Obsidian uses MathJax/KaTeX:
160
-
161
- Inline math:
162
- ```markdown
163
- $E = mc^2$
164
- ```
165
-
166
- Block math:
167
- ```markdown
168
- $$
169
- \int_0^\infty e^{-x} dx = 1
170
- $$
171
- ```
172
-
173
- ---
174
-
175
- ## Code Blocks
176
-
177
- Standard fenced code blocks. Obsidian highlights all common languages:
178
-
179
- ````markdown
180
- ```python
181
- def hello():
182
- return "world"
183
- ```
184
- ````
185
-
186
- ---
187
-
188
- ## Tables
189
-
190
- Standard Markdown tables:
191
-
192
- ```markdown
193
- | Column A | Column B | Column C |
194
- |----------|----------|----------|
195
- | Value | Value | Value |
196
- | Value | Value | Value |
197
- ```
198
-
199
- Obsidian renders tables natively. No plugin needed.
200
-
201
- ---
202
-
203
- ## Mermaid Diagrams
204
-
205
- Obsidian renders Mermaid natively:
206
-
207
- ````markdown
208
- ```mermaid
209
- graph TD
210
- A[Start] --> B{Decision}
211
- B -->|Yes| C[End]
212
- B -->|No| D[Loop]
213
- D --> A
214
- ```
215
- ````
216
-
217
- Supported: `graph`, `sequenceDiagram`, `gantt`, `classDiagram`, `pie`, `flowchart`.
218
-
219
- ---
220
-
221
- ## Footnotes
222
-
223
- ```markdown
224
- This sentence has a footnote.[^1]
225
-
226
- [^1]: The footnote text goes here.
227
- ```
228
-
229
- ---
230
-
231
- ## What NOT to Do
232
-
233
- - Do not use `[link text](path/to/note.md)` for internal links: use `[[Note Name]]` instead.
234
- - Do not use HTML inside callouts: stick to Markdown.
235
- - Do not use `##` inside a callout body: headings don't render inside callouts.
236
- - Do not write `tags: [a, b, c]` inline in frontmatter: Obsidian prefers the list format.
237
- - Do not write ISO datetimes in frontmatter (`2026-04-08T00:00:00Z`): use `2026-04-08`.
@@ -1,50 +0,0 @@
1
- import type { ExtensionUIContext } from "@earendil-works/pi-coding-agent";
2
- import { formatPlanPacketLines } from "./format-plan.js";
3
- import type {
4
- PlanApprovalDialogResult,
5
- ValidatedApprovePlanParams,
6
- } from "./types.js";
7
-
8
- export async function runPlanApprovalFallback(
9
- ui: ExtensionUIContext,
10
- validated: ValidatedApprovePlanParams,
11
- ): Promise<PlanApprovalDialogResult> {
12
- const lines = formatPlanPacketLines(validated.plan_packet, 80);
13
- const body = lines.join("\n");
14
- const summary = validated.human_summary
15
- ? `${validated.human_summary}\n\n`
16
- : "";
17
- const prompt = `${summary}${body}\n\nSelect: ${validated.options.map((o, i) => `${i + 1}. ${o.title}`).join(" | ")}`;
18
- const raw = await ui.input("Plan approval", prompt);
19
- if (!raw?.trim()) {
20
- return { response: null, cancelled: true };
21
- }
22
- const pick = raw.trim();
23
- const byIndex = Number.parseInt(pick, 10);
24
- if (
25
- Number.isFinite(byIndex) &&
26
- byIndex >= 1 &&
27
- byIndex <= validated.options.length
28
- ) {
29
- return {
30
- response: {
31
- kind: "selection",
32
- selections: [validated.options[byIndex - 1].title],
33
- },
34
- cancelled: false,
35
- };
36
- }
37
- const match = validated.options.find(
38
- (o) => o.title.toLowerCase() === pick.toLowerCase(),
39
- );
40
- if (match) {
41
- return {
42
- response: { kind: "selection", selections: [match.title] },
43
- cancelled: false,
44
- };
45
- }
46
- return {
47
- response: { kind: "freeform", text: pick },
48
- cancelled: false,
49
- };
50
- }