@yycholla/pi-dynamic-workflows 3.3.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/LICENSE +22 -0
- package/README.md +325 -0
- package/assets/readme/hero.png +0 -0
- package/assets/readme/hero.svg +70 -0
- package/assets/readme/package-cover.png +0 -0
- package/assets/readme/package-cover.svg +66 -0
- package/assets/readme/workflow.png +0 -0
- package/assets/readme/workflow.svg +77 -0
- package/dist/accept-workflow-guidance.d.ts +14 -0
- package/dist/accept-workflow-guidance.js +53 -0
- package/dist/adversarial-review.d.ts +30 -0
- package/dist/adversarial-review.js +107 -0
- package/dist/agent-history.d.ts +20 -0
- package/dist/agent-history.js +122 -0
- package/dist/agent-registry.d.ts +83 -0
- package/dist/agent-registry.js +190 -0
- package/dist/agent.d.ts +364 -0
- package/dist/agent.js +714 -0
- package/dist/builtin-commands.d.ts +19 -0
- package/dist/builtin-commands.js +251 -0
- package/dist/builtin-workflows.d.ts +45 -0
- package/dist/builtin-workflows.js +121 -0
- package/dist/code-review.d.ts +26 -0
- package/dist/code-review.js +181 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.js +44 -0
- package/dist/deep-research.d.ts +30 -0
- package/dist/deep-research.js +124 -0
- package/dist/display.d.ts +134 -0
- package/dist/display.js +248 -0
- package/dist/effort-command.d.ts +28 -0
- package/dist/effort-command.js +68 -0
- package/dist/enums.d.ts +69 -0
- package/dist/enums.js +78 -0
- package/dist/errors.d.ts +113 -0
- package/dist/errors.js +140 -0
- package/dist/extension-reload.d.ts +37 -0
- package/dist/extension-reload.js +78 -0
- package/dist/fs-persistence.d.ts +63 -0
- package/dist/fs-persistence.js +102 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +35 -0
- package/dist/logger.d.ts +21 -0
- package/dist/logger.js +66 -0
- package/dist/model-routing.d.ts +30 -0
- package/dist/model-routing.js +50 -0
- package/dist/model-spec.d.ts +29 -0
- package/dist/model-spec.js +252 -0
- package/dist/model-tier-config.d.ts +133 -0
- package/dist/model-tier-config.js +249 -0
- package/dist/run-persistence.d.ts +180 -0
- package/dist/run-persistence.js +294 -0
- package/dist/saved-commands.d.ts +28 -0
- package/dist/saved-commands.js +100 -0
- package/dist/shared-store.d.ts +98 -0
- package/dist/shared-store.js +212 -0
- package/dist/structured-output.d.ts +19 -0
- package/dist/structured-output.js +30 -0
- package/dist/task-panel.d.ts +61 -0
- package/dist/task-panel.js +422 -0
- package/dist/usage-limit-scheduler.d.ts +145 -0
- package/dist/usage-limit-scheduler.js +368 -0
- package/dist/web-tools.d.ts +20 -0
- package/dist/web-tools.js +120 -0
- package/dist/workflow-authoring-coverage.d.ts +70 -0
- package/dist/workflow-authoring-coverage.js +421 -0
- package/dist/workflow-authoring-reference.d.ts +20 -0
- package/dist/workflow-authoring-reference.js +156 -0
- package/dist/workflow-capability-contract.d.ts +131 -0
- package/dist/workflow-capability-contract.js +604 -0
- package/dist/workflow-commands.d.ts +18 -0
- package/dist/workflow-commands.js +260 -0
- package/dist/workflow-comprehension.d.ts +133 -0
- package/dist/workflow-comprehension.js +1321 -0
- package/dist/workflow-context-measurement.d.ts +72 -0
- package/dist/workflow-context-measurement.js +213 -0
- package/dist/workflow-control-tool.d.ts +30 -0
- package/dist/workflow-control-tool.js +176 -0
- package/dist/workflow-delivery-choice.d.ts +20 -0
- package/dist/workflow-delivery-choice.js +48 -0
- package/dist/workflow-editor.d.ts +93 -0
- package/dist/workflow-editor.js +363 -0
- package/dist/workflow-manager.d.ts +492 -0
- package/dist/workflow-manager.js +1124 -0
- package/dist/workflow-paths.d.ts +22 -0
- package/dist/workflow-paths.js +46 -0
- package/dist/workflow-release-gate.d.ts +39 -0
- package/dist/workflow-release-gate.js +309 -0
- package/dist/workflow-saved.d.ts +38 -0
- package/dist/workflow-saved.js +126 -0
- package/dist/workflow-settings.d.ts +70 -0
- package/dist/workflow-settings.js +131 -0
- package/dist/workflow-tool.d.ts +71 -0
- package/dist/workflow-tool.js +367 -0
- package/dist/workflow-ui.d.ts +182 -0
- package/dist/workflow-ui.js +1587 -0
- package/dist/workflow.d.ts +333 -0
- package/dist/workflow.js +1151 -0
- package/dist/workflows-models-command.d.ts +31 -0
- package/dist/workflows-models-command.js +156 -0
- package/dist/worktree.d.ts +25 -0
- package/dist/worktree.js +61 -0
- package/extensions/workflow.ts +151 -0
- package/package.json +104 -0
- package/skills/workflow-authoring/SKILL.md +30 -0
- package/skills/workflow-authoring/examples/adversarial-verification.js +63 -0
- package/skills/workflow-authoring/examples/bounded-semantic-retry.js +56 -0
- package/skills/workflow-authoring/examples/classify-and-act.js +67 -0
- package/skills/workflow-authoring/examples/fan-out-and-synthesize.js +47 -0
- package/skills/workflow-authoring/examples/generate-and-filter.js +68 -0
- package/skills/workflow-authoring/examples/loop-until-done.js +68 -0
- package/skills/workflow-authoring/examples/phased-budgets.js +75 -0
- package/skills/workflow-authoring/examples/saved-nested-workflows.js +44 -0
- package/skills/workflow-authoring/examples/structured-output.js +37 -0
- package/skills/workflow-authoring/examples/tournament.js +81 -0
- package/skills/workflow-authoring/examples/validated-gate.js +63 -0
- package/skills/workflow-authoring/references/capabilities.md +41 -0
- package/skills/workflow-authoring/references/capability-details.md +357 -0
- package/skills/workflow-authoring/references/common-helpers.md +4 -0
- package/skills/workflow-authoring/references/debugging.md +27 -0
- package/skills/workflow-authoring/references/focused-recipes.md +11 -0
- package/skills/workflow-authoring/references/helpers.md +9 -0
- package/skills/workflow-authoring/references/lifecycle.md +33 -0
- package/skills/workflow-authoring/references/pattern-selection.md +15 -0
- package/skills/workflow-authoring/references/quality-helpers.md +8 -0
- package/skills/workflow-authoring/references/registry-ownership.md +15 -0
- package/skills/workflow-authoring/references/retry-helper.md +5 -0
- package/skills/workflow-authoring/references/review.md +43 -0
- package/skills/workflow-authoring/references/runtime.md +27 -0
- package/skills/workflow-authoring/references/specialized-helpers.md +19 -0
- package/skills/workflow-authoring/references/versions.md +13 -0
- package/skills/workflow-patterns/SKILL.md +51 -0
- package/src/accept-workflow-guidance.ts +71 -0
- package/src/adversarial-review.ts +120 -0
- package/src/agent-history.ts +157 -0
- package/src/agent-registry.ts +221 -0
- package/src/agent.ts +929 -0
- package/src/builtin-commands.ts +286 -0
- package/src/builtin-workflows.ts +155 -0
- package/src/code-review.ts +183 -0
- package/src/config.ts +55 -0
- package/src/deep-research.ts +135 -0
- package/src/display.ts +367 -0
- package/src/effort-command.ts +87 -0
- package/src/enums.ts +77 -0
- package/src/errors.ts +199 -0
- package/src/extension-reload.ts +100 -0
- package/src/fs-persistence.ts +124 -0
- package/src/index.ts +176 -0
- package/src/logger.ts +88 -0
- package/src/model-routing.ts +73 -0
- package/src/model-spec.ts +309 -0
- package/src/model-tier-config.ts +296 -0
- package/src/run-persistence.ts +484 -0
- package/src/saved-commands.ts +115 -0
- package/src/shared-store.ts +228 -0
- package/src/structured-output.ts +47 -0
- package/src/task-panel.ts +490 -0
- package/src/usage-limit-scheduler.ts +432 -0
- package/src/web-tools.ts +124 -0
- package/src/workflow-authoring-coverage.ts +486 -0
- package/src/workflow-authoring-reference.ts +186 -0
- package/src/workflow-capability-contract.ts +806 -0
- package/src/workflow-commands.ts +287 -0
- package/src/workflow-comprehension.ts +1673 -0
- package/src/workflow-context-measurement.ts +262 -0
- package/src/workflow-control-tool.ts +238 -0
- package/src/workflow-delivery-choice.ts +69 -0
- package/src/workflow-editor.ts +444 -0
- package/src/workflow-manager.ts +1405 -0
- package/src/workflow-paths.ts +63 -0
- package/src/workflow-release-gate.ts +529 -0
- package/src/workflow-saved.ts +180 -0
- package/src/workflow-settings.ts +194 -0
- package/src/workflow-tool.ts +464 -0
- package/src/workflow-ui.ts +1789 -0
- package/src/workflow.ts +1615 -0
- package/src/workflows-models-command.ts +211 -0
- package/src/worktree.ts +76 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep research workflow.
|
|
3
|
+
* Built-in workflow for comprehensive research across multiple sources.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface DeepResearchConfig {
|
|
7
|
+
/** Number of distinct search angles/queries to explore. */
|
|
8
|
+
angles: number;
|
|
9
|
+
/** Minimum distinct sources required for a claim to survive cross-checking. */
|
|
10
|
+
minSupport: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate a deep-research workflow that uses the real web_search/web_fetch tools.
|
|
15
|
+
*
|
|
16
|
+
* The script is static and reads its inputs from `args` (question/angles/minSupport),
|
|
17
|
+
* so the question is never string-interpolated into source — no escaping hazards.
|
|
18
|
+
* Inject the web tools at run time via the agent's `tools` option.
|
|
19
|
+
*/
|
|
20
|
+
export function generateDeepResearchWorkflow(): string {
|
|
21
|
+
return `export const meta = {
|
|
22
|
+
name: 'deep_research',
|
|
23
|
+
description: 'Deep research with real web search and cross-checked claims',
|
|
24
|
+
phases: [
|
|
25
|
+
{ title: 'Queries' },
|
|
26
|
+
{ title: 'Gather' },
|
|
27
|
+
{ title: 'Verify' },
|
|
28
|
+
{ title: 'Report' },
|
|
29
|
+
],
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const question = (args && args.question) || ''
|
|
33
|
+
const angles = (args && args.angles) || 4
|
|
34
|
+
const minSupport = (args && args.minSupport) || 2
|
|
35
|
+
|
|
36
|
+
phase('Queries')
|
|
37
|
+
const plan = await agent(
|
|
38
|
+
'You are planning web research for this question:\\n' + question +
|
|
39
|
+
'\\n\\nProduce ' + angles + ' diverse, specific search queries that together cover the question from different angles.',
|
|
40
|
+
{ label: 'plan queries', schema: { type: 'object', properties: { queries: { type: 'array', items: { type: 'string' } } }, required: ['queries'] } }
|
|
41
|
+
)
|
|
42
|
+
// The planner agent() can return null (e.g. a subagent that died on a terminal
|
|
43
|
+
// provider error) or omit a usable queries array. Mirror the null-tolerance the
|
|
44
|
+
// Gather phase uses below and fall back to the original question as a single
|
|
45
|
+
// query so research still proceeds (degraded) instead of crashing on plan.queries.
|
|
46
|
+
const planned = plan && Array.isArray(plan.queries) ? plan.queries.filter((q) => typeof q === 'string' && q.trim().length > 0) : []
|
|
47
|
+
const queries = (planned.length > 0 ? planned : [question]).slice(0, angles)
|
|
48
|
+
|
|
49
|
+
phase('Gather')
|
|
50
|
+
const gathered = await parallel(queries.map((q, i) => () =>
|
|
51
|
+
agent(
|
|
52
|
+
'Research this query using the web_search and web_fetch tools.\\nQuery: ' + q +
|
|
53
|
+
'\\n\\nSteps: (1) call web_search with the query; (2) web_fetch the 2 most relevant result URLs; ' +
|
|
54
|
+
'(3) extract concrete, verifiable factual claims, each tagged with the exact source URL it came from. ' +
|
|
55
|
+
'Do NOT invent sources or claims — report only what the fetched pages actually say.',
|
|
56
|
+
{ label: 'research ' + (i + 1), schema: { type: 'object', properties: { sources: { type: 'array', items: { type: 'object', properties: { url: { type: 'string' }, claims: { type: 'array', items: { type: 'string' } } }, required: ['url', 'claims'] } } }, required: ['sources'] } }
|
|
57
|
+
)
|
|
58
|
+
))
|
|
59
|
+
const allSources = gathered.filter(Boolean).flatMap((g) => (g && g.sources) || [])
|
|
60
|
+
|
|
61
|
+
phase('Verify')
|
|
62
|
+
const verdict = await agent(
|
|
63
|
+
'Cross-check these research sources. Group claims that assert the same fact across different source URLs. ' +
|
|
64
|
+
'Keep a claim only if it is supported by at least ' + minSupport + ' distinct source URLs OR by one clearly authoritative source. ' +
|
|
65
|
+
'Discard claims found in a single weak source or that conflict with others.\\n\\nSOURCES JSON:\\n' + JSON.stringify(allSources),
|
|
66
|
+
{ label: 'cross-check', schema: { type: 'object', properties: { supported: { type: 'array', items: { type: 'object', properties: { claim: { type: 'string' }, sources: { type: 'array', items: { type: 'string' } } }, required: ['claim', 'sources'] } }, discarded: { type: 'array', items: { type: 'string' } } }, required: ['supported'] } }
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
phase('Report')
|
|
70
|
+
const report = await agent(
|
|
71
|
+
'Write a concise, well-structured research report that answers the question using ONLY the supported claims below. ' +
|
|
72
|
+
'Cite source URLs inline next to each claim. If the evidence is thin, say so explicitly.\\n\\n' +
|
|
73
|
+
'QUESTION: ' + question + '\\n\\nSUPPORTED CLAIMS JSON:\\n' + JSON.stringify((verdict && verdict.supported) || []),
|
|
74
|
+
{ label: 'write report' }
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
return { question, queries, supported: (verdict && verdict.supported) || [], report }`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generate a codebase audit workflow.
|
|
82
|
+
*
|
|
83
|
+
* `scope` and each `checks` entry are user-supplied strings that get baked
|
|
84
|
+
* directly into the generated script's source (unlike the runtime-args-driven
|
|
85
|
+
* generators above), so every one is embedded via JSON.stringify — a proper JS
|
|
86
|
+
* string literal that can't be broken out of by a quote, backslash, or
|
|
87
|
+
* backtick in the value. Only the human-readable `meta.description` is
|
|
88
|
+
* truncated for display; the operative `scope` used by the agents is always
|
|
89
|
+
* the full, untruncated value.
|
|
90
|
+
*/
|
|
91
|
+
export function generateCodebaseAuditWorkflow(scope: string, checks: string[]): string {
|
|
92
|
+
const displayScope = scope.length > 60 ? `${scope.slice(0, 60)}…` : scope;
|
|
93
|
+
const checkAgents = checks
|
|
94
|
+
.map((check, i) => {
|
|
95
|
+
const label =
|
|
96
|
+
check
|
|
97
|
+
.toLowerCase()
|
|
98
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
99
|
+
.replace(/^-+|-+$/g, "")
|
|
100
|
+
.slice(0, 20) || `check-${i + 1}`;
|
|
101
|
+
return ` () => agent(${JSON.stringify(`Audit ${check} across: `)} + scope, { label: ${JSON.stringify(label)} }),`;
|
|
102
|
+
})
|
|
103
|
+
.join("\n");
|
|
104
|
+
|
|
105
|
+
return `export const meta = {
|
|
106
|
+
name: 'codebase_audit',
|
|
107
|
+
description: ${JSON.stringify(`Codebase audit: ${displayScope}`)},
|
|
108
|
+
phases: [
|
|
109
|
+
{ title: 'Individual Checks' },
|
|
110
|
+
{ title: 'Cross-Validation' },
|
|
111
|
+
{ title: 'Report' },
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
phase('Individual Checks');
|
|
116
|
+
const scope = ${JSON.stringify(scope)};
|
|
117
|
+
const findings = await parallel([
|
|
118
|
+
${checkAgents}
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
phase('Cross-Validation');
|
|
122
|
+
const validated = await agent(
|
|
123
|
+
'Cross-validate these audit findings. Remove false positives and confirm real issues:\\n' +
|
|
124
|
+
JSON.stringify(findings),
|
|
125
|
+
{ label: 'validator' }
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
phase('Report');
|
|
129
|
+
const report = await agent(
|
|
130
|
+
'Generate a prioritized audit report with actionable recommendations:\\n' + validated,
|
|
131
|
+
{ label: 'report-writer' }
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
return { findings, validated, report };`;
|
|
135
|
+
}
|
package/src/display.ts
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import type { ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { AgentUsage } from "./agent.js";
|
|
3
|
+
import type { AgentHistoryEntry } from "./agent-history.js";
|
|
4
|
+
import type { WorkflowErrorCode } from "./errors.js";
|
|
5
|
+
import type { WorkflowMeta } from "./workflow.js";
|
|
6
|
+
|
|
7
|
+
export type WorkflowAgentStatus = "queued" | "running" | "done" | "error" | "skipped";
|
|
8
|
+
|
|
9
|
+
export interface WorkflowAgentSnapshot {
|
|
10
|
+
id: number;
|
|
11
|
+
/** Runtime call identity (`${runId}:${callIndex}`), used to rehydrate journaled results. */
|
|
12
|
+
callId?: string;
|
|
13
|
+
label: string;
|
|
14
|
+
phase?: string;
|
|
15
|
+
prompt: string;
|
|
16
|
+
status: WorkflowAgentStatus;
|
|
17
|
+
/** Full agent result, retained for the interactive detail pager. */
|
|
18
|
+
result?: unknown;
|
|
19
|
+
resultPreview?: string;
|
|
20
|
+
error?: string;
|
|
21
|
+
errorCode?: WorkflowErrorCode;
|
|
22
|
+
recoverable?: boolean;
|
|
23
|
+
history?: AgentHistoryEntry[];
|
|
24
|
+
/** Tokens used by this agent (a scalar estimate when the provider reports no usage). */
|
|
25
|
+
tokens?: number;
|
|
26
|
+
/** Per-agent token usage breakdown (fresh input+output vs cached), when known. */
|
|
27
|
+
tokenUsage?: AgentUsage;
|
|
28
|
+
/** The model this agent ran on (provider/id), when known. */
|
|
29
|
+
model?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface WorkflowSnapshot {
|
|
33
|
+
name: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
phases: string[];
|
|
36
|
+
currentPhase?: string;
|
|
37
|
+
logs: string[];
|
|
38
|
+
agents: WorkflowAgentSnapshot[];
|
|
39
|
+
agentCount: number;
|
|
40
|
+
runningCount: number;
|
|
41
|
+
doneCount: number;
|
|
42
|
+
errorCount: number;
|
|
43
|
+
durationMs?: number;
|
|
44
|
+
result?: unknown;
|
|
45
|
+
tokenUsage?: {
|
|
46
|
+
input: number;
|
|
47
|
+
output: number;
|
|
48
|
+
total: number;
|
|
49
|
+
cost?: number;
|
|
50
|
+
cacheRead?: number;
|
|
51
|
+
cacheWrite?: number;
|
|
52
|
+
};
|
|
53
|
+
runId?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface WorkflowDisplay {
|
|
57
|
+
update(snapshot: WorkflowSnapshot): void;
|
|
58
|
+
complete(snapshot: WorkflowSnapshot): void;
|
|
59
|
+
clear(): void;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface WorkflowDisplayOptions {
|
|
63
|
+
key?: string;
|
|
64
|
+
placement?: "aboveEditor" | "belowEditor";
|
|
65
|
+
maxAgents?: number;
|
|
66
|
+
showStatus?: boolean;
|
|
67
|
+
showResultPreviews?: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Displayable fresh/cached figures from a usage breakdown and/or a scalar
|
|
72
|
+
* estimate. The token pipeline has two sources that don't always agree: the
|
|
73
|
+
* provider-reported breakdown (input/output/cacheRead/cacheWrite) and a scalar
|
|
74
|
+
* estimate (`total` at run level, `tokens` per agent) that keeps accruing even
|
|
75
|
+
* when the provider reports nothing. Two rules:
|
|
76
|
+
* - `fresh` counts input+output+cacheWrite: cache writes are first-time
|
|
77
|
+
* ingestion billed at full (or premium) price, so hiding them would
|
|
78
|
+
* under-report real spend; only cacheRead is the cheap reuse shown apart.
|
|
79
|
+
* - `fresh` is never less than what the estimate can account for after
|
|
80
|
+
* removing cache reads, so estimate-only providers, cost-only providers
|
|
81
|
+
* (billed but zero token counts), and mixed runs keep the count the display
|
|
82
|
+
* showed before the split existed, instead of a false "0 tok".
|
|
83
|
+
*/
|
|
84
|
+
export function tokenFigures(
|
|
85
|
+
usage: Partial<AgentUsage> | undefined,
|
|
86
|
+
scalarTokens?: number,
|
|
87
|
+
): { fresh: number; cacheRead: number } {
|
|
88
|
+
const cacheRead = usage?.cacheRead ?? 0;
|
|
89
|
+
const reported = (usage?.input ?? 0) + (usage?.output ?? 0) + (usage?.cacheWrite ?? 0);
|
|
90
|
+
const estimate = Math.max(scalarTokens ?? 0, usage?.total ?? 0);
|
|
91
|
+
return { fresh: Math.max(reported, estimate - cacheRead), cacheRead };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Sum a set of agents into fresh vs cacheRead totals, via {@link tokenFigures}. */
|
|
95
|
+
export function aggregateAgentUsage(agents: ReadonlyArray<Pick<WorkflowAgentSnapshot, "tokens" | "tokenUsage">>): {
|
|
96
|
+
fresh: number;
|
|
97
|
+
cacheRead: number;
|
|
98
|
+
} {
|
|
99
|
+
let fresh = 0;
|
|
100
|
+
let cacheRead = 0;
|
|
101
|
+
for (const a of agents) {
|
|
102
|
+
const f = tokenFigures(a.tokenUsage, a.tokens);
|
|
103
|
+
fresh += f.fresh;
|
|
104
|
+
cacheRead += f.cacheRead;
|
|
105
|
+
}
|
|
106
|
+
return { fresh, cacheRead };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Format a token count for a display surface: "12.4K tok" on its own, or
|
|
111
|
+
* "89K tok · 3.0M cached" when there were cache reads. The cache segment is shown
|
|
112
|
+
* only when `cacheRead > 0`, so a non-caching provider (or a single-turn agent that
|
|
113
|
+
* never re-reads its cache) reads as a plain "tok" rather than a bare, contextless
|
|
114
|
+
* "fresh". `fmt` adapts the number style per surface (compact in panels, full in
|
|
115
|
+
* the print view).
|
|
116
|
+
*/
|
|
117
|
+
export function fmtTokenCount(fresh: number, cacheRead: number, fmt: (n: number) => string): string {
|
|
118
|
+
const f = fmt(fresh) || "0";
|
|
119
|
+
return cacheRead > 0 ? `${f} tok · ${fmt(cacheRead)} cached` : `${f} tok`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Like {@link fmtTokenCount}, but "" when nothing is known yet (both figures 0),
|
|
124
|
+
* so surfaces omit the segment instead of rendering a false "0 tok" — e.g. for a
|
|
125
|
+
* journal-replayed resume or a run whose agents were all skipped. Every surface
|
|
126
|
+
* should use this rather than re-implementing the zero guard.
|
|
127
|
+
*/
|
|
128
|
+
export function fmtTokenSegment(figures: { fresh: number; cacheRead: number }, fmt: (n: number) => string): string {
|
|
129
|
+
return figures.fresh + figures.cacheRead > 0 ? fmtTokenCount(figures.fresh, figures.cacheRead, fmt) : "";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* "$1.23" from one cent up, four decimals below it, and "<$0.0001" for
|
|
134
|
+
* anything smaller — a real cost never rounds to a zero-looking "$0.00".
|
|
135
|
+
*/
|
|
136
|
+
export function fmtCost(cost: number): string {
|
|
137
|
+
if (cost > 0 && cost < 0.0001) return "<$0.0001";
|
|
138
|
+
return `$${cost.toFixed(cost >= 0.01 ? 2 : 4)}`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Full (non-compact) number style for print/text surfaces: locale-grouped digits. */
|
|
142
|
+
export const fmtFull = (n: number): string => n.toLocaleString();
|
|
143
|
+
|
|
144
|
+
export function createWorkflowSnapshot(meta: WorkflowMeta): WorkflowSnapshot {
|
|
145
|
+
return {
|
|
146
|
+
name: meta.name,
|
|
147
|
+
description: meta.description,
|
|
148
|
+
phases: meta.phases?.map((phase) => phase.title) ?? [],
|
|
149
|
+
logs: [],
|
|
150
|
+
agents: [],
|
|
151
|
+
agentCount: 0,
|
|
152
|
+
runningCount: 0,
|
|
153
|
+
doneCount: 0,
|
|
154
|
+
errorCount: 0,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function recomputeWorkflowSnapshot(snapshot: WorkflowSnapshot): WorkflowSnapshot {
|
|
159
|
+
const runningCount = snapshot.agents.filter((agent) => agent.status === "running").length;
|
|
160
|
+
const doneCount = snapshot.agents.filter((agent) => agent.status === "done").length;
|
|
161
|
+
const errorCount = snapshot.agents.filter((agent) => agent.status === "error").length;
|
|
162
|
+
return { ...snapshot, agentCount: snapshot.agents.length, runningCount, doneCount, errorCount };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function createWidgetWorkflowDisplay(
|
|
166
|
+
ctx: Pick<ExtensionContext, "ui" | "hasUI">,
|
|
167
|
+
options: WorkflowDisplayOptions = {},
|
|
168
|
+
): WorkflowDisplay {
|
|
169
|
+
const key = options.key ?? "workflow";
|
|
170
|
+
const placement = options.placement ?? "belowEditor";
|
|
171
|
+
const showStatus = options.showStatus ?? false;
|
|
172
|
+
|
|
173
|
+
// Mutable state captured by the component closure so re-renders
|
|
174
|
+
// always read the latest snapshot even though the factory ran once.
|
|
175
|
+
let snapshot: WorkflowSnapshot | undefined;
|
|
176
|
+
let completed = false;
|
|
177
|
+
|
|
178
|
+
// Store the factory so update()/complete() can re-register it to trigger re-render.
|
|
179
|
+
const widgetFactory = (_tui: unknown, theme: Theme) => ({
|
|
180
|
+
render: () => (snapshot ? renderWorkflowLines(snapshot, options, theme) : []),
|
|
181
|
+
invalidate: () => {},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
if (ctx.hasUI) {
|
|
185
|
+
ctx.ui.setWidget(key, widgetFactory, { placement });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
update(s) {
|
|
190
|
+
snapshot = s;
|
|
191
|
+
if (!ctx.hasUI) return;
|
|
192
|
+
if (showStatus) ctx.ui.setStatus(key, statusLine(s, completed));
|
|
193
|
+
ctx.ui.setWidget(key, widgetFactory, { placement });
|
|
194
|
+
},
|
|
195
|
+
complete(s) {
|
|
196
|
+
snapshot = s;
|
|
197
|
+
completed = true;
|
|
198
|
+
if (!ctx.hasUI) return;
|
|
199
|
+
if (showStatus) ctx.ui.setStatus(key, statusLine(s, true));
|
|
200
|
+
ctx.ui.setWidget(key, widgetFactory, { placement });
|
|
201
|
+
},
|
|
202
|
+
clear() {
|
|
203
|
+
if (!ctx.hasUI) return;
|
|
204
|
+
if (showStatus) ctx.ui.setStatus(key, undefined);
|
|
205
|
+
ctx.ui.setWidget(key, undefined);
|
|
206
|
+
},
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function createToolUpdateWorkflowDisplay(
|
|
211
|
+
onUpdate: ((result: { content: Array<{ type: "text"; text: string }>; details: unknown }) => void) | undefined,
|
|
212
|
+
ctx?: Pick<ExtensionContext, "ui" | "hasUI">,
|
|
213
|
+
options: WorkflowDisplayOptions & { streamToolUpdates?: boolean } = {},
|
|
214
|
+
): WorkflowDisplay {
|
|
215
|
+
const widget = ctx ? createWidgetWorkflowDisplay(ctx, options) : undefined;
|
|
216
|
+
const streamToolUpdates = options.streamToolUpdates ?? !ctx?.hasUI;
|
|
217
|
+
|
|
218
|
+
const emit = (snapshot: WorkflowSnapshot, completed = false) => {
|
|
219
|
+
if (streamToolUpdates) {
|
|
220
|
+
onUpdate?.({
|
|
221
|
+
content: [{ type: "text", text: renderWorkflowText(snapshot, completed) }],
|
|
222
|
+
details: snapshot,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
if (completed) widget?.complete(snapshot);
|
|
226
|
+
else widget?.update(snapshot);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
update(snapshot) {
|
|
231
|
+
emit(snapshot, false);
|
|
232
|
+
},
|
|
233
|
+
complete(snapshot) {
|
|
234
|
+
emit(snapshot, true);
|
|
235
|
+
},
|
|
236
|
+
clear() {
|
|
237
|
+
widget?.clear();
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Minimal theme surface so rendering works without a real Theme (tool output, tests). */
|
|
243
|
+
export interface ThemeLike {
|
|
244
|
+
fg(color: string, text: string): string;
|
|
245
|
+
bold(text: string): string;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** Identity passthrough for contexts where no theme is available (tool text output). */
|
|
249
|
+
const NO_THEME: ThemeLike = { fg: (_c, t) => t, bold: (t) => t };
|
|
250
|
+
|
|
251
|
+
/** The bracketed per-agent token cell (" [89 tok · 3,000 cached]"), or "" when nothing is known yet. */
|
|
252
|
+
function agentTokenCell(agent: WorkflowAgentSnapshot, theme: ThemeLike): string {
|
|
253
|
+
const segment = fmtTokenSegment(tokenFigures(agent.tokenUsage, agent.tokens), fmtFull);
|
|
254
|
+
return segment ? theme.fg("dim", ` [${segment}]`) : "";
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function renderWorkflowLines(
|
|
258
|
+
snapshot: WorkflowSnapshot,
|
|
259
|
+
options: WorkflowDisplayOptions = {},
|
|
260
|
+
theme: ThemeLike = NO_THEME,
|
|
261
|
+
): string[] {
|
|
262
|
+
const maxAgents = options.maxAgents ?? 8;
|
|
263
|
+
const showResultPreviews = options.showResultPreviews ?? false;
|
|
264
|
+
const state =
|
|
265
|
+
snapshot.errorCount > 0
|
|
266
|
+
? `, ${snapshot.errorCount} errors`
|
|
267
|
+
: snapshot.runningCount > 0
|
|
268
|
+
? `, ${snapshot.runningCount} running`
|
|
269
|
+
: "";
|
|
270
|
+
// Build header with token info (and cost when the provider reports it)
|
|
271
|
+
const usage = snapshot.tokenUsage;
|
|
272
|
+
const costInfo = usage?.cost ? ` · ${fmtCost(usage.cost)}` : "";
|
|
273
|
+
const segment = fmtTokenSegment(tokenFigures(usage), fmtFull);
|
|
274
|
+
const tokenInfo = `${segment ? ` · ${segment}` : ""}${costInfo}`;
|
|
275
|
+
const lines = [
|
|
276
|
+
`${theme.bold(`◆ Workflow: ${snapshot.name}`)} (${snapshot.doneCount}/${snapshot.agentCount} done${state}${tokenInfo})`,
|
|
277
|
+
];
|
|
278
|
+
|
|
279
|
+
const phaseNames = snapshot.phases.length
|
|
280
|
+
? snapshot.phases
|
|
281
|
+
: unique(snapshot.agents.map((agent) => agent.phase).filter(Boolean) as string[]);
|
|
282
|
+
const rendered = new Set<WorkflowAgentSnapshot>();
|
|
283
|
+
|
|
284
|
+
for (const phase of phaseNames) {
|
|
285
|
+
const agents = snapshot.agents.filter((agent) => agent.phase === phase);
|
|
286
|
+
for (const agent of agents) rendered.add(agent);
|
|
287
|
+
const done = agents.filter((agent) => agent.status === "done").length;
|
|
288
|
+
const running = agents.filter((agent) => agent.status === "running").length;
|
|
289
|
+
const errors = agents.filter((agent) => agent.status === "error").length;
|
|
290
|
+
const skipped = agents.filter((agent) => agent.status === "skipped").length;
|
|
291
|
+
const complete = agents.length > 0 && done + errors + skipped === agents.length;
|
|
292
|
+
const marker = running > 0 || (!complete && snapshot.currentPhase === phase) ? "▶" : complete ? "✓" : " ";
|
|
293
|
+
lines.push(
|
|
294
|
+
theme.fg("accent", ` ${marker} ${phase}`) +
|
|
295
|
+
theme.fg(
|
|
296
|
+
"dim",
|
|
297
|
+
` ${done}/${agents.length}${running ? ` · ${running} running` : ""}${errors ? ` · ${errors} errors` : ""}${skipped ? ` · ${skipped} skipped` : ""}`,
|
|
298
|
+
),
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
const visibleAgents = agents.slice(-maxAgents);
|
|
302
|
+
for (const agent of visibleAgents) {
|
|
303
|
+
const order = `[${agent.id}]`;
|
|
304
|
+
const result = showResultPreviews && agent.resultPreview ? ` — ${agent.resultPreview}` : "";
|
|
305
|
+
lines.push(
|
|
306
|
+
` ${order} ${statusIcon(agent.status)} ${shorten(agent.label, 48)}${agentTokenCell(agent, theme)}${result}`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
if (agents.length > visibleAgents.length)
|
|
310
|
+
lines.push(theme.fg("dim", ` … ${agents.length - visibleAgents.length} earlier agents`));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const unphased = snapshot.agents.filter((agent) => !rendered.has(agent));
|
|
314
|
+
if (unphased.length) {
|
|
315
|
+
lines.push(theme.fg("accent", " Unphased"));
|
|
316
|
+
for (const agent of unphased.slice(-maxAgents)) {
|
|
317
|
+
const result = showResultPreviews && agent.resultPreview ? ` — ${agent.resultPreview}` : "";
|
|
318
|
+
lines.push(
|
|
319
|
+
` [${agent.id}] ${statusIcon(agent.status)} ${shorten(agent.label, 48)}${agentTokenCell(agent, theme)}${result}`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return lines;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function renderWorkflowText(snapshot: WorkflowSnapshot, completed = false): string {
|
|
328
|
+
const header = completed ? "Workflow completed" : "Workflow running";
|
|
329
|
+
return [header, ...renderWorkflowLines(snapshot)].join("\n");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function statusLine(snapshot: WorkflowSnapshot, completed: boolean): string {
|
|
333
|
+
if (completed) return `workflow ✓ ${snapshot.name}: ${snapshot.doneCount}/${snapshot.agentCount}`;
|
|
334
|
+
if (snapshot.runningCount > 0)
|
|
335
|
+
return `workflow ${snapshot.name}: ${snapshot.runningCount} running, ${snapshot.doneCount}/${snapshot.agentCount} done`;
|
|
336
|
+
return `workflow ${snapshot.name}: ${snapshot.doneCount}/${snapshot.agentCount} done`;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function statusIcon(status: WorkflowAgentStatus): string {
|
|
340
|
+
switch (status) {
|
|
341
|
+
case "queued":
|
|
342
|
+
return "○";
|
|
343
|
+
case "running":
|
|
344
|
+
return "●";
|
|
345
|
+
case "done":
|
|
346
|
+
return "✓";
|
|
347
|
+
case "error":
|
|
348
|
+
return "✗";
|
|
349
|
+
case "skipped":
|
|
350
|
+
return "-";
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function unique(values: string[]): string[] {
|
|
355
|
+
return [...new Set(values)];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function shorten(value: string, max: number): string {
|
|
359
|
+
const text = value.replace(/\s+/g, " ").trim();
|
|
360
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export function preview(value: unknown, max = 80): string {
|
|
364
|
+
const text = typeof value === "string" ? value : JSON.stringify(value);
|
|
365
|
+
if (!text) return "";
|
|
366
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
367
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standing `/effort` opt-in (pi's answer to CC's ultracode): a session toggle that
|
|
3
|
+
* auto-arms a workflow for substantive interactive messages, with effort-tier
|
|
4
|
+
* guidance nudging fan-out breadth and the hard caps (tokenBudget / maxAgents) the
|
|
5
|
+
* model should set on the workflow tool call.
|
|
6
|
+
*
|
|
7
|
+
* Honest scope: the runtime cannot enforce "reviewer N / loop K" — those live in
|
|
8
|
+
* the script the model writes — so the tiers are guidance plus the model setting
|
|
9
|
+
* the real hard caps (tokenBudget/maxAgents are genuine runtime ceilings). The
|
|
10
|
+
* pre-flight ceiling-confirm dialog (roadmap P1-5 #4) is a downscope point: an
|
|
11
|
+
* `input` hook transforms synchronously and can't await a confirm, so it is left
|
|
12
|
+
* to a follow-up; `/effort` is explicit opt-in, which is the safety valve.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
16
|
+
|
|
17
|
+
export type EffortLevel = "off" | "high" | "ultra";
|
|
18
|
+
|
|
19
|
+
export interface EffortState {
|
|
20
|
+
level: EffortLevel;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createEffortState(): EffortState {
|
|
24
|
+
return { level: "off" };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const HIGH_DIRECTIVE =
|
|
28
|
+
"Effort: HIGH. Be thorough — use a few parallel reviewers/perspectives and an adversarial verify pass (see verify()/judgePanel()); set a moderate tokenBudget and maxAgents on the workflow tool call.";
|
|
29
|
+
const ULTRA_DIRECTIVE =
|
|
30
|
+
"Effort: ULTRA. Be exhaustive — fan out widely (more reviewers/judges, deeper loopUntilDry rounds, a completenessCheck at the end), and prefer the big tier for synthesis. This can spend a lot of tokens quickly, so set explicit caps you're comfortable paying for (a generous but bounded tokenBudget and a high maxAgents) on the workflow tool call rather than leaving them unbounded.";
|
|
31
|
+
|
|
32
|
+
/** The extra directive appended to the forced-workflow prompt for an effort level. */
|
|
33
|
+
export function effortDirective(level: EffortLevel): string | undefined {
|
|
34
|
+
if (level === "high") return HIGH_DIRECTIVE;
|
|
35
|
+
if (level === "ultra") return ULTRA_DIRECTIVE;
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether a message should auto-arm under effort mode: a real interactive request,
|
|
41
|
+
* not a terse acknowledgement or a slash command. (hasTrigger handles the explicit
|
|
42
|
+
* "workflow(s)" keyword separately.)
|
|
43
|
+
*/
|
|
44
|
+
export function isSubstantive(text: string): boolean {
|
|
45
|
+
const t = text.trim();
|
|
46
|
+
return t.length >= 16 && !t.startsWith("/");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function registerEffortCommand(pi: ExtensionAPI, state: EffortState): void {
|
|
50
|
+
pi.registerCommand("effort", {
|
|
51
|
+
description: "Standing workflow effort: off | high | ultra — auto-arms a workflow for substantive messages",
|
|
52
|
+
async handler(args: string, _ctx: ExtensionCommandContext) {
|
|
53
|
+
const arg = args.trim().toLowerCase();
|
|
54
|
+
const say = (content: string) => pi.sendMessage({ customType: "effort", content, display: true });
|
|
55
|
+
if (arg === "off" || arg === "high" || arg === "ultra") {
|
|
56
|
+
state.level = arg;
|
|
57
|
+
await say(
|
|
58
|
+
arg === "off"
|
|
59
|
+
? "Effort off — messages are no longer auto-armed as workflows."
|
|
60
|
+
: `Effort ${arg} — substantive messages now auto-arm a workflow (${arg === "ultra" ? "exhaustive" : "thorough"} fan-out). Use /effort off to stop.`,
|
|
61
|
+
);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
await say(`Effort is currently "${state.level}". Usage: /effort off | high | ultra`);
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// `/ultracode` — the headline name for the maximal-effort mode (Pi's ultracode):
|
|
69
|
+
// `/ultracode` turns it on, `/ultracode off` turns it off. Alias for /effort ultra.
|
|
70
|
+
pi.registerCommand("ultracode", {
|
|
71
|
+
description:
|
|
72
|
+
"Ultracode: standing maximal-effort mode (this session only, never persisted) — auto-arms an exhaustive workflow for substantive messages. /ultracode off to stop.",
|
|
73
|
+
async handler(args: string, _ctx: ExtensionCommandContext) {
|
|
74
|
+
const arg = args.trim().toLowerCase();
|
|
75
|
+
const say = (content: string) => pi.sendMessage({ customType: "effort", content, display: true });
|
|
76
|
+
if (arg === "off") {
|
|
77
|
+
state.level = "off";
|
|
78
|
+
await say("Ultracode off — messages are no longer auto-armed as workflows.");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
state.level = "ultra";
|
|
82
|
+
await say(
|
|
83
|
+
"Ultracode ON — substantive messages now auto-arm an exhaustive workflow (wide fan-out, big-tier synthesis). Use /ultracode off to stop.",
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
}
|
package/src/enums.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/** Classifies a workflow capability by its runtime and documentation role. */
|
|
2
|
+
export enum CapabilityClassification {
|
|
3
|
+
RUNTIME_GLOBAL = "runtime-global",
|
|
4
|
+
WORKFLOW_TOOL_INPUT = "workflow-tool-input",
|
|
5
|
+
SCRIPT_CONTRACT = "script-contract",
|
|
6
|
+
COMPATIBILITY_BEHAVIOR = "compatibility-behavior",
|
|
7
|
+
INTERNAL_SUBSTRATE = "internal-substrate",
|
|
8
|
+
DYNAMIC_REFERENCE = "dynamic-reference",
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Declares whether workflow authors should use a capability. */
|
|
12
|
+
export enum CapabilitySupport {
|
|
13
|
+
SUPPORTED = "supported",
|
|
14
|
+
COMPATIBILITY = "compatibility",
|
|
15
|
+
INTERNAL = "internal",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Identifies the model-visible surface responsible for discovery. */
|
|
19
|
+
export enum DiscoveryPlacement {
|
|
20
|
+
COMPACT_GUIDANCE = "compact-guidance",
|
|
21
|
+
WORKFLOW_AUTHORING_SKILL = "workflow-authoring-skill",
|
|
22
|
+
NONE = "none",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Names the subsystem that owns a capability's behavior. */
|
|
26
|
+
export enum CapabilityOrigin {
|
|
27
|
+
PROJECT = "project",
|
|
28
|
+
TOOL_ADAPTER = "tool-adapter",
|
|
29
|
+
VM_REALM = "vm-realm",
|
|
30
|
+
LIVE_CONFIGURATION = "live-configuration",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Severity carried by capability-alignment diagnostics. */
|
|
34
|
+
export enum DiagnosticSeverity {
|
|
35
|
+
ERROR = "error",
|
|
36
|
+
WARNING = "warning",
|
|
37
|
+
INFORMATION = "information",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Optional model-comprehension scenario groups. */
|
|
41
|
+
export enum ComprehensionSuite {
|
|
42
|
+
QUICK = "quick",
|
|
43
|
+
FULL = "full",
|
|
44
|
+
COVERAGE = "coverage",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Authoring operation exercised by a comprehension scenario. */
|
|
48
|
+
export enum ComprehensionTaskKind {
|
|
49
|
+
WRITE = "write",
|
|
50
|
+
EDIT = "edit",
|
|
51
|
+
REVIEW = "review",
|
|
52
|
+
DEBUG = "debug",
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Whether authoring guidance may be optimized against behavioral evidence or must remain frozen. */
|
|
56
|
+
export enum WorkflowAuthoringProtection {
|
|
57
|
+
BEHAVIORALLY_COVERED = "behaviorally-covered",
|
|
58
|
+
GUIDANCE_FROZEN = "guidance-frozen",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Machine-readable release-gate failure and warning domains. */
|
|
62
|
+
export enum WorkflowReleaseDiagnosticCode {
|
|
63
|
+
INCOMPATIBLE_VERSION = "INCOMPATIBLE_VERSION",
|
|
64
|
+
MISSING_BEHAVIOR_EVIDENCE = "MISSING_BEHAVIOR_EVIDENCE",
|
|
65
|
+
UNRESOLVED_BEHAVIOR_EVIDENCE = "UNRESOLVED_BEHAVIOR_EVIDENCE",
|
|
66
|
+
BROKEN_CONTRACT_REFERENCE = "BROKEN_CONTRACT_REFERENCE",
|
|
67
|
+
MISSING_PACKAGE_RESOURCE = "MISSING_PACKAGE_RESOURCE",
|
|
68
|
+
BROKEN_PACKAGE_LINK = "BROKEN_PACKAGE_LINK",
|
|
69
|
+
STALE_GENERATED_SURFACE = "STALE_GENERATED_SURFACE",
|
|
70
|
+
TOOL_INPUT_MISMATCH = "TOOL_INPUT_MISMATCH",
|
|
71
|
+
RUNTIME_CONSTRAINT_DISAGREEMENT = "RUNTIME_CONSTRAINT_DISAGREEMENT",
|
|
72
|
+
NON_CONTRACTUAL_PROSE_DRIFT = "NON_CONTRACTUAL_PROSE_DRIFT",
|
|
73
|
+
MISSING_AUTHORING_COVERAGE = "MISSING_AUTHORING_COVERAGE",
|
|
74
|
+
UNPROTECTED_AUTHORING_GUIDANCE = "UNPROTECTED_AUTHORING_GUIDANCE",
|
|
75
|
+
PROTECTED_GUIDANCE_DRIFT = "PROTECTED_GUIDANCE_DRIFT",
|
|
76
|
+
UNKNOWN_COMPREHENSION_SCENARIO = "UNKNOWN_COMPREHENSION_SCENARIO",
|
|
77
|
+
}
|