deepclause-pi 0.4.0 → 0.5.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.
- package/README.md +4 -4
- package/dist/diagram/extract.d.ts +2 -0
- package/dist/diagram/extract.js +223 -3
- package/dist/diagram/grade.d.ts +1 -1
- package/dist/diagram/grade.js +4 -4
- package/dist/index.d.ts +9 -0
- package/dist/index.js +103 -81
- package/package.json +1 -1
- package/skills/handbook-dml/SKILL.md +174 -46
- package/src/assets/AGENTS.md +43 -7
- package/src/diagram/extract.ts +225 -3
- package/src/diagram/grade.ts +4 -4
- package/src/index.ts +120 -92
package/README.md
CHANGED
|
@@ -155,15 +155,15 @@ Give me a specification-grade diagram of src/report.dml
|
|
|
155
155
|
|
|
156
156
|
Pi calls the always-active `dc_diagram` model tool, which:
|
|
157
157
|
|
|
158
|
-
1. extracts a deterministic Mermaid seed from the DML in-process,
|
|
159
|
-
2. has the active pi model rewrite it in the requested grade,
|
|
158
|
+
1. extracts a deterministic Mermaid seed from the DML in-process (the specification seed adds a `LOGIC` section for decision predicates and a `RULES` section for fact tables),
|
|
159
|
+
2. has the active pi model rewrite it in the requested grade, preserving the seed's conditions, thresholds and outcomes,
|
|
160
160
|
3. validates each attempt (structural checks, plus the real Mermaid parser when Chrome is available),
|
|
161
161
|
4. writes the sidecar under `.pi/deepclause/diagrams/`, rebuilds the self-contained offline `viewer.html`, and opens it.
|
|
162
162
|
|
|
163
163
|
Grades:
|
|
164
164
|
|
|
165
|
-
- **presentation** — about 8-12 nodes, plain language, headline numbers; for slides and overviews.
|
|
166
|
-
- **specification** — function names, task/tool roles, post-conditions; for engineers.
|
|
165
|
+
- **presentation** — about 8-12 nodes, plain language, headline numbers and the headline decision; for slides and overviews.
|
|
166
|
+
- **specification** — function names, task/tool roles, post-conditions, plus the core decision logic: each decision predicate with its conditions, thresholds and outcomes, and the rule fact tables; for engineers.
|
|
167
167
|
|
|
168
168
|
Selecting `both` produces both sidecars. The DML source may be anywhere (workspace-relative or absolute); only the generated viewer is confined to `.pi/deepclause/`. `dc_diagram` never executes the DML and needs no shell approval. Regenerating a grade replaces only that grade's sidecar (`<name>.presentation.mmd` / `<name>.specification.mmd`). The Mermaid bundle is vendored so the viewer works offline.
|
|
169
169
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export interface RenderOptions {
|
|
2
2
|
hideOutput?: boolean;
|
|
3
|
+
/** Include core decision-logic blocks and rule facts. Defaults to true. */
|
|
4
|
+
includeLogic?: boolean;
|
|
3
5
|
}
|
|
4
6
|
export declare function renderDml(file: string, src: string, opts?: RenderOptions): string;
|
|
5
7
|
export declare function renderSequence(file: string, src: string): string;
|
package/dist/diagram/extract.js
CHANGED
|
@@ -325,7 +325,7 @@ function extractClauses(src) {
|
|
|
325
325
|
depth++;
|
|
326
326
|
else if (")]}".includes(c))
|
|
327
327
|
depth--;
|
|
328
|
-
else if (c === "." && depth === 0 && /\s
|
|
328
|
+
else if (c === "." && depth === 0 && (b + 1 >= src.length || /\s/.test(src.charAt(b + 1))))
|
|
329
329
|
break;
|
|
330
330
|
}
|
|
331
331
|
if (!clauses.has(name))
|
|
@@ -376,6 +376,158 @@ function agenticPredicates(clauses) {
|
|
|
376
376
|
visit(n, new Set());
|
|
377
377
|
return agentic;
|
|
378
378
|
}
|
|
379
|
+
// ---------- core logic extraction --------------------------------------------
|
|
380
|
+
const JUDGE_PREDICATES = new Set([
|
|
381
|
+
"judge", "choose", "rate", "verify", "probability", "holds", "with_judgment", "require_judgment",
|
|
382
|
+
]);
|
|
383
|
+
const MECHANICAL_HELPERS = new Set([
|
|
384
|
+
"dget", "get_dict", "num", "to_num", "present", "lower", "lower_string", "upper",
|
|
385
|
+
"state_text", "norm_sign", "as_list", "truthy", "falsy", "format", "trunc", "basename",
|
|
386
|
+
]);
|
|
387
|
+
const DECISION_RE = /(?:>=|=<|<|>|=:=|\bis\b|\bbetween\b|\bmod\b|\\\+)/;
|
|
388
|
+
const AGGREGATE_RE = /\b(findall|forall|setof|bagof|aggregate_all|maplist)\b/;
|
|
389
|
+
/** All `name(` tokens in a clause body, with strings and chars removed. */
|
|
390
|
+
function headNamesIn(text) {
|
|
391
|
+
const bare = text
|
|
392
|
+
.replace(/"(?:[^"\\]|\\.)*"/g, '""')
|
|
393
|
+
.replace(/'(?:[^'\\]|\\.)*'/g, "''");
|
|
394
|
+
const names = [];
|
|
395
|
+
for (const m of bare.matchAll(/([a-z][a-zA-Z0-9_]*)\s*\(/g)) {
|
|
396
|
+
if (m[1])
|
|
397
|
+
names.push(m[1]);
|
|
398
|
+
}
|
|
399
|
+
return names;
|
|
400
|
+
}
|
|
401
|
+
function predicateArity(clauses) {
|
|
402
|
+
return splitTop(clauses[0]?.args ?? "", ",").filter(Boolean).length;
|
|
403
|
+
}
|
|
404
|
+
function isFactClauses(clauses) {
|
|
405
|
+
return clauses.every((clause) => !clause.body.trim());
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* A predicate carries core logic when it branches, applies thresholds or
|
|
409
|
+
* generators, or consults a semantic judgment. Mechanical plumbing helpers are
|
|
410
|
+
* excluded so the logic section stays about decisions, not string handling.
|
|
411
|
+
*/
|
|
412
|
+
function isDecisionPredicate(name, clauses) {
|
|
413
|
+
if (MECHANICAL_HELPERS.has(name))
|
|
414
|
+
return false;
|
|
415
|
+
if (clauses.length > 1)
|
|
416
|
+
return true;
|
|
417
|
+
const body = clauses[0]?.body ?? "";
|
|
418
|
+
if (!body.trim())
|
|
419
|
+
return false;
|
|
420
|
+
if (DECISION_RE.test(body))
|
|
421
|
+
return true;
|
|
422
|
+
if (AGGREGATE_RE.test(body))
|
|
423
|
+
return true;
|
|
424
|
+
for (const h of headNamesIn(body))
|
|
425
|
+
if (JUDGE_PREDICATES.has(h))
|
|
426
|
+
return true;
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
const escLabel = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, "'");
|
|
430
|
+
/** Join the summaries of a conjunction/disjunction into one readable line. */
|
|
431
|
+
function summarizeBody(text, max = 96) {
|
|
432
|
+
const parts = splitGoals(text)
|
|
433
|
+
.map(({ goal }) => summarizeGoal(goal, max))
|
|
434
|
+
.filter(Boolean);
|
|
435
|
+
return [...new Set(parts)].slice(-2).join("; ");
|
|
436
|
+
}
|
|
437
|
+
/** One short, readable line for a single body goal. */
|
|
438
|
+
function summarizeGoal(goal, max = 96) {
|
|
439
|
+
const g = stripOuterParens(goal).trim();
|
|
440
|
+
if (!g)
|
|
441
|
+
return "";
|
|
442
|
+
const br = parseArrow(g);
|
|
443
|
+
if (br) {
|
|
444
|
+
const then = summarizeBody(br.then, Math.max(24, max - 12));
|
|
445
|
+
const otherwise = br.else.trim() ? summarizeBody(br.else, Math.max(24, max - 12)) : "";
|
|
446
|
+
return `if ${trunc(br.cond.replace(/\s+/g, " "), max)} -> ${then || "…"}${otherwise ? ` ; else: ${otherwise}` : ""}`;
|
|
447
|
+
}
|
|
448
|
+
return summarizeSingle(g, max);
|
|
449
|
+
}
|
|
450
|
+
function summarizeSingle(g, max) {
|
|
451
|
+
const h = headName(g);
|
|
452
|
+
if (!h)
|
|
453
|
+
return trunc(g.replace(/\s+/g, " "), max);
|
|
454
|
+
if (["format", "write", "print", "output", "answer"].includes(h)) {
|
|
455
|
+
const s = firstString(g);
|
|
456
|
+
if (!s)
|
|
457
|
+
return `${h}(...)`;
|
|
458
|
+
const decision = /(?:decision|answer|verdict|conclusion):.*/i.exec(s);
|
|
459
|
+
return trunc(decision ? decision[0] : s, Math.max(max, 120));
|
|
460
|
+
}
|
|
461
|
+
if (JUDGE_PREDICATES.has(h)) {
|
|
462
|
+
const label = h === "require_judgment" ? "require calibrated" : h;
|
|
463
|
+
const s = firstString(g);
|
|
464
|
+
return s ? `${label}: ${trunc(s, Math.max(16, max - label.length - 2))}` : `${label}(...)`;
|
|
465
|
+
}
|
|
466
|
+
if (["findall", "forall", "setof", "bagof", "aggregate_all"].includes(h))
|
|
467
|
+
return `${h}(...)`;
|
|
468
|
+
const args = () => splitTop(g.slice(g.indexOf("(") + 1, g.lastIndexOf(")")), ",").map((p) => p.trim());
|
|
469
|
+
if (h === "get_dict")
|
|
470
|
+
return args()[0] || "get_dict";
|
|
471
|
+
if (h === "dget" || h === "num" || h === "to_num")
|
|
472
|
+
return args()[1] || h;
|
|
473
|
+
const inside = g.slice(g.indexOf("(") + 1, g.lastIndexOf(")")).replace(/\s+/g, " ").trim();
|
|
474
|
+
return inside ? `${h}(${trunc(inside, Math.max(12, max - h.length - 3))})` : h;
|
|
475
|
+
}
|
|
476
|
+
/** Render one clause as an escaped `<br/>`-joined list of its meaningful goals. */
|
|
477
|
+
function describeClause(clause) {
|
|
478
|
+
if (!clause.body.trim())
|
|
479
|
+
return escLabel(trunc(clause.args.replace(/\s+/g, " "), 80));
|
|
480
|
+
const seen = new Set();
|
|
481
|
+
const lines = [];
|
|
482
|
+
for (const { goal } of splitGoals(clause.body)) {
|
|
483
|
+
const line = summarizeGoal(goal);
|
|
484
|
+
if (!line)
|
|
485
|
+
continue;
|
|
486
|
+
const escaped = escLabel(line);
|
|
487
|
+
if (seen.has(escaped))
|
|
488
|
+
continue;
|
|
489
|
+
seen.add(escaped);
|
|
490
|
+
lines.push(escaped);
|
|
491
|
+
}
|
|
492
|
+
return lines.join("<br/>");
|
|
493
|
+
}
|
|
494
|
+
function factSummary(name, clauses) {
|
|
495
|
+
const sample = clauses
|
|
496
|
+
.slice(0, 6)
|
|
497
|
+
.map((clause) => escLabel(trunc(clause.args.replace(/\s+/g, " "), 32)))
|
|
498
|
+
.join(" · ");
|
|
499
|
+
return `${name}/${predicateArity(clauses)} — ${clauses.length} facts: ${sample}${clauses.length > 6 ? " …" : ""}`;
|
|
500
|
+
}
|
|
501
|
+
/** Transitive closure of decision predicates and fact tables reachable from the flow. */
|
|
502
|
+
function collectLogic(clauses, roots) {
|
|
503
|
+
const logic = new Map();
|
|
504
|
+
const facts = new Map();
|
|
505
|
+
const seen = new Set();
|
|
506
|
+
const visit = (name) => {
|
|
507
|
+
if (seen.has(name))
|
|
508
|
+
return;
|
|
509
|
+
seen.add(name);
|
|
510
|
+
const bodies = clauses.get(name);
|
|
511
|
+
if (!bodies)
|
|
512
|
+
return;
|
|
513
|
+
if (isFactClauses(bodies)) {
|
|
514
|
+
if (bodies.length >= 2)
|
|
515
|
+
facts.set(name, bodies);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
if (isDecisionPredicate(name, bodies))
|
|
519
|
+
logic.set(name, bodies);
|
|
520
|
+
for (const clause of bodies) {
|
|
521
|
+
for (const inner of headNamesIn(clause.body)) {
|
|
522
|
+
if (inner !== name && clauses.has(inner) && !BUILTIN.has(inner))
|
|
523
|
+
visit(inner);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
for (const root of roots)
|
|
528
|
+
visit(root);
|
|
529
|
+
return { logic, facts };
|
|
530
|
+
}
|
|
379
531
|
// ---------- rendering --------------------------------------------------------
|
|
380
532
|
function parseArrow(goal) {
|
|
381
533
|
const t = stripOuterParens(goal);
|
|
@@ -461,6 +613,9 @@ export function renderDml(file, src, opts = {}) {
|
|
|
461
613
|
stack: [],
|
|
462
614
|
sawAnswer: false,
|
|
463
615
|
phaseOpen: false,
|
|
616
|
+
includeLogic: opts.includeLogic !== false,
|
|
617
|
+
logicNodes: new Map(),
|
|
618
|
+
factRefs: new Set(),
|
|
464
619
|
};
|
|
465
620
|
const nid = () => `n${++state.n}`;
|
|
466
621
|
const node = (shape, label, klass) => {
|
|
@@ -469,6 +624,24 @@ export function renderDml(file, src, opts = {}) {
|
|
|
469
624
|
return id;
|
|
470
625
|
};
|
|
471
626
|
const edge = (a, b, label) => state.lines.push(` ${a} ${label ? `-->|${label}|` : "-->"} ${b}`);
|
|
627
|
+
/** Record user predicates referenced by a condition so their logic still gets a block. */
|
|
628
|
+
const registerLogicRefs = (text, nodeId) => {
|
|
629
|
+
for (const name of headNamesIn(text)) {
|
|
630
|
+
const bodies = clauses.get(name);
|
|
631
|
+
if (!bodies || BUILTIN.has(name) || name === "agent_main")
|
|
632
|
+
continue;
|
|
633
|
+
if (isFactClauses(bodies)) {
|
|
634
|
+
if (bodies.length >= 2)
|
|
635
|
+
state.factRefs.add(name);
|
|
636
|
+
continue;
|
|
637
|
+
}
|
|
638
|
+
if (agentic.has(name))
|
|
639
|
+
continue;
|
|
640
|
+
const referenced = state.logicNodes.get(name) ?? [];
|
|
641
|
+
referenced.push(nodeId);
|
|
642
|
+
state.logicNodes.set(name, referenced);
|
|
643
|
+
}
|
|
644
|
+
};
|
|
472
645
|
function renderGoals(goals, ctx = "", topLevel = false) {
|
|
473
646
|
let entry = null;
|
|
474
647
|
let exit = null;
|
|
@@ -506,6 +679,8 @@ export function renderDml(file, src, opts = {}) {
|
|
|
506
679
|
const br = parseArrow(goal);
|
|
507
680
|
if (br) {
|
|
508
681
|
const d = node(["{", "}"], `if ${trunc(br.cond, 46)}`, "det");
|
|
682
|
+
if (state.includeLogic)
|
|
683
|
+
registerLogicRefs(br.cond, d);
|
|
509
684
|
const t = renderGoals(splitGoals(br.then), ctx);
|
|
510
685
|
const e = br.else.trim() ? renderGoals(splitGoals(br.else), ctx) : null;
|
|
511
686
|
const merge = nid();
|
|
@@ -546,15 +721,25 @@ export function renderDml(file, src, opts = {}) {
|
|
|
546
721
|
if (h && clauses.has(h)) {
|
|
547
722
|
const bodies = clauses.get(h);
|
|
548
723
|
const isFact = bodies.every((c) => !c.body.trim());
|
|
549
|
-
if (isFact)
|
|
724
|
+
if (isFact) {
|
|
725
|
+
if (bodies.length >= 2)
|
|
726
|
+
state.factRefs.add(h);
|
|
550
727
|
return null;
|
|
728
|
+
}
|
|
551
729
|
if (agentic.has(h) && !state.stack.includes(h)) {
|
|
552
730
|
state.stack.push(h);
|
|
553
731
|
const seg = renderGoals(splitGoals(bodies[0]?.body ?? ""), h);
|
|
554
732
|
state.stack.pop();
|
|
555
733
|
return seg.entry ? seg : null;
|
|
556
734
|
}
|
|
557
|
-
|
|
735
|
+
const label = state.includeLogic ? `${h}/${predicateArity(bodies)}` : `${h}()`;
|
|
736
|
+
const id = node(["[[", "]]"], label, "det");
|
|
737
|
+
if (state.includeLogic) {
|
|
738
|
+
const referenced = state.logicNodes.get(h) ?? [];
|
|
739
|
+
referenced.push(id);
|
|
740
|
+
state.logicNodes.set(h, referenced);
|
|
741
|
+
}
|
|
742
|
+
return { entry: id, exit: null };
|
|
558
743
|
}
|
|
559
744
|
return null;
|
|
560
745
|
}
|
|
@@ -579,6 +764,41 @@ export function renderDml(file, src, opts = {}) {
|
|
|
579
764
|
tools.forEach((t, i) => state.lines.push(` tool${i}[["${t.name}(${trunc(t.args, 26)})"]]:::tool`));
|
|
580
765
|
state.lines.push(" end");
|
|
581
766
|
}
|
|
767
|
+
if (state.includeLogic) {
|
|
768
|
+
const { logic, facts } = collectLogic(clauses, [...state.logicNodes.keys(), ...state.factRefs]);
|
|
769
|
+
if (logic.size || facts.size) {
|
|
770
|
+
const edges = [];
|
|
771
|
+
if (logic.size) {
|
|
772
|
+
state.lines.push(' subgraph LOGIC["core decision logic"]');
|
|
773
|
+
state.lines.push(" direction TB");
|
|
774
|
+
let index = 0;
|
|
775
|
+
for (const [name, bodies] of logic) {
|
|
776
|
+
const sg = `lg${++index}`;
|
|
777
|
+
state.lines.push(` subgraph ${sg}["${name}/${predicateArity(bodies)}"]`);
|
|
778
|
+
state.lines.push(" direction TB");
|
|
779
|
+
bodies.forEach((clause, ci) => {
|
|
780
|
+
const description = describeClause(clause) || "(clause)";
|
|
781
|
+
state.lines.push(` ${sg}c${ci}["${ci + 1}) ${description}"]:::det`);
|
|
782
|
+
});
|
|
783
|
+
state.lines.push(" end");
|
|
784
|
+
for (const nodeId of state.logicNodes.get(name) ?? []) {
|
|
785
|
+
edges.push(` ${nodeId} -.->|"core logic"| ${sg}`);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
state.lines.push(" end");
|
|
789
|
+
}
|
|
790
|
+
if (facts.size) {
|
|
791
|
+
state.lines.push(' subgraph RULES["rule facts"]');
|
|
792
|
+
state.lines.push(" direction LR");
|
|
793
|
+
let index = 0;
|
|
794
|
+
for (const [name, bodies] of facts) {
|
|
795
|
+
state.lines.push(` rf${++index}["${factSummary(name, bodies)}"]:::det`);
|
|
796
|
+
}
|
|
797
|
+
state.lines.push(" end");
|
|
798
|
+
}
|
|
799
|
+
state.lines.push(...edges);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
582
802
|
state.lines.push(" classDef start fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px;", " classDef terminal fill:#e3f2fd,stroke:#1565c0;", " classDef llm fill:#fff8e1,stroke:#f9a825,stroke-width:2px;", " classDef det fill:#eceff1,stroke:#546e7a;", " classDef host fill:#f3e5f5,stroke:#6a1b9a;", " classDef out fill:#fafafa,stroke:#bdbdbd;", " classDef tool fill:#ede7f6,stroke:#4527a0;");
|
|
583
803
|
return state.lines.join("\n");
|
|
584
804
|
}
|
package/dist/diagram/grade.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CheckResult, MermaidView } from "./validate.js";
|
|
2
2
|
export type DiagramGrade = "presentation" | "specification";
|
|
3
3
|
export type RequestedGrade = DiagramGrade | "both";
|
|
4
|
-
export declare const GRADE_SYSTEM_PROMPT = "You are a meticulous Mermaid v11 diagram editor. You output only valid Mermaid source, never wrapped in code fences, and you keep all facts accurate.";
|
|
4
|
+
export declare const GRADE_SYSTEM_PROMPT = "You are a meticulous Mermaid v11 diagram editor. You output only valid Mermaid source, never wrapped in code fences, and you keep all facts and decision logic accurate. Never invent or drop a rule, threshold, or outcome.";
|
|
5
5
|
export declare const GRADE_PROMPTS: Record<DiagramGrade, string>;
|
|
6
6
|
/**
|
|
7
7
|
* Map free-form user/tool wording onto a supported grade. Returns undefined when
|
package/dist/diagram/grade.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export const GRADE_SYSTEM_PROMPT = "You are a meticulous Mermaid v11 diagram editor. You output only valid Mermaid source, never wrapped in code fences, and you keep all facts accurate.";
|
|
1
|
+
export const GRADE_SYSTEM_PROMPT = "You are a meticulous Mermaid v11 diagram editor. You output only valid Mermaid source, never wrapped in code fences, and you keep all facts and decision logic accurate. Never invent or drop a rule, threshold, or outcome.";
|
|
2
2
|
export const GRADE_PROMPTS = {
|
|
3
|
-
presentation: "Produce a PRESENTATION-GRADE version: about 8-12 nodes, plain non-technical language, NO function names or framework jargon, highlight the headline numbers and the
|
|
4
|
-
specification: "Produce a SPECIFICATION-GRADE (detailed engineering) version: keep the technical detail (function names, task/tool roles, post-conditions, seed data), but
|
|
3
|
+
presentation: "Produce a PRESENTATION-GRADE version: about 8-12 nodes, plain non-technical language, NO function names or framework jargon, highlight the headline numbers, the main steps and the headline decision, and add 1-2 short callouts. Keep it accurate but simple enough for a general audience; you may compress the detailed logic but must not change the final decision or omit a rule that flips it.",
|
|
4
|
+
specification: "Produce a SPECIFICATION-GRADE (detailed engineering) version: keep the technical detail (function names, task/tool roles, post-conditions, seed data) AND the domain decision logic. Preserve the decision predicates from the seed's `LOGIC` section — each with its exact conditions, thresholds and outcomes — and every `RULES` fact table. You may group or collapse pure arithmetic, date and formatting helpers, but never drop or alter a domain rule, threshold or outcome. Expand each retained logic block from the DML source. Improve labels, grouping and readability so an engineer can trace every domain decision precisely.",
|
|
5
5
|
};
|
|
6
6
|
/**
|
|
7
7
|
* Map free-form user/tool wording onto a supported grade. Returns undefined when
|
|
@@ -29,7 +29,7 @@ function buildPrompt(grade, view, source, seed, feedback) {
|
|
|
29
29
|
return [
|
|
30
30
|
GRADE_PROMPTS[grade],
|
|
31
31
|
"",
|
|
32
|
-
`Rules: output ONLY Mermaid v11 source (no code fences); keep it a '${syntax}' diagram; keep the facts accurate; do not use reserved words such as 'end' as node ids or class names.`,
|
|
32
|
+
`Rules: output ONLY Mermaid v11 source (no code fences); keep it a '${syntax}' diagram; keep the facts and decision logic accurate; preserve the seed's domain LOGIC blocks (conditions, thresholds, outcomes) and RULES facts instead of collapsing them into generic nodes, while grouping pure arithmetic/date/format helpers; do not use reserved words such as 'end' as node ids or class names.`,
|
|
33
33
|
"",
|
|
34
34
|
"DML source:",
|
|
35
35
|
source,
|
package/dist/index.d.ts
CHANGED
|
@@ -23,5 +23,14 @@ export declare function parsePlan(input: string): ParsedPlan;
|
|
|
23
23
|
* A clean tree is what lets the next /dc-apply take a rollback snapshot.
|
|
24
24
|
*/
|
|
25
25
|
export declare function offerCommit(pi: ExtensionAPI, ctx: ExtensionContext, action: string, change: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Ask the user a DeepClause question.
|
|
28
|
+
*
|
|
29
|
+
* Pi's interactive text-input dialog renders only its title: the placeholder
|
|
30
|
+
* argument is ignored by `ExtensionInputComponent`. Passing the question as the
|
|
31
|
+
* placeholder (as the extension used to) made it invisible, so put the whole
|
|
32
|
+
* question in the title and label which run is asking.
|
|
33
|
+
*/
|
|
34
|
+
export declare function requestDeepClauseInput(ctx: Pick<ExtensionContext, "ui">, label: string, prompt: string, signal: AbortSignal): Promise<string | undefined>;
|
|
26
35
|
export default function deepClauseExtension(pi: ExtensionAPI): void;
|
|
27
36
|
export {};
|