deepclause-pi 0.1.4 → 0.1.5
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/docs/BLOG_POST_PI_EXTENSION.md +253 -0
- package/package.json +6 -2
- package/skills/handbook-dml/SKILL.md +265 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# DeepClause meets pi: executable agent plans inside your coding session
|
|
2
|
+
|
|
3
|
+
### DML orchestration with pi’s models, tools and context
|
|
4
|
+
|
|
5
|
+
`tldr;` I built a [pi](https://github.com/badlogic/pi-mono) extension for [DeepClause](https://github.com/deepclause/deepclause-sdk). It runs DML programs with pi’s active model, credentials and session context. It can also turn a normal planning request into an executable DML plan. The plan can delegate individual steps back to pi, with a fixed set of tools for each step.
|
|
6
|
+
|
|
7
|
+
The extension is available here: [https://github.com/deepclause/deepclause-pi](https://github.com/deepclause/deepclause-pi)
|
|
8
|
+
|
|
9
|
+
[The following is mostly written by a real person ;-]
|
|
10
|
+
|
|
11
|
+
I have spent quite a bit of time using DeepClause as a standalone agent runtime. That works well for benchmarks and self-contained workflows, but it leaves out something useful: the environment of a coding agent that is already running.
|
|
12
|
+
|
|
13
|
+
A coding agent such as pi already has:
|
|
14
|
+
|
|
15
|
+
- a selected model and working authentication
|
|
16
|
+
- the current conversation and compacted session history
|
|
17
|
+
- repository instructions and loaded skills
|
|
18
|
+
- file, shell and extension tools
|
|
19
|
+
- a terminal UI, cancellation and usage accounting
|
|
20
|
+
|
|
21
|
+
Reimplementing all of that in DeepClause would make little sense. The more useful option is to let pi remain the host and use DeepClause for the part it is good at: explicit orchestration.
|
|
22
|
+
|
|
23
|
+
This is what the new extension does.
|
|
24
|
+
|
|
25
|
+
[Image: `/dc` status and command overview]
|
|
26
|
+
|
|
27
|
+
### Running DML inside pi
|
|
28
|
+
|
|
29
|
+
The basic case is simple. DML programs live in `.pi/deepclause/skills/` and can be executed with a slash command:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
/dc-run example --debug
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The extension uses the model currently selected in pi. It does not ask for another API key or try to guess the provider. Model calls, cancellation, input prompts and usage stay connected to the current pi session.
|
|
36
|
+
|
|
37
|
+
A minimal skill still looks like ordinary DML:
|
|
38
|
+
|
|
39
|
+
```prolog
|
|
40
|
+
agent_main(Topic) :-
|
|
41
|
+
system("You are a concise technical analyst."),
|
|
42
|
+
format(string(Request),
|
|
43
|
+
"Explain ~w. Store the final explanation in Summary.",
|
|
44
|
+
[Topic]),
|
|
45
|
+
task(Request, string(Summary)),
|
|
46
|
+
answer(Summary).
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Run it as follows:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
/dc-run skills/explain.dml "constraint logic programming"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
There are three context modes:
|
|
56
|
+
|
|
57
|
+
- `turn` imports the current request and its immediate context
|
|
58
|
+
- `branch` imports a bounded part of the active session branch
|
|
59
|
+
- `isolated` starts without pi conversation history
|
|
60
|
+
|
|
61
|
+
For example:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
/dc-run skills/explain.dml "constraint logic programming" --context=isolated
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Pi remains the session owner. DeepClause does not create another chat history next to it.
|
|
68
|
+
|
|
69
|
+
### Tools are deliberately boring
|
|
70
|
+
|
|
71
|
+
Ordinary DML programs do not receive pi’s complete tool registry. They start with two narrow host operations:
|
|
72
|
+
|
|
73
|
+
- `pi_workspace_list` lists one directory level inside the workspace
|
|
74
|
+
- `pi_bash` runs an approved command inside the workspace
|
|
75
|
+
|
|
76
|
+
Every `pi_bash` call requires user confirmation. Paths are checked against the active workspace, including resolved symlinks.
|
|
77
|
+
|
|
78
|
+
A DML program can wrap these operations in a more useful tool predicate:
|
|
79
|
+
|
|
80
|
+
```prolog
|
|
81
|
+
tool(bing_search(Query, Results),
|
|
82
|
+
"Search Bing RSS and return the response body") :-
|
|
83
|
+
format(string(QueryArg), "q=~w", [Query]),
|
|
84
|
+
exec(pi_bash("curl", [
|
|
85
|
+
"--fail", "--silent", "--show-error", "--location", "--get",
|
|
86
|
+
"--data-urlencode", QueryArg,
|
|
87
|
+
"https://www.bing.com/search?format=rss&count=8"
|
|
88
|
+
]), Result),
|
|
89
|
+
get_dict(stdout, Result, Results).
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The repository includes a small deep-research example built on this pattern. It asks the user to review a search plan through pi’s input UI, runs approved `curl` requests and produces a cited report.
|
|
93
|
+
|
|
94
|
+
I intentionally did not expose all coding tools directly through `exec/2`. Pi extensions can describe their tools, but there is no public generic API for another extension to invoke any tool by name. More importantly, copying tool execution into DeepClause would bypass behavior owned by pi or another extension, such as approval dialogs and policy checks.
|
|
95
|
+
|
|
96
|
+
This becomes relevant for planning.
|
|
97
|
+
|
|
98
|
+
### DML is the plan
|
|
99
|
+
|
|
100
|
+
The extension adds this command:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
/dc-plan <request> [--name=slug]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For example:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
/dc-plan build a small Three.js Space Invaders game and verify it --name=threejs-space-invaders
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This starts a normal pi turn. The planner can inspect the repository, read its instructions, see loaded skills and consider the currently active tools. It does not directly return a Markdown checklist and it does not generate arbitrary DML source in one shot.
|
|
113
|
+
|
|
114
|
+
Instead, the planning turn finishes by calling a temporary tool named `dc_plan_commit`. The tool accepts a typed plan specification with:
|
|
115
|
+
|
|
116
|
+
- a title and objective
|
|
117
|
+
- ordered steps
|
|
118
|
+
- an executor for each step
|
|
119
|
+
- exact required tool names
|
|
120
|
+
- relevant pi skills
|
|
121
|
+
- an expected result for every step
|
|
122
|
+
- a fallback message
|
|
123
|
+
|
|
124
|
+
The extension validates this object and shows a preview. After user confirmation, it deterministically assembles the DML file, parses the generated program and writes it under `.pi/deepclause/plans/` without overwriting an existing file.
|
|
125
|
+
|
|
126
|
+
This follows the same general idea as the planner used in my DeepPlanning experiments: ask the model for a constrained intermediate representation and let normal code produce the executable DML. This is simpler and more reliable than asking the model to get every comma, variable and fallback clause right.
|
|
127
|
+
|
|
128
|
+
A generated plan looks like this:
|
|
129
|
+
|
|
130
|
+
```prolog
|
|
131
|
+
agent_main :-
|
|
132
|
+
output("Step 1/3: Inspect the workspace"),
|
|
133
|
+
exec(pi_agent_step(
|
|
134
|
+
instruction: "Inspect repository instructions and identify the target app.",
|
|
135
|
+
tools: ["bash", "read"],
|
|
136
|
+
expected: "A target directory and concrete implementation baseline.",
|
|
137
|
+
skills: []
|
|
138
|
+
), Step1Summary),
|
|
139
|
+
Step1Summary \= "",
|
|
140
|
+
|
|
141
|
+
output("Step 2/3: Implement the application"),
|
|
142
|
+
exec(pi_agent_step(
|
|
143
|
+
instruction: "Implement the agreed application and keep changes scoped.",
|
|
144
|
+
tools: ["read", "write", "edit"],
|
|
145
|
+
expected: "A runnable implementation with a concise change summary.",
|
|
146
|
+
skills: []
|
|
147
|
+
), Step2Summary),
|
|
148
|
+
Step2Summary \= "",
|
|
149
|
+
|
|
150
|
+
output("Step 3/3: Validate the result"),
|
|
151
|
+
exec(pi_agent_step(
|
|
152
|
+
instruction: "Run the relevant checks and fix implementation failures.",
|
|
153
|
+
tools: ["bash", "read", "write", "edit"],
|
|
154
|
+
expected: "Passing checks or a precise account of remaining failures.",
|
|
155
|
+
skills: []
|
|
156
|
+
), Step3Summary),
|
|
157
|
+
Step3Summary \= "",
|
|
158
|
+
|
|
159
|
+
answer([Step1Summary, Step2Summary, Step3Summary]).
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The full file is executable. There is no Markdown-to-DML compilation step in the pi integration.
|
|
163
|
+
|
|
164
|
+
[Image: generated DML plan in the editor]
|
|
165
|
+
|
|
166
|
+
### What `pi_agent_step` does
|
|
167
|
+
|
|
168
|
+
`pi_agent_step` is the bridge between DML orchestration and a normal pi coding turn.
|
|
169
|
+
|
|
170
|
+
When the DML runtime reaches one of these calls, the extension:
|
|
171
|
+
|
|
172
|
+
1. checks that every named tool is installed and currently active
|
|
173
|
+
2. rejects DeepClause control tools to prevent recursive planning or execution
|
|
174
|
+
3. saves pi’s current active-tool set
|
|
175
|
+
4. temporarily activates only the tools named by the step
|
|
176
|
+
5. sends the bounded instruction through a normal pi turn
|
|
177
|
+
6. captures the final textual summary and tool failures
|
|
178
|
+
7. restores the previous active-tool set on success, failure or cancellation
|
|
179
|
+
|
|
180
|
+
The important point is that pi still executes the turn. A third-party extension tool therefore keeps its own UI, approvals and policy. DeepClause only controls which tools are available to that particular step and what should happen next.
|
|
181
|
+
|
|
182
|
+
The user must start such a plan explicitly:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
/dc-run plans/threejs_space_invaders.dml
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Before execution, the extension shows the required tools and asks for confirmation.
|
|
189
|
+
|
|
190
|
+
The optional model-callable `dc_run` tool cannot execute contextual plans. Allowing an agent turn to start a plan that starts more agent turns would make recursion and session ownership needlessly difficult. For this first version, the boundary is simple: reusable self-contained skills may be model-called after explicit enablement; contextual plans are user-called.
|
|
191
|
+
|
|
192
|
+
### A concrete example
|
|
193
|
+
|
|
194
|
+
I used `/dc-plan` to create a five-step plan for a small Three.js Space Invaders game. The generated DML fixes the execution order:
|
|
195
|
+
|
|
196
|
+
1. inspect the workspace and choose the integration boundary
|
|
197
|
+
2. create the browser application foundation
|
|
198
|
+
3. implement deterministic game state and collision logic
|
|
199
|
+
4. connect the state to rendering, controls and UI
|
|
200
|
+
5. run tests and build the production bundle
|
|
201
|
+
|
|
202
|
+
Each step has a different tool set. Inspection gets `bash` and `read`. Pure implementation steps get `read`, `write` and `edit`. Validation gets all four. The plan records these requirements before any work starts.
|
|
203
|
+
|
|
204
|
+
This does not guarantee a correct game. The model can still write bad code, misunderstand an API or produce an incomplete summary. What it does guarantee is a more explicit execution structure. The agent cannot quietly skip from initial inspection to a confident final answer without the intervening DML goals succeeding.
|
|
205
|
+
|
|
206
|
+
This is the same reason I find DML useful with smaller models. Long context alone does not make long-running execution reliable. An explicit program can carry the sequence, checks, retries and fallback while the model deals with the parts that actually require judgment.
|
|
207
|
+
|
|
208
|
+
### Installation
|
|
209
|
+
|
|
210
|
+
The current release is `0.1.2` and depends on `deepclause-sdk` `0.0.87`.
|
|
211
|
+
|
|
212
|
+
Install directly from GitHub:
|
|
213
|
+
|
|
214
|
+
```sh
|
|
215
|
+
pi install git:github.com/deepclause/deepclause-pi
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Or install it for one project:
|
|
219
|
+
|
|
220
|
+
```sh
|
|
221
|
+
pi install git:github.com/deepclause/deepclause-pi -l
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
For a project-local installation, start pi in the directory containing `.pi/settings.json`. The startup screen should list the DeepClause extension. If it does not, `/dc-run` will be treated as an ordinary message and sent to the model.
|
|
225
|
+
|
|
226
|
+
Useful commands:
|
|
227
|
+
|
|
228
|
+
```text
|
|
229
|
+
/dc
|
|
230
|
+
/dc-list
|
|
231
|
+
/dc-plan inspect this repository and propose a safe migration --name=migration
|
|
232
|
+
/dc-run plans/migration.dml
|
|
233
|
+
/dc-tool enable
|
|
234
|
+
/dc-cancel
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
`dc_run` is disabled by default. `/dc-tool enable` makes it available to the model for that workspace. This does not grant ordinary DML programs access to all pi tools.
|
|
238
|
+
|
|
239
|
+
### Some more thoughts and notes
|
|
240
|
+
|
|
241
|
+
1. This is an early integration. The main execution path works and has tests for plan creation, tool preflight, contextual delegation, cancellation and tool restoration. There are still plenty of rough edges to find in real repositories.
|
|
242
|
+
|
|
243
|
+
2. `task/N` supports stream events, but the current pi model adapter receives a completed model response and forwards it as one chunk. Tool activity, DML progress, input requests and usage are already live.
|
|
244
|
+
|
|
245
|
+
3. Generated plans currently record tool names, but not stable hashes of their schemas. A tool can change between planning and execution. The runtime catches missing or inactive tools, while deeper schema-drift checks can be added later.
|
|
246
|
+
|
|
247
|
+
4. DML backtracking does not undo external effects. If a plan writes a file and later fails, Prolog can try another clause, but the file is still there. Generated coding plans therefore use ordered steps and explicit summaries rather than pretending that side effects are transactional.
|
|
248
|
+
|
|
249
|
+
5. Does this produce better coding results than an unconstrained pi turn? I have some good examples, but no benchmark yet. The useful claim for now is narrower: it gives us an executable, inspectable plan with a clear boundary around context and tools. Please try it and report what breaks.
|
|
250
|
+
|
|
251
|
+
Repository: [https://github.com/deepclause/deepclause-pi](https://github.com/deepclause/deepclause-pi)
|
|
252
|
+
|
|
253
|
+
DeepClause SDK: [https://github.com/deepclause/deepclause-sdk](https://github.com/deepclause/deepclause-sdk)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deepclause-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Pi-hosted runtime for DeepClause DML programs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,11 +25,15 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
27
|
"docs",
|
|
28
|
-
"src"
|
|
28
|
+
"src",
|
|
29
|
+
"skills"
|
|
29
30
|
],
|
|
30
31
|
"pi": {
|
|
31
32
|
"extensions": [
|
|
32
33
|
"./src/index.ts"
|
|
34
|
+
],
|
|
35
|
+
"skills": [
|
|
36
|
+
"./skills"
|
|
33
37
|
]
|
|
34
38
|
},
|
|
35
39
|
"scripts": {
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: handbook-dml
|
|
3
|
+
description: Convert a long handbook/SOP into one DeepClause DML skill per workflow — an LLM-first subagent (agentic task/N leaves, narrow tool/2 capabilities) that takes a generic natural-language request as input and uses deterministic Prolog only for mechanical checks, with LLM fallback. Also teaches a tool audit, user confirmation, and how to write the repo-root AGENTS.md policy-routing table so pi calls the skills automatically via dc_run. Use when asked to turn a handbook or procedures manual into executable DML, update a handbook-derived skill, or wire the policy router.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Handbook → DML (procedures)
|
|
7
|
+
|
|
8
|
+
Turn a long handbook into **one DML skill per workflow/procedure**. Each skill is
|
|
9
|
+
an **LLM-first subagent**: agentic `task/N` leaves do the reading, reasoning,
|
|
10
|
+
and acting, while Prolog handles only what is genuinely mechanical (arithmetic,
|
|
11
|
+
counting, exact equality) or a hard safety invariant.
|
|
12
|
+
|
|
13
|
+
Before writing DML, read `.pi/deepclause/AGENTS.md` and
|
|
14
|
+
`.pi/deepclause/DML_REFERENCE.md`. They are authoritative for syntax.
|
|
15
|
+
|
|
16
|
+
## Mental model
|
|
17
|
+
|
|
18
|
+
- **Pi authors; DML is the runtime artifact.** Decomposition and authoring happen
|
|
19
|
+
in a normal pi turn. There is no Markdown→DML compiler.
|
|
20
|
+
- **LLM-first.** Rules and flow are `task/N` / `prompt/N` by default. Use Prolog
|
|
21
|
+
only where a rule is mechanical or must never be wrong.
|
|
22
|
+
- **Input is a generic request.** `agent_main(Request)` takes free text; the
|
|
23
|
+
first step is an LLM `task/N` that parses it into a typed `object/1` case (or
|
|
24
|
+
the request is used directly for simple skills).
|
|
25
|
+
- **Forbidden actions become tool scoping.** "Never send" means *no send tool*.
|
|
26
|
+
"Read-only inspection" means the inspect phase gets read tools only.
|
|
27
|
+
- **Every deterministic rule gets an LLM fallback.** If a deterministic check
|
|
28
|
+
fails, branch to a `prompt/N`/`task/N` that reviews, repairs, or asks the user
|
|
29
|
+
— do not hard-fail.
|
|
30
|
+
- **Ask, don't assume.** Confirm scope, the decomposition, and tool choices with
|
|
31
|
+
the user before authoring.
|
|
32
|
+
|
|
33
|
+
## Workflow
|
|
34
|
+
|
|
35
|
+
1. **Ingest** the handbook to Markdown (PDF→`pdftotext`, DOCX/HTML→`pandoc`).
|
|
36
|
+
Keep the source under `examples/handbook-md/<handbook_slug>/`.
|
|
37
|
+
2. **Clarify** with the user: which workflows to convert, what the input looks
|
|
38
|
+
like (a request? a file? a case id?), and what the skill may change.
|
|
39
|
+
3. **Decompose** by the document's own workflows and **propose the
|
|
40
|
+
section → skill map; get approval** before writing files.
|
|
41
|
+
4. **Tool audit** (below): list each procedure's required capabilities, check
|
|
42
|
+
what is available, flag gaps, and ask whether dummy tools are acceptable.
|
|
43
|
+
5. **Author** one DML per workflow from the template below.
|
|
44
|
+
6. **Run and iterate** with the user's real input:
|
|
45
|
+
`/dc-run skills/<handbook_slug>/<slug>.dml "<request>" --debug`.
|
|
46
|
+
7. **Write `INDEX.md`** and **add a row to the repo-root `AGENTS.md`** routing
|
|
47
|
+
table.
|
|
48
|
+
|
|
49
|
+
## Input convention
|
|
50
|
+
|
|
51
|
+
The skill takes a **generic natural-language request**, not positional args and
|
|
52
|
+
not hardcoded case facts.
|
|
53
|
+
|
|
54
|
+
- Default: parse the request with an LLM `task/N` into a typed `object/1` case.
|
|
55
|
+
- Simpler skills: pass the request text directly into the first `task/N` and
|
|
56
|
+
skip the extraction step.
|
|
57
|
+
|
|
58
|
+
```prolog
|
|
59
|
+
extract_case(Request, Case) :-
|
|
60
|
+
format(string(Desc),
|
|
61
|
+
"Extract a structured case from this request: ~w. Store an object with keys <fields>. Use null for unknown fields.",
|
|
62
|
+
[Request]),
|
|
63
|
+
task(Desc, object(Case)).
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`object(Var)` is a supported typed output; read it with `get_dict/3`. Then
|
|
67
|
+
confirm with the user before acting. User interaction loops belong **inside a
|
|
68
|
+
`task/N`**, with `ask_user` exposed as a tool:
|
|
69
|
+
|
|
70
|
+
```prolog
|
|
71
|
+
tool(user_feedback(Prompt, Response), "Ask the user one focused question and return their response") :-
|
|
72
|
+
exec(ask_user(prompt: Prompt), Result),
|
|
73
|
+
get_dict(user_response, Result, Response).
|
|
74
|
+
|
|
75
|
+
confirm_case(Case, ConfirmedCase) :-
|
|
76
|
+
format(string(Instruction),
|
|
77
|
+
"Present this extracted case to the user with the user_feedback tool: ~w. Ask them to type 'ok' or describe corrections. If 'ok', return the case unchanged. Otherwise apply corrections and ask again, up to 3 rounds. Store the final case in ConfirmedCase.",
|
|
78
|
+
[Case]),
|
|
79
|
+
with_tools([user_feedback], (
|
|
80
|
+
task(Instruction, object(ConfirmedCase))
|
|
81
|
+
)).
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Tool audit
|
|
85
|
+
|
|
86
|
+
Before authoring, list what the procedure needs and check what actually exists.
|
|
87
|
+
|
|
88
|
+
| Procedure need | Real option | Dummy fallback |
|
|
89
|
+
| --- | --- | --- |
|
|
90
|
+
| email / Slack / calendar / Jira / Shopify | pi tools (if installed & active) or MCP | `tool/2` over `pi_bash` (files) or over facts |
|
|
91
|
+
| read spreadsheets / PDFs / CSVs | pi tools or `pi_bash` | `tool/2` reading fixture files |
|
|
92
|
+
| ask the user | `ask_user` (always available in DML) | — |
|
|
93
|
+
| arbitrary shell | `pi_bash` (approval-gated) | — |
|
|
94
|
+
|
|
95
|
+
The DML runtime itself exposes only `pi_workspace_list`, `pi_bash`, and
|
|
96
|
+
`ask_user`. Everything else (email, Slack, calendar, structured file readers) is
|
|
97
|
+
missing unless you add it as a DML `tool/2`. So:
|
|
98
|
+
|
|
99
|
+
1. For each required capability, note whether a real tool exists.
|
|
100
|
+
2. If it is missing, **tell the user and ask: "use a dummy tool for X?"** before
|
|
101
|
+
authoring. Do not silently build a dummy.
|
|
102
|
+
3. Record the chosen substitution in the skill header and in `INDEX.md`.
|
|
103
|
+
|
|
104
|
+
## Light template
|
|
105
|
+
|
|
106
|
+
```prolog
|
|
107
|
+
% POLICY: <slug>
|
|
108
|
+
% Handbook : <handbook_slug> (<title>)
|
|
109
|
+
% Trigger : <when to run>
|
|
110
|
+
% Input : a natural-language request (parsed by the first task)
|
|
111
|
+
% Effects : <what state this changes, if any>
|
|
112
|
+
% Tools : <real or dummy, per the tool audit>
|
|
113
|
+
%
|
|
114
|
+
% Run: /dc-run skills/<handbook_slug>/<slug>.dml "<request>"
|
|
115
|
+
|
|
116
|
+
% --- tools ----------------------------------------------------------------
|
|
117
|
+
% Read tools for inspection; write tools for action; omit forbidden actions.
|
|
118
|
+
tool(<read_...>(Args, Out), "Description") :- ... .
|
|
119
|
+
tool(<write_...>(Args, Result), "Description") :- ... .
|
|
120
|
+
tool(user_feedback(Prompt, Response), "Ask the user one focused question and return their response") :-
|
|
121
|
+
exec(ask_user(prompt: Prompt), Result),
|
|
122
|
+
get_dict(user_response, Result, Response).
|
|
123
|
+
|
|
124
|
+
% --- deterministic helpers (mechanical only) -------------------------------
|
|
125
|
+
<compute_or_check>(...). % arithmetic/counts; keep small
|
|
126
|
+
|
|
127
|
+
% --- entry point ------------------------------------------------------------
|
|
128
|
+
agent_main(Request) :-
|
|
129
|
+
Request \= "",
|
|
130
|
+
system("Role and hard rules. Treat supplied policy text as governing."),
|
|
131
|
+
output("Parsing the request..."),
|
|
132
|
+
extract_case(Request, Case), % task/N -> object/1
|
|
133
|
+
output("Confirming..."),
|
|
134
|
+
confirm_case(Case, ConfirmedCase), % user_feedback loop
|
|
135
|
+
output("Acting..."),
|
|
136
|
+
with_tools([<write tools>], (
|
|
137
|
+
task("Produce the required effects for this case: {ConfirmedCase}.", string(Summary))
|
|
138
|
+
)),
|
|
139
|
+
<optional verification with LLM fallback>,
|
|
140
|
+
answer(Final).
|
|
141
|
+
|
|
142
|
+
agent_main(_) :-
|
|
143
|
+
answer("Supply a request describing the case.").
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Notes:
|
|
147
|
+
|
|
148
|
+
- `task/N` = agentic leaf (memory + DML tools). `prompt/N` = fresh-context
|
|
149
|
+
review. `with_tools/2` scopes capability per phase.
|
|
150
|
+
- Build `task/N` descriptions with `format/3` (not `{Var}` interpolation) when
|
|
151
|
+
you embed dynamic values — avoids singleton-variable noise.
|
|
152
|
+
- Mutable facts must be declared `:- dynamic` before `assertz`/`retract`.
|
|
153
|
+
|
|
154
|
+
## Verification (optional, LLM-first)
|
|
155
|
+
|
|
156
|
+
Only add checks when the procedure has observable post-conditions. Prefer model
|
|
157
|
+
review; use deterministic checks only for mechanical facts, and always give a
|
|
158
|
+
deterministic check an LLM fallback.
|
|
159
|
+
|
|
160
|
+
```prolog
|
|
161
|
+
% deterministic gate (mechanical only)
|
|
162
|
+
holds(drafts_count) :- findall(_, draft(_,_,_,_), Ds), length(Ds, 2).
|
|
163
|
+
|
|
164
|
+
verify_state(Failed, Report) :-
|
|
165
|
+
findall(Name, (postcondition(Name), \+ holds(Name)), Failed),
|
|
166
|
+
( Failed = [] -> Report = "PASS" ; format(string(Report), "FAIL: ~w", [Failed]) ).
|
|
167
|
+
|
|
168
|
+
% LLM fallback: never hard-fail on a deterministic check
|
|
169
|
+
fallback_review(Failed, Verdict, Reason) :-
|
|
170
|
+
format(string(Prompt),
|
|
171
|
+
"These structural checks failed: ~w. Review the outcome and the requirement. Store 'acceptable' or 'needs-attention' in Verdict and a one-line reason in Reason.",
|
|
172
|
+
[Failed]),
|
|
173
|
+
prompt(Prompt, string(Verdict), string(Reason)).
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
In `agent_main`:
|
|
177
|
+
|
|
178
|
+
```prolog
|
|
179
|
+
verify_state(Failed, Report),
|
|
180
|
+
( Failed = [] -> V = "n/a", R = "deterministic checks passed"
|
|
181
|
+
; fallback_review(Failed, V, R)
|
|
182
|
+
),
|
|
183
|
+
answer(... report Report + V/R ...).
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Choosing:
|
|
187
|
+
|
|
188
|
+
- **Model review** (default): tone, completeness, correctness of free text,
|
|
189
|
+
"does this read right", and anything the rubric phrases as a judgment.
|
|
190
|
+
- **Deterministic** (only when mechanical): counts, exact IDs, arithmetic. Keep
|
|
191
|
+
it tiny, and route failures to the model or the user instead of failing.
|
|
192
|
+
|
|
193
|
+
## Dummy tools
|
|
194
|
+
|
|
195
|
+
Only after the user approves. Prefer **file-backed** dummy tools (read/write
|
|
196
|
+
fixture files through `pi_bash`) because they mirror real services and make the
|
|
197
|
+
skill runnable against real data. Use **fact-backed** state only for pure
|
|
198
|
+
in-memory cases. Keep the tool name/contract stable so a real `exec/2`/MCP
|
|
199
|
+
implementation can replace the dummy body later.
|
|
200
|
+
|
|
201
|
+
## The AGENTS.md policy router
|
|
202
|
+
|
|
203
|
+
After the skills are written and tested, wire them into the repo-root
|
|
204
|
+
`AGENTS.md` so pi calls them automatically. `AGENTS.md` is always in pi's
|
|
205
|
+
context; `dc_run` (enabled once with `/dc-tool enable`) executes a named skill.
|
|
206
|
+
|
|
207
|
+
```markdown
|
|
208
|
+
## DeepClause policy routing
|
|
209
|
+
|
|
210
|
+
When a request matches a procedure below, do **not** answer from memory or from
|
|
211
|
+
the source handbook text. Call the `dc_run` tool with the mapped skill, then
|
|
212
|
+
report its answer (including its verification result, if any).
|
|
213
|
+
|
|
214
|
+
If `dc_run` is unavailable, tell the user to run `/dc-tool enable` (persists for
|
|
215
|
+
the workspace) or to run the equivalent `/dc-run` command themselves.
|
|
216
|
+
|
|
217
|
+
| Handbook | Procedure / trigger | Skill (`dc_run.skill`) | Args (`dc_run.args`) |
|
|
218
|
+
| --- | --- | --- | --- |
|
|
219
|
+
| <handbook_slug> | <short trigger phrase a request would match> | `skills/<handbook_slug>/<slug>.dml` | `["<the user's request>"]` |
|
|
220
|
+
|
|
221
|
+
Conventions:
|
|
222
|
+
|
|
223
|
+
- `args` carries the natural-language request; pass the user's message through.
|
|
224
|
+
- If the skill has verification, do not claim success unless it passes.
|
|
225
|
+
- Detailed maps live in each handbook's
|
|
226
|
+
`.pi/deepclause/skills/<handbook_slug>/INDEX.md`.
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Rules:
|
|
230
|
+
|
|
231
|
+
1. **`Handbook`** — the `<handbook_slug>` directory under `.pi/deepclause/skills/`.
|
|
232
|
+
2. **`Procedure / trigger`** — a short phrase in the *user's* wording.
|
|
233
|
+
3. **`Skill`** — path relative to `.pi/deepclause/`; must contain `/`.
|
|
234
|
+
4. **`Args`** — the request text (the skill parses it). One row per procedure.
|
|
235
|
+
5. Update the table in the same change; tell the user to `/reload` if pi is
|
|
236
|
+
already running.
|
|
237
|
+
|
|
238
|
+
## Testing checklist
|
|
239
|
+
|
|
240
|
+
For each generated skill:
|
|
241
|
+
|
|
242
|
+
1. `/dc-run skills/<handbook_slug>/<slug>.dml "<request>" --context=isolated --debug`
|
|
243
|
+
— runs clean; verification (if any) passes or the fallback explains.
|
|
244
|
+
2. Inspect phase is read-only, action phase is write-only, and a forbidden
|
|
245
|
+
action has no tool at all.
|
|
246
|
+
3. Deterministic code is limited to arithmetic/counts; every deterministic
|
|
247
|
+
check has an LLM fallback branch.
|
|
248
|
+
4. The tool audit was done and its result is recorded in the header/INDEX.
|
|
249
|
+
5. Re-check the invalid-pattern table in `.pi/deepclause/AGENTS.md` (singleton
|
|
250
|
+
variables, `~` vs `{}` interpolation, `Result.field` vs `get_dict/3`, `->`
|
|
251
|
+
committing over generators, `answer/1` last, `:- dynamic` before
|
|
252
|
+
`assertz/retract`).
|
|
253
|
+
|
|
254
|
+
`--context=isolated` keeps session text out of the run. The runtime still needs
|
|
255
|
+
a model selected.
|
|
256
|
+
|
|
257
|
+
## Reference shape
|
|
258
|
+
|
|
259
|
+
A typical procedure skill has: `agent_main(Request)` that parses the request
|
|
260
|
+
with `task/N`, confirms with the user via a `user_feedback` tool loop, acts
|
|
261
|
+
through write tools, and reviews with `prompt/N` — with small deterministic
|
|
262
|
+
helpers for arithmetic and a fallback branch instead of hard failures.
|
|
263
|
+
|
|
264
|
+
For DML mechanics, see the bundled example skills in a fresh workspace
|
|
265
|
+
(`example.dml`, `deep_research.dml`) and `.pi/deepclause/AGENTS.md`.
|