@widnyana/design-thinking 0.0.3 → 0.0.6

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
@@ -61,6 +61,7 @@ pi -e ./pi-packages/design-thinking
61
61
  |---|---|
62
62
  | `/dt` | Toggle Design Thinking mode. While on, plans and reviews render as Design Graphs. Persists across restarts. |
63
63
  | `/dt on\|off\|status` | Set or query the mode explicitly. |
64
+ | `/dt approve\|deny` | Arm/revoke file edits for the next agent run — run `approve` after a presented graph to let the implementation run edit, `deny` to re-lock. |
64
65
  | `/dt <prompt>` | Turn the mode **on** (never off), then run `<prompt>` under it — graph and clarifying questions first, implementation after your go-ahead. |
65
66
  | `/cg <module \| task>` | Generate a call graph: extract the graph existing code implements, or sketch one for a task. |
66
67
  | `/cg-plan <task>` | Design before code — full Design Graph, then implement to match it. |
@@ -15,6 +15,7 @@
15
15
  * /dt toggle Design Thinking mode
16
16
  * /dt on|off set explicitly
17
17
  * /dt status show current state
18
+ * /dt approve|deny arm/revoke file edits for the next agent run
18
19
  * /dt <prompt> turn mode ON (never off), then run <prompt> as a user
19
20
  * message — graph + clarifying questions before implementation
20
21
  *
@@ -42,7 +43,7 @@ const REF_DIR = path.resolve(
42
43
  "references",
43
44
  );
44
45
 
45
- /** Compact distilled prompt block injected while active (~33 lines). */
46
+ /** Compact distilled prompt block injected while active. */
46
47
  const DISTILLED = `
47
48
  DESIGN THINKING MODE — active.
48
49
  Read the problem. Draw the data flow as a call graph. Write code that IS the graph.
@@ -65,7 +66,9 @@ Rules:
65
66
  refactor — the model does NOT get to reclassify the request): render the
66
67
  Design Graph in Graph Protocol form and any clarifying questions FIRST;
67
68
  ZERO file edits until the user approves the design. Reading/exploring code
68
- first is fine; the FIRST edit is not allowed before the graph.
69
+ first is fine; the FIRST edit is not allowed before the graph. Once the
70
+ user runs /dt approve, edits are armed for the NEXT run: implement the
71
+ approved design without re-presenting the graph.
69
72
  - Design, plan, and review answers must render a Design Graph — fixed
70
73
  sections: PROBLEM, SHAPES, GRAPH, CARDINALITY, BOUNDARIES, BEHAVIOR, SCOPE,
71
74
  TEST LAYERS, VERDICT.
@@ -82,15 +85,32 @@ Skills load BY NAME into the agent (/skill:<name>); the files above are named
82
85
  by stem, NOT by skill name. Exact mapping:
83
86
  /skill:graph-protocol → protocol.md /skill:design-method → method.md
84
87
  /skill:design-graph → design-graph.md
88
+ The extension blocks write/edit tools mechanically until the user runs
89
+ /dt approve — it arms the NEXT run, cleared when that run ends. Re-approve
90
+ per implementation round. Present the graph first.
85
91
  NEVER read references/<skill-name>.md — no such files exist.
86
92
  `.trim();
87
93
 
94
+ // pi's file-edit tools — the mechanical gate's scope ("file edits"). Bash
95
+ // stays open for read-only exploration. apply_patch/multiedit are Claude Code
96
+ // tool names that never fire in pi; keep this list to real pi mutators.
97
+ const MUTATING_TOOLS: Record<string, true> = {
98
+ write: true,
99
+ edit: true,
100
+ };
101
+
88
102
  interface DtState {
89
103
  enabled: boolean;
90
104
  }
91
105
 
106
+ const GATE_REASON =
107
+ "Design Thinking mode is ON: present the Design Graph (Graph Protocol) and wait for user approval before file edits. The user arms the NEXT run with /dt approve; the approval clears when that run ends.";
108
+
92
109
  export default function designThinkingExtension(pi: ExtensionAPI) {
93
110
  let enabled = false;
111
+ // Armed by /dt approve for the NEXT agent run. Cleared when that run ends
112
+ // (agent_end), by /dt deny, or when the mode turns off. Not persisted.
113
+ let editsApproved = false;
94
114
 
95
115
  function applyStatus(ctx: ExtensionContext) {
96
116
  ctx.ui.setStatus(
@@ -129,15 +149,35 @@ export default function designThinkingExtension(pi: ExtensionAPI) {
129
149
  ctx.ui.setStatus("design-thinking", undefined);
130
150
  });
131
151
 
132
- // /dt — the Design Thinking tool. Toggles mode, or /dt on|off|status.
152
+ // /dt — the Design Thinking tool. Toggles mode; on|off|status set/query;
153
+ // approve|deny arm/revoke file edits; anything else runs as a prompt with mode on.
133
154
  pi.registerCommand("dt", {
134
- description: "Design Thinking mode: /dt toggles, on|off|status set/query, anything else runs as a prompt with mode on",
155
+ description: "Design Thinking mode: /dt toggles, on|off|status set/query, approve arms the next run for file edits, deny revokes; anything else runs as a prompt with mode on",
135
156
  handler: async (args, ctx) => {
136
157
  const arg = (args ?? "").trim();
137
158
  const lower = arg.toLowerCase();
138
159
 
139
160
  if (lower === "status") {
140
- ctx.ui.notify(`Design Thinking mode: ${enabled ? "on" : "off"}`, "info");
161
+ ctx.ui.notify(`Design Thinking mode: ${enabled ? "on" : "off"}${editsApproved ? " (file edits armed for the next run)" : ""}`, "info");
162
+ return;
163
+ }
164
+
165
+ if (lower === "approve") {
166
+ if (!enabled) {
167
+ ctx.ui.notify("Design Thinking is OFF — nothing to approve. Run /dt on first.", "info");
168
+ return;
169
+ }
170
+ editsApproved = true;
171
+ ctx.ui.notify("Design Thinking: file edits armed (current or next run) — it may implement the approved design without re-presenting the graph", "info");
172
+ return;
173
+ }
174
+ if (lower === "deny") {
175
+ if (!editsApproved) {
176
+ ctx.ui.notify("Design Thinking: no approval in effect — file edits are already blocked", "info");
177
+ return;
178
+ }
179
+ editsApproved = false;
180
+ ctx.ui.notify("Design Thinking: file edits blocked again", "info");
141
181
  return;
142
182
  }
143
183
 
@@ -145,6 +185,7 @@ export default function designThinkingExtension(pi: ExtensionAPI) {
145
185
  // mode and always turns the mode ON (never toggles it off); bare /dt toggles.
146
186
  const prompt = /^(on|off|status)$/.test(lower) ? "" : arg;
147
187
  enabled = lower === "on" || prompt ? true : lower === "off" ? false : !enabled;
188
+ if (!enabled) editsApproved = false;
148
189
  persist();
149
190
  applyStatus(ctx);
150
191
  ctx.ui.notify(
@@ -164,11 +205,26 @@ export default function designThinkingExtension(pi: ExtensionAPI) {
164
205
  },
165
206
  });
166
207
 
167
- // While active, append the distilled block to the system prompt every turn.
208
+ // While active, append the distilled block to the system prompt every run.
168
209
  pi.on("before_agent_start", async (event) => {
169
210
  if (!enabled) return undefined;
170
211
  return {
171
212
  systemPrompt: event.systemPrompt + "\n\n" + DISTILLED + "\n",
172
213
  };
173
214
  });
215
+
216
+ // An approved run consumes the approval: clear it when the run ends so
217
+ // later runs are gated again until the user re-approves with /dt approve.
218
+ pi.on("agent_end", async () => {
219
+ editsApproved = false;
220
+ });
221
+
222
+ // Hard gate: while enabled, file-edit tools are blocked until the user
223
+ // arms the next run with /dt approve. Prompt-level rules alone proved
224
+ // insufficient — this is the mechanical backstop.
225
+ pi.on("tool_call", async (event) => {
226
+ if (!enabled || editsApproved) return undefined;
227
+ if (!MUTATING_TOOLS[event.toolName]) return undefined;
228
+ return { block: true, reason: GATE_REASON };
229
+ });
174
230
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@widnyana/design-thinking",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "type": "module",
5
5
  "description": "Design Thinking · Design Graph · Graph Protocol — a stack-agnostic design methodology for pi. Turns every plan, review, and refactor into an annotated call graph. Method originally by r17x; generalized to a pi package by widnyana.",
6
6
  "author": {
@@ -35,8 +35,11 @@
35
35
  "methodology",
36
36
  "call-graph"
37
37
  ],
38
+ "omp": {
39
+ "extensions": ["./extensions/design-thinking.ts"]
40
+ },
38
41
  "pi": {
39
- "extensions": ["./extensions"],
42
+ "extensions": ["./extensions/design-thinking.ts"],
40
43
  "prompts": ["./prompts"],
41
44
  "skills": ["./skills"]
42
45
  },
@@ -11,8 +11,8 @@ description: >
11
11
  # Design Graph — The Artifact
12
12
 
13
13
  A **Design Graph** is the annotated call graph of a concrete problem. It is
14
- what you produce when you apply [Design Thinking](/skill:design-method) to
15
- something, and it is written in [Graph Protocol](/skill:graph-protocol) notation.
14
+ what you produce when you apply Design Thinking (see the `design-method` skill) to
15
+ something, and it is written in Graph Protocol notation (see the `graph-protocol` skill).
16
16
 
17
17
  Nodes are functions. Edges are data flow. The annotations answer, for every
18
18
  node: what flows through it (A), how many times it runs (cardinality), where
@@ -97,5 +97,5 @@ VERDICT line.
97
97
 
98
98
  ## Worked example
99
99
 
100
- See the end of [Graph Protocol](/skill:graph-protocol) for a complete, non-TS worked
100
+ See the end of the `graph-protocol` skill for a complete, non-TS worked
101
101
  example (a resumable URL-sync CLI in Python) with all sections filled.
@@ -25,7 +25,7 @@ implement only after the user approves the design. Reading and exploring code
25
25
  first is fine; the FIRST edit is not allowed before the graph. This rule is
26
26
  not optional and not stack-dependent.
27
27
 
28
- Render every result in [Graph Protocol](/skill:graph-protocol) format.
28
+ Render every result in Graph Protocol format (see the `graph-protocol` skill).
29
29
 
30
30
  ```
31
31
  X → DesignGraph<A, E, R>