intentdna 1.8.7 → 1.9.0-rc.2
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/cli/commands/candidate-promotion.d.ts +15 -0
- package/dist/cli/commands/candidate-promotion.js +197 -0
- package/dist/cli/commands/run-lifecycle.js +1 -0
- package/dist/cli/commands/run.js +76 -42
- package/dist/cli/commands/setup.d.ts +10 -0
- package/dist/cli/commands/setup.js +129 -36
- package/dist/cli/commands/source-assets.d.ts +32 -0
- package/dist/cli/commands/source-assets.js +154 -0
- package/dist/cli/commands/sync.js +52 -12
- package/dist/cli/commands/templates.js +59 -37
- package/dist/cli/index.js +161 -5
- package/dist/compiler/cascade.js +1 -1
- package/dist/hooks/cli.d.ts +6 -0
- package/dist/hooks/cli.js +118 -10
- package/dist/hooks/enforcement-boundary.d.ts +1 -1
- package/dist/hooks/protocol.d.ts +1 -1
- package/dist/hooks/state.d.ts +5 -0
- package/dist/hooks/state.js +21 -6
- package/dist/mcp/tools-state.js +251 -15
- package/dist/runtime/claude-sync-target.d.ts +2 -0
- package/dist/runtime/claude-sync-target.js +1 -1
- package/dist/runtime/evaluator.d.ts +13 -0
- package/dist/runtime/evaluator.js +46 -0
- package/dist/runtime/index.d.ts +8 -4
- package/dist/runtime/index.js +4 -2
- package/dist/runtime/plugin-adapter.d.ts +14 -1
- package/dist/runtime/plugin-adapter.js +23 -9
- package/dist/runtime/run-contracts.d.ts +5 -3
- package/dist/runtime/run-contracts.js +11 -1
- package/dist/runtime/run-controller.d.ts +15 -1
- package/dist/runtime/run-controller.js +235 -94
- package/dist/runtime/skill-adapter.js +24 -53
- package/dist/runtime/verifier.js +101 -2
- package/dist/runtime/workflow-plan-adapter.d.ts +2 -1
- package/dist/runtime/workflow-plan-adapter.js +78 -11
- package/dist/runtime/workflow-runtime-manifest.d.ts +48 -0
- package/dist/runtime/workflow-runtime-manifest.js +196 -0
- package/dist/runtime/workflow-variable-scopes.d.ts +12 -0
- package/dist/runtime/workflow-variable-scopes.js +55 -0
- package/dist/schema/types.d.ts +9 -0
- package/dist/schema/validate.js +29 -1
- package/dist/sources/authoring-packet.d.ts +8 -0
- package/dist/sources/authoring-packet.js +85 -0
- package/dist/sources/discovery.d.ts +7 -0
- package/dist/sources/discovery.js +150 -0
- package/dist/sources/license.d.ts +5 -0
- package/dist/sources/license.js +94 -0
- package/dist/sources/manifest.d.ts +11 -0
- package/dist/sources/manifest.js +84 -0
- package/dist/sources/skill-markdown.d.ts +6 -0
- package/dist/sources/skill-markdown.js +174 -0
- package/dist/sources/types.d.ts +125 -0
- package/dist/sources/types.js +1 -0
- package/dist/templates/asset-refinery.dna.yaml +192 -0
- package/dist/templates/flutter-behavior-lock.dna.yaml +17 -0
- package/dist/templates/flutter-refactoring-rescue.dna.yaml +11 -0
- package/dist/templates/flutter-rewrite.dna.yaml +154 -28
- package/dist/templates/metadata.js +2 -0
- package/dist/templates/multi-agent-handoff-coordination.dna.yaml +102 -37
- package/dist/templates/persistent-executor.dna.yaml +61 -3
- package/dist/templates/research-improvement.dna.yaml +295 -0
- package/dist/templates/subagent-parallel.dna.yaml +90 -17
- package/dist/templates/workflow-evidence-review.dna.yaml +8 -0
- package/dist/workflow/candidate-projection.d.ts +33 -0
- package/dist/workflow/candidate-projection.js +70 -0
- package/package.json +3 -1
- package/scripts/sync-release-plugin.cjs +87 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* dna templates — template catalog and deployment commands.
|
|
3
3
|
*/
|
|
4
|
-
import { readdirSync, copyFileSync, existsSync, readFileSync, mkdirSync } from "node:fs";
|
|
4
|
+
import { readdirSync, copyFileSync, existsSync, readFileSync, mkdirSync, lstatSync, } from "node:fs";
|
|
5
5
|
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { resolve, join, basename, dirname } from "node:path";
|
|
@@ -15,6 +15,7 @@ import { resolveAuthToken } from "./auth.js";
|
|
|
15
15
|
import { missingCliApiTokenReason } from "./cloud-auth-guidance.js";
|
|
16
16
|
import { createWorkflowDraft, workflowDraftToTemplateYaml, } from "../../workflow/index.js";
|
|
17
17
|
import { WORKFLOW_ASSET_IDS } from "../../templates/metadata.js";
|
|
18
|
+
import { buildSourceAuthoringPacket } from "../../sources/authoring-packet.js";
|
|
18
19
|
/**
|
|
19
20
|
* Resolve the global intentdna templates directory.
|
|
20
21
|
* Strategy: npm root -g + /intentdna/dist/templates
|
|
@@ -1774,6 +1775,9 @@ function candidateTemplateName(sourceId) {
|
|
|
1774
1775
|
function normalizeTemplateSaveName(name) {
|
|
1775
1776
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "source-candidate";
|
|
1776
1777
|
}
|
|
1778
|
+
function isSafeCandidateName(name) {
|
|
1779
|
+
return /^[a-z][a-z0-9-]{1,62}$/.test(name);
|
|
1780
|
+
}
|
|
1777
1781
|
function workflowFromSourceCandidate(candidate) {
|
|
1778
1782
|
const closestTemplate = candidate.coverage.matchedTemplates[0]?.name;
|
|
1779
1783
|
const comparePrompt = closestTemplate
|
|
@@ -1922,37 +1926,50 @@ function buildSourceCandidatePreview(candidate, requestedTemplateName) {
|
|
|
1922
1926
|
boundary: "Read-only candidate preview. It prints a reviewable template YAML draft but does not write files, configure projects, sync runtimes, deploy, or mutate evolution markers.",
|
|
1923
1927
|
};
|
|
1924
1928
|
}
|
|
1925
|
-
function writeSourceCandidatePreview(preview) {
|
|
1926
|
-
process.stderr.write("Template reference candidate preview\n");
|
|
1927
|
-
process.stderr.write(`Reference: ${preview.candidate.id}\n`);
|
|
1928
|
-
process.stderr.write(`Template: ${preview.templateName}\n`);
|
|
1929
|
-
process.stderr.write(`Decision: ${preview.decision.status}\n`);
|
|
1930
|
-
process.stderr.write(`Workflow: ${preview.draft.workflow.name}\n`);
|
|
1931
|
-
process.stderr.write(`Steps: ${preview.draft.workflow.steps.length}\n`);
|
|
1932
|
-
process.stderr.write("\nReview commands\n");
|
|
1933
|
-
for (const command of preview.reviewCommands)
|
|
1934
|
-
process.stderr.write(` - ${command}\n`);
|
|
1935
|
-
process.stderr.write("\nBlocked until review\n");
|
|
1936
|
-
for (const blocker of preview.blockedUntilReview)
|
|
1937
|
-
process.stderr.write(` - ${blocker}\n`);
|
|
1938
|
-
process.stderr.write(`Boundary: ${preview.boundary}\n`);
|
|
1939
|
-
process.stderr.write("\n--- YAML preview is written to stdout ---\n");
|
|
1940
|
-
process.stdout.write(preview.templateYaml);
|
|
1941
|
-
if (!preview.templateYaml.endsWith("\n"))
|
|
1942
|
-
process.stdout.write("\n");
|
|
1943
|
-
}
|
|
1944
1929
|
async function saveSourceCandidatePreview(params) {
|
|
1945
|
-
const projectDir = params.projectDir ?? process.cwd();
|
|
1946
|
-
const
|
|
1947
|
-
const
|
|
1930
|
+
const projectDir = resolve(params.projectDir ?? process.cwd());
|
|
1931
|
+
const dnaDir = join(projectDir, ".dna");
|
|
1932
|
+
const authoringDir = join(dnaDir, "authoring");
|
|
1933
|
+
const path = join(authoringDir, `${params.preview.templateName}.candidate.dna.yaml`);
|
|
1934
|
+
for (const stagingParent of [dnaDir, authoringDir]) {
|
|
1935
|
+
if (existsSync(stagingParent)
|
|
1936
|
+
&& lstatSync(stagingParent).isSymbolicLink()) {
|
|
1937
|
+
return {
|
|
1938
|
+
error: `Candidate staging path must not contain a symlink: ${stagingParent}`,
|
|
1939
|
+
path,
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1948
1943
|
if (existsSync(path)) {
|
|
1949
1944
|
return {
|
|
1950
|
-
error: `
|
|
1945
|
+
error: `Candidate already exists: ${params.preview.templateName}`,
|
|
1951
1946
|
path,
|
|
1952
1947
|
};
|
|
1953
1948
|
}
|
|
1954
|
-
await mkdir(
|
|
1955
|
-
|
|
1949
|
+
await mkdir(authoringDir, { recursive: true });
|
|
1950
|
+
for (const stagingParent of [dnaDir, authoringDir]) {
|
|
1951
|
+
if (lstatSync(stagingParent).isSymbolicLink()) {
|
|
1952
|
+
return {
|
|
1953
|
+
error: `Candidate staging path must not contain a symlink: ${stagingParent}`,
|
|
1954
|
+
path,
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
try {
|
|
1959
|
+
await writeFile(path, params.preview.templateYaml, {
|
|
1960
|
+
encoding: "utf-8",
|
|
1961
|
+
flag: "wx",
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
catch (error) {
|
|
1965
|
+
if (error.code === "EEXIST") {
|
|
1966
|
+
return {
|
|
1967
|
+
error: `Candidate already exists: ${params.preview.templateName}`,
|
|
1968
|
+
path,
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
throw error;
|
|
1972
|
+
}
|
|
1956
1973
|
const closestTemplate = params.preview.candidate.coverage.matchedTemplates[0]?.name ?? "<current-template>";
|
|
1957
1974
|
return {
|
|
1958
1975
|
mode: "saved_template_source_candidate",
|
|
@@ -1963,19 +1980,18 @@ async function saveSourceCandidatePreview(params) {
|
|
|
1963
1980
|
decision: params.preview.decision,
|
|
1964
1981
|
reviewCommands: params.preview.reviewCommands,
|
|
1965
1982
|
nextCommands: [
|
|
1966
|
-
`dna
|
|
1983
|
+
`dna validate ${path}`,
|
|
1984
|
+
`dna workflow project-candidate ${path} --target claude --dry-run`,
|
|
1985
|
+
`dna workflow project-candidate ${path} --target codex --dry-run`,
|
|
1967
1986
|
`dna assets diff ${closestTemplate} ${params.preview.templateName}`,
|
|
1968
1987
|
`dna assets adoption ${params.preview.templateName}`,
|
|
1969
|
-
`dna org bind --asset ${params.preview.templateName} --status planned --sync-target codex`,
|
|
1970
|
-
"dna org rollout",
|
|
1971
|
-
"dna sync --codex --dry-run",
|
|
1972
1988
|
],
|
|
1973
1989
|
blockedUntilReview: [
|
|
1974
1990
|
"Runtime sync remains blocked until asset diff/adoption and organization rollout review pass.",
|
|
1975
1991
|
"Vercel deployment is unrelated unless a web/public surface changes.",
|
|
1976
1992
|
"Evolution marker mutation remains blocked until evidence-backed suggestions are reviewed.",
|
|
1977
1993
|
],
|
|
1978
|
-
boundary: "Saved
|
|
1994
|
+
boundary: "Saved an unreviewed candidate under .dna/authoring only. It is not promoted, adopted, organization-bound, synced, deployed, or evolved.",
|
|
1979
1995
|
};
|
|
1980
1996
|
}
|
|
1981
1997
|
function writeSavedSourceCandidate(result) {
|
|
@@ -2029,8 +2045,12 @@ export async function runTemplatesSources(opts = {}) {
|
|
|
2029
2045
|
return 2;
|
|
2030
2046
|
}
|
|
2031
2047
|
if (opts.candidate) {
|
|
2032
|
-
const preview = buildSourceCandidatePreview(candidate, opts.saveTemplate);
|
|
2033
2048
|
if (opts.saveTemplate) {
|
|
2049
|
+
if (!isSafeCandidateName(opts.saveTemplate)) {
|
|
2050
|
+
process.stderr.write("Error: invalid candidate name; use 2-63 lowercase letters, digits, or hyphens, starting with a letter.\n");
|
|
2051
|
+
return 2;
|
|
2052
|
+
}
|
|
2053
|
+
const preview = buildSourceCandidatePreview(candidate, opts.saveTemplate);
|
|
2034
2054
|
const saved = await saveSourceCandidatePreview({ preview, projectDir: opts.projectDir });
|
|
2035
2055
|
if ("error" in saved) {
|
|
2036
2056
|
process.stderr.write(`${saved.error}\n`);
|
|
@@ -2045,11 +2065,13 @@ export async function runTemplatesSources(opts = {}) {
|
|
|
2045
2065
|
writeSavedSourceCandidate(saved);
|
|
2046
2066
|
return 0;
|
|
2047
2067
|
}
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2068
|
+
const packet = await buildSourceAuthoringPacket({
|
|
2069
|
+
skillDir: dirname(candidate.path),
|
|
2070
|
+
projectDir: opts.projectDir,
|
|
2071
|
+
sourceId: candidate.id,
|
|
2072
|
+
});
|
|
2073
|
+
process.stderr.write("Warning: deprecated --candidate alias; use --packet for source authoring packets.\n");
|
|
2074
|
+
process.stdout.write(`${JSON.stringify(packet, null, 2)}\n`);
|
|
2053
2075
|
return 0;
|
|
2054
2076
|
}
|
|
2055
2077
|
const packet = await buildTemplateSourceReviewPacket(candidate);
|
package/dist/cli/index.js
CHANGED
|
@@ -12,9 +12,57 @@
|
|
|
12
12
|
* help Show this help message
|
|
13
13
|
*/
|
|
14
14
|
import { parseArgs } from "node:util";
|
|
15
|
+
import { basename, isAbsolute, relative, resolve } from "node:path";
|
|
15
16
|
import { getPackageVersion } from "./util/version.js";
|
|
16
17
|
import { WORKFLOW_ASSET_IDS } from "../templates/metadata.js";
|
|
17
18
|
const fallbackVersion = "unknown";
|
|
19
|
+
const REFINERY_CANDIDATE_FILE_RE = /^([a-z][a-z0-9-]{1,62})\.candidate\.dna\.yaml$/;
|
|
20
|
+
function normalizeAssetRefineryVariables(projectDir, variables) {
|
|
21
|
+
const authoringRoot = resolve(projectDir, ".dna", "authoring");
|
|
22
|
+
const normalizeAuthoringPath = (value, label) => {
|
|
23
|
+
const absolute = resolve(projectDir, value);
|
|
24
|
+
const fromAuthoring = relative(authoringRoot, absolute);
|
|
25
|
+
if (fromAuthoring === ""
|
|
26
|
+
|| fromAuthoring === ".."
|
|
27
|
+
|| fromAuthoring.startsWith("../")
|
|
28
|
+
|| fromAuthoring.startsWith("..\\")
|
|
29
|
+
|| isAbsolute(fromAuthoring)) {
|
|
30
|
+
return {
|
|
31
|
+
error: `${label} must resolve inside the selected project's .dna/authoring directory`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
path: `.dna/authoring/${fromAuthoring.replaceAll("\\", "/")}`,
|
|
36
|
+
absolute,
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const sourcePacket = normalizeAuthoringPath(variables.source_packet ?? ".dna/authoring/source-packet.json", "source_packet");
|
|
40
|
+
if (sourcePacket.error)
|
|
41
|
+
return sourcePacket.error;
|
|
42
|
+
const requestedCandidateName = variables.candidate_name;
|
|
43
|
+
const candidateValue = variables.candidate_path
|
|
44
|
+
?? `.dna/authoring/${requestedCandidateName ?? "source"}.candidate.dna.yaml`;
|
|
45
|
+
const candidate = normalizeAuthoringPath(candidateValue, "candidate_path");
|
|
46
|
+
if (candidate.error)
|
|
47
|
+
return candidate.error;
|
|
48
|
+
const candidateFilename = basename(candidate.absolute);
|
|
49
|
+
const candidateMatch = REFINERY_CANDIDATE_FILE_RE.exec(candidateFilename);
|
|
50
|
+
if (!candidateMatch) {
|
|
51
|
+
return "candidate_path must end with <safe-name>.candidate.dna.yaml, using 2-63 lowercase letters, digits, or hyphens";
|
|
52
|
+
}
|
|
53
|
+
if (candidate.path.slice(".dna/authoring/".length) !== candidateFilename) {
|
|
54
|
+
return "candidate_path must be a direct child of .dna/authoring";
|
|
55
|
+
}
|
|
56
|
+
const candidateName = candidateMatch[1];
|
|
57
|
+
if (requestedCandidateName !== undefined
|
|
58
|
+
&& requestedCandidateName !== candidateName) {
|
|
59
|
+
return "candidate_name must match the basename of candidate_path";
|
|
60
|
+
}
|
|
61
|
+
variables.source_packet = sourcePacket.path;
|
|
62
|
+
variables.candidate_name = candidateName;
|
|
63
|
+
variables.candidate_path = candidate.path;
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
18
66
|
function helpText(version) {
|
|
19
67
|
return `Intent DNA CLI v${version}
|
|
20
68
|
|
|
@@ -223,9 +271,9 @@ Boundaries:
|
|
|
223
271
|
`,
|
|
224
272
|
sync: `Usage: dna sync [status|doctor|remove] [files...] [options]\n\nSubcommands:\n status Show registry-tracked sync artifacts and drift posture\n doctor Check whether registry-tracked artifacts still match last sync\n remove Remove safe hash-matching IntentDNA-owned/diagnostic artifacts from the registry\n\nOptions:\n --mode auto|plugin|bin Sync mode (default: auto)\n --dry-run Print planned outputs without writing files; with remove, preview removals\n --post-summary Print registry-backed output summary after sync\n --json Print status/doctor JSON to stdout\n --project-dir <path> Read/write local sync configs and artifacts in another project directory\n --target <target> Markdown target for injection\n --inject <path> File to inject markdown into\n --agents <dir> Generate agent files\n --skills <dir> Generate skill files\n --workflow <dir> Generate workflow shell scripts\n --settings <path> Write hook settings in bin mode\n --codex Generate Codex CLI instruction, plugin, fallback hook, and evidence artifacts\n --codex-install-mode <mode> plugin_scoped|project_fallback|managed|none (default project_fallback)\n --codex-dogfood Probe codex exec --json and attach diagnostic evidence\n --lock <path> Write lock file (default .dna/lock)\n --remove Legacy explicit-target removal; requires --inject/--agents/--skills/--workflow/--codex\n`,
|
|
225
273
|
verify: `Usage: dna verify [--lock <path>] [--stats] [--health] [--strict]\n\nOptions:\n --health Comprehensive installation health check\n --stats Show hook call statistics\n --strict Require valid RuntimeDecisionEvent enterprise evidence\n --lock <path> Lock file path (default .dna/lock)\n`,
|
|
226
|
-
templates: `Usage: dna templates <list|marketplace|manage|sources|show|publish|publications|revoke|deploy> [name] [--json] [--project-dir <path>]\n\nSubcommands:\n list List built-in and project templates with marketplace visibility/harness metadata\n marketplace Export a shared intentdna.template_marketplace_catalog.v1 catalog\n manage [name] Show template management view: tags/details/marketplace/step index plus full YAML\n sources [reference] Review external workflow/skill references
|
|
274
|
+
templates: `Usage: dna templates <list|marketplace|manage|sources|show|publish|publications|revoke|deploy> [name] [--json] [--project-dir <path>]\n\nSubcommands:\n list List built-in and project templates with marketplace visibility/harness metadata\n marketplace Export a shared intentdna.template_marketplace_catalog.v1 catalog\n manage [name] Show template management view: tags/details/marketplace/step index plus full YAML\n sources [reference] Review, snapshot, or packetize external workflow/skill references\n show <name> Show template metadata, marketplace metadata, and YAML\n publish Publish an org-private template through Supabase using a local receipt evidence file\n publications List org-private template publications through Supabase as read-only projection\n revoke Mark one org-private template publication unpublished through Supabase metadata\n deploy Copy local templates to global install\n\nOptions:\n --json Print manage/sources/marketplace/publish/publications/revoke JSON to stdout\n --project-dir <path> Include project-local .dna/templates from another project directory\n --output <path> For marketplace: write catalog JSON for online/static import\n --source-dir <path> Scan a reference workflow/skill directory (repeatable)\n --focus all|refresh|gaps For sources list: all references, existing-template refreshes, or uncovered gaps\n --snapshot Emit deterministic source manifests and hashes\n --packet Emit intentdna.source_authoring_packet.v1 for the selected source\n --write <path> Write a snapshot or packet under .dna/authoring without overwrite\n --candidate Deprecated read-only packet alias retained for one release\n --save-template <name> With --candidate, stage a compatibility candidate under .dna/authoring; never promote it\n --org <org> For publish/publications/revoke: organization id/slug/name\n --project <project> For publish/publications/revoke: project id/slug/name\n --template <name> For publish/publications: template name filter\n --publication-id <id> For revoke: org-private template publication id from dna templates publications\n --reason <text> For revoke: optional human reason stored in request metadata\n --receipt <path> For publish: intentdna.org_review_receipt.v1 or intentdna.report_ingest_receipt.v1 evidence file\n --endpoint <url> For publish/publications/revoke: Supabase Edge Function endpoint override\n --auth-config-dir <dir> Read CLI API token config from a specific directory for isolated template publication checks\n --dry-run For publish/publications/revoke: validate request without network upload\n`,
|
|
227
275
|
assets: `Usage: dna assets <list|library|candidates|lineage|show|inspect|status|review|governance|lifecycle|adoption|suggestions|diff|evidence> [name] [--evidence] [--json]\n\nSubcommands:\n list List template-backed workflow assets\n library Browse workflow assets by readiness with evidence/governance next commands\n candidates [name] Find candidate workflow assets to extract or promote from dogfood evidence\n lineage <name> Explain origin, cascade, evidence, and human-reviewed evolution route\n lifecycle <name> Show cascade, evidence, suggestion, draft, review, adoption, bind, and sync lifecycle\n show <name> Show workflow asset summary\n inspect <name> Show workflows, controllers, roles, steps, and optional evidence links\n status [name] Show read-only management, evidence, and project configuration posture\n review Show manager-facing asset health summary and next actions\n governance <name> Explain cascade inheritance and preview-first evolution for an asset\n adoption <name> Show adoption readiness checks and the safe adoption path\n suggestions <name> Suggest human-reviewed workflow improvements from evidence\n diff <from> <to> Compare two workflow assets for manager review before adoption\n evidence <name> Summarize registered dogfood progress JSON for a workflow asset\n\nOptions:\n --evidence Include registered evidence/reference links\n --project-dir <path> Read project-local workflow assets and configs from another project directory\n --json Print JSON to stdout\n`,
|
|
228
|
-
workflow: `Usage: dna workflow <examples|authoring-packet|intake|route|suggestions|mine|draft|edit-plan|review-suggestion|improve-from-suggestions|from-candidate>
|
|
276
|
+
workflow: `Usage: dna workflow <examples|authoring-packet|intake|route|suggestions|mine|draft|edit-plan|review-suggestion|improve-from-suggestions|from-candidate>\n dna workflow promote-candidate <candidate-path> --save-template <name>\n dna workflow project-candidate <candidate-path> --target claude|codex --dry-run\n\nSubcommands:\n examples List draft examples\n authoring-packet [goal] Emit the C3 packet for external-agent workflow authoring; no intent modeling or mutation\n intake <description> Review a workflow request and recommend reuse or authoring path\n route <description> Show the personal no-canvas route: describe, author, validate, run; use --org for organization rollout gates\n suggestions <asset> Suggest human-reviewed workflow improvements from evidence without mutation\n mine [asset] Find candidate workflow assets or follow-up drafts from real evidence\n draft <description> Clone a built-in example as a scaffold fallback; structure is not derived from the goal\n edit-plan <instruction> Preview a workflow edit without writing DNA or runtime files\n review-suggestion Persist accept/reject/defer for an evidence-backed suggestion\n improve-from-suggestions Build a reviewable edit plan from an accepted asset suggestion\n from-candidate <id> Act on a dogfood-backed candidate without copying a long command\n promote-candidate <path> Revalidate and explicitly copy exact candidate bytes into .dna/templates\n project-candidate <path> Dry-run an unpromoted candidate through Claude or Codex projection\n\nOptions:\n --name <org> Organization name for --org route planning\n --project <project> Project name for --org route planning\n --sync-target <target> Runtime surface for --org route planning, such as codex or claude\n --target claude|codex Projection target for project-candidate\n --dry-run Required for project-candidate; never writes project artifacts\n --org Include organization binding, configure, rollout, sync, deploy, improve, and evolution gates\n --from-template <name> Source workflow asset for route/edit/candidate commands\n --workflow <id> Select a workflow inside a multi-workflow asset template such as fix or behavior-lock\n --suggestion <id> Suggestion id such as template-model-verifier or template-blocked-triage\n --decision <decision> For review-suggestion: accept|reject|defer\n --save-template <name> Promotion target name, or reviewed draft/scaffold name for legacy commands\n --project-dir <path> Read/write workflow assets in another project directory\n --force Overwrite an existing saved workflow asset draft\n --operation <op> Optional override; otherwise auto-chosen from the instruction\n --target-step <id> Optional override; otherwise auto-chosen from the edit\n --role <role> Optional override; otherwise auto-chosen/defaulted from the edit\n\nExamples:\n dna workflow examples\n dna workflow authoring-packet "Create a code review workflow" --json\n dna workflow intake "Rewrite module with logic equivalence"\n dna workflow route "Rewrite module with logic equivalence"\n dna workflow route "Rewrite module with logic equivalence" --org --name "Project Admin" --project "Mobile Rewrite" --sync-target codex\n dna workflow project-candidate .dna/authoring/source.candidate.dna.yaml --target claude --dry-run\n dna workflow promote-candidate .dna/authoring/source.candidate.dna.yaml --save-template source-reviewed\n dna workflow suggestions ${WORKFLOW_ASSET_IDS.default} --json\n dna workflow mine ${WORKFLOW_ASSET_IDS.default} --json\n dna workflow draft "Rewrite module with logic equivalence" --example rewrite_governance --strictness high # scaffold fallback only\n dna workflow draft "Rewrite module with logic equivalence" --save-template team-rewrite-flow # scaffold fallback only\n dna workflow edit-plan "Add equivalence verifier after rewrite" --from-template team-rewrite-flow --save-template team-rewrite-flow-v2\n dna workflow review-suggestion --from-template ${WORKFLOW_ASSET_IDS.default} --workflow fix --suggestion template-model-verifier --decision accept\n dna workflow improve-from-suggestions --from-template ${WORKFLOW_ASSET_IDS.default} --workflow fix --suggestion template-model-verifier --save-template ${WORKFLOW_ASSET_IDS.default}-v2\n dna workflow from-candidate extract-diagnosis-review-${WORKFLOW_ASSET_IDS.default} --from-template ${WORKFLOW_ASSET_IDS.default} --save-template ${WORKFLOW_ASSET_IDS.rewriteDiagnosisReview}\n`,
|
|
229
277
|
org: `Usage: dna org <intake|configure-plan|route|rollout|init|bind|status|review|receipt> [description] [options]\n\nSubcommands:\n intake [description] Plan organization/project setup and asset binding without writing files\n configure-plan List explicit dna init commands for declared assets missing project config\n route Show the organization operating route and rollout readiness without syncing\n rollout Review sync/downstream rollout readiness without syncing (alias-compatible with route)\n init Create local .dna/org.yaml with organization/project bindings\n bind Add or update a workflow asset binding for a project\n status Show local organization, projects, assets, sync targets, and evidence totals\n review Show manager-facing gaps and next actions\n receipt Emit intentdna.org_review_receipt.v1 from local org review and rollout data\n\nOptions:\n --name <organization> Organization name for intake or init\n --project <project> Project name/id for intake, init, or bind\n --asset <asset> Bind a workflow asset such as ${WORKFLOW_ASSET_IDS.default}\n --status <status> planned|active|paused for org bind (default planned)\n --sync-target <target> Declare a target such as codex or claude\n --project-dir <path> Read/write organization state in a different project directory\n --apply For configure-plan only: create missing .dna/configs from declared assets\n --json Print JSON to stdout\n\nBoundaries:\n - org receipt is local projection evidence only; cloud_authority=false\n - internal_ready candidates are adoption candidates, not org-private SaaS visibility\n - No online org auth, permissions, backend persistence, or cloud storage is implied\n\nExamples:\n dna org intake "Mobile rewrite team" --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex\n dna org configure-plan\n dna org configure-plan --apply\n dna org route\n dna org rollout\n dna org receipt --json\n dna org init --name "My Org" --project "Mobile Rewrite" --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex\n dna org bind --asset team-rewrite-flow-v2 --status active --sync-target codex\n dna org review\n`,
|
|
230
278
|
release: `Usage: dna release <deploy-plan|evidence> [files...] [--json]\n\nSubcommands:\n deploy-plan Read changed files and decide whether Vercel and/or Supabase release verification is required\n evidence Record deploy-plan, deployed URL, checked routes, and cloud checks as intentdna.release_evidence.v1\n\nOptions:\n --json Print JSON to stdout\n --output <path> For evidence: write release evidence JSON (default .dna/release/latest-release-evidence.json)\n --deployment-url <url> For evidence: deployed URL captured from Vercel CLI stdout when web routes changed\n --checked-route <route> For evidence: route verified on the deployed URL (repeatable or comma-separated)\n --checked-cloud-check <id> For evidence: cloud check completed, such as cloud-contract-check or cloud-edge-check (repeatable or comma-separated)\n --dry-run For evidence: do not write the evidence file\n\nBoundaries:\n - CLI/core/runtime/docs/wiki changes do not require Vercel deployment by themselves\n - Web/public surfaces require Vercel CLI deploy only when reviewers or users need a deployed URL\n - Supabase SaaS surfaces require cloud contract, Edge Function, deploy-plan, remote secret-name presence, Vercel public env presence, function health, and live ingest-smoke evidence before production release claims\n - Deployment is separate from org rollout and runtime sync\n - A web deploy is not complete until the deployed URL is opened or fetched and verified\n - A cloud deploy is not complete until Supabase migrations/functions/secrets, Vercel public env presence, and ingestion smoke evidence are recorded\n - Release evidence records supplied checks; it does not run build, deploy, URL verification, Supabase commands, sync, or policy enforcement\n\nExamples:\n dna release deploy-plan\n dna release deploy-plan apps/online/src/main.ts\n dna release deploy-plan src/cli/index.ts --json\n dna release deploy-plan supabase/functions/ingest-report/index.ts --json\n dna release evidence apps/online/src/main.ts --deployment-url https://intentdna.vercel.app --checked-route / --checked-route '/?mode=public' --checked-route '/?mode=public&embed=1' --checked-route /runtime --checked-route /templates --checked-route /readiness --json\n dna release evidence supabase/functions/ingest-report/index.ts --checked-cloud-check cloud-contract-check --checked-cloud-check cloud-edge-check --checked-cloud-check cloud-deploy-plan --checked-cloud-check cloud-function-health --checked-cloud-check cloud-secrets-check --checked-cloud-check cloud-vercel-env-check --checked-cloud-check cloud-ingest-smoke --json\n`,
|
|
231
279
|
auth: `Usage: dna auth status [--auth-config-dir <dir>] [--json]\n dna auth token set <token> [--auth-config-dir <dir>] [--json]\n dna auth token clear [--auth-config-dir <dir>] [--json]\n dna auth user-jwt status [--auth-config-dir <dir>] [--json]\n dna auth user-jwt set <jwt> [--auth-config-dir <dir>] [--json]\n dna auth user-jwt clear [--auth-config-dir <dir>] [--json]\n dna auth bootstrap-account [--org <name>] [--project <name>] [options]\n dna auth onboard [--project-id <id>] [options]\n dna auth issue-token --project-id <id> [options]\n dna auth projects [options]\n dna auth tokens list [options]\n dna auth tokens revoke <token-id> [--yes] [options]\n\nSubcommands:\n status Show local CLI API token status without network validation\n token set <token> Store a CLI API token in user config outside the project repository\n token clear Remove the stored CLI API token; idempotent if already absent\n user-jwt status Show local Supabase user JWT account bridge status without network validation\n user-jwt set <jwt> Store a Supabase user JWT for account onboarding commands outside the project repository\n user-jwt clear Remove the stored Supabase user JWT; idempotent if already absent\n bootstrap-account Create/reuse Supabase account org/project with a user JWT; token issuance remains dna auth onboard\n onboard Discover account projects, select one safely, issue a CLI API token, and store it locally\n issue-token Call Supabase issue-api-token with a user JWT and store the issued CLI token\n projects Call Supabase list-projects with a user JWT for account onboarding projection\n tokens list Call Supabase manage-api-tokens to list API token metadata only\n tokens revoke <token-id> Revoke an API token after explicit --yes confirmation\n\nOptions:\n --org <name> Organization name for account bootstrap\n --project <name> Project name for account bootstrap\n --org-slug <slug> Optional organization slug for account bootstrap\n --project-slug <slug> Optional project slug for account bootstrap\n --project-hint <path> Optional local project hint stored as account bootstrap metadata\n --project-id <id> Supabase projects.id for issue-token or token filtering\n --organization-id <id> Optional organization id to cross-check or filter\n --token-id <id> API token id for revoke or filtering\n --include-revoked Include revoked API token metadata in tokens list\n --limit <n> Maximum token summaries to request, capped at 100\n --user-jwt <jwt> Supabase user access token override; env or dna auth user-jwt set can also supply it\n --endpoint <url> Edge Function URL; defaults from INTENTDNA_CLOUD_URL\n --auth-config-dir <dir> Read/write CLI API token and user JWT config in a specific directory for isolated local checks\n --token-name <name> Display name for the issued CLI token\n --scope <scope> Requested scope; repeatable or comma-separated, defaults to report:ingest\n --expires-at <iso> Optional token expiry timestamp\n --dry-run Build the request without making a network call or storing a token\n --yes Required before live dna auth tokens revoke mutates account auth state\n --json Print JSON to stdout\n\nBoundaries:\n - CLI ingestion auth uses IntentDNA API tokens, not MCP authorization\n - dna auth bootstrap-account is an onboarding mutation only; it does not issue CLI tokens, upload reports, publish templates, or run workflows\n - dna auth onboard is a CLI onboarding convenience over projects plus issue-token; it does not guess between multiple projects\n - Supabase user JWTs are account onboarding credentials for projects, issue-token, and token management; they are not CLI ingestion API tokens\n - User JWTs are stored only by explicit dna auth user-jwt set and output uses masked previews only\n - Token status is local until cloud token verification exists\n - Raw tokens are not printed after set or issue-token; token list/revoke never prints raw tokens or token hashes\n - Service role keys are server-only and rejected as CLI/user tokens when detected\n - Auth state and account projections do not grant runtime allow/warn/block/validate authority\n\nExamples:\n dna auth status --json\n dna auth token set idna_example_token --json\n dna auth token set idna_example_token --auth-config-dir /tmp/intentdna-auth --json\n dna auth status --auth-config-dir /tmp/intentdna-auth --json\n dna auth token clear --json\n dna auth user-jwt status --json\n dna auth user-jwt set eyJhbGciOi... --json\n dna auth user-jwt clear --json\n dna auth bootstrap-account --org "My Org" --project "IntentDNA" --dry-run --json\n dna auth bootstrap-account --org "My Org" --project "IntentDNA" --json\n dna auth onboard --dry-run --json\n dna auth onboard --project-id 00000000-0000-4000-8000-000000000000 --json\n dna auth issue-token --project-id 00000000-0000-4000-8000-000000000000 --dry-run --json\n dna auth issue-token --project-id 00000000-0000-4000-8000-000000000000 --token-name "Laptop CLI" --json\n dna auth projects --dry-run --json\n dna auth tokens list --project-id 00000000-0000-4000-8000-000000000000 --dry-run --json\n dna auth tokens revoke token_123 --yes --json\n`,
|
|
@@ -235,6 +283,7 @@ Boundaries:
|
|
|
235
283
|
context: `Usage: dna context <index|search|doc> [query|id] [files...]\n\nSubcommands:\n index List explicitly declared planning-only advisory context sources\n search <query> Search source metadata\n doc <id> Read a local file/doc source body\n`,
|
|
236
284
|
run: `Usage:
|
|
237
285
|
dna run [start] --dna <file> --workflow <name> --task <id> [options]
|
|
286
|
+
dna run asset-refinery --var source_packet=<path> --var candidate_path=<path> [--dry-run]
|
|
238
287
|
dna run status <run-id> [--json] [--project-dir <path>]
|
|
239
288
|
dna run inspect <run-id> [--json] [--project-dir <path>]
|
|
240
289
|
dna run resume <run-id> [--json] [--project-dir <path>]
|
|
@@ -249,6 +298,7 @@ Actions:
|
|
|
249
298
|
|
|
250
299
|
Options:
|
|
251
300
|
--run-id <id> Explicit run id; lifecycle actions also accept a positional id
|
|
301
|
+
--var <key=value> Set a workflow variable; repeat for multiple values
|
|
252
302
|
--dry-run Print the compiled Controller plan without starting a run
|
|
253
303
|
--provider <name> claude|codex (default: claude)
|
|
254
304
|
--provider-executable <path> Override the selected provider executable
|
|
@@ -483,13 +533,49 @@ async function main() {
|
|
|
483
533
|
vars[v.slice(0, eqIdx)] = v.slice(eqIdx + 1);
|
|
484
534
|
}
|
|
485
535
|
}
|
|
536
|
+
let dnaFiles = runValues.dna ?? runPositionals;
|
|
537
|
+
let workflowName = runValues.workflow;
|
|
538
|
+
let taskId = runValues.task;
|
|
539
|
+
if (runAction === "start"
|
|
540
|
+
&& !runValues.dna
|
|
541
|
+
&& runPositionals.length === 1) {
|
|
542
|
+
const templateName = runPositionals[0];
|
|
543
|
+
const projectDir = runValues["project-dir"];
|
|
544
|
+
const { findTemplateCatalogEntry } = await import("../templates/catalog.js");
|
|
545
|
+
const template = await findTemplateCatalogEntry(templateName, {
|
|
546
|
+
projectDir,
|
|
547
|
+
});
|
|
548
|
+
if (template) {
|
|
549
|
+
if (template.name === "asset-refinery") {
|
|
550
|
+
const variableError = normalizeAssetRefineryVariables(resolve(projectDir ?? process.cwd()), vars);
|
|
551
|
+
if (variableError) {
|
|
552
|
+
process.stderr.write(`Error: ${variableError}\n`);
|
|
553
|
+
return exitWith(2);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
dnaFiles = [template.path];
|
|
557
|
+
taskId ??= template.name;
|
|
558
|
+
if (!workflowName) {
|
|
559
|
+
const { loadDNA } = await import("../compiler/index.js");
|
|
560
|
+
const dna = await loadDNA(template.path);
|
|
561
|
+
const workflowNames = Object.keys(dna.workflows ?? {});
|
|
562
|
+
if (workflowNames.length !== 1) {
|
|
563
|
+
process.stderr.write(`Error: template '${template.name}' has ${workflowNames.length} workflows; select one with --workflow.\n`);
|
|
564
|
+
return exitWith(2);
|
|
565
|
+
}
|
|
566
|
+
workflowName = dna.namespace
|
|
567
|
+
? `${dna.namespace}_${workflowNames[0]}`
|
|
568
|
+
: workflowNames[0];
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
486
572
|
const { runRun } = await import("./commands/run.js");
|
|
487
573
|
const code = await runRun({
|
|
488
574
|
action: runAction,
|
|
489
575
|
runId: optionRunId ?? positionalRunId,
|
|
490
|
-
dnaFiles
|
|
491
|
-
workflowName
|
|
492
|
-
taskId
|
|
576
|
+
dnaFiles,
|
|
577
|
+
workflowName,
|
|
578
|
+
taskId,
|
|
493
579
|
context: runValues.context,
|
|
494
580
|
vars: Object.keys(vars).length > 0 ? vars : undefined,
|
|
495
581
|
dryRun: runValues["dry-run"],
|
|
@@ -869,6 +955,9 @@ async function main() {
|
|
|
869
955
|
"source-dir": { type: "string", multiple: true },
|
|
870
956
|
output: { type: "string", short: "o" },
|
|
871
957
|
focus: { type: "string", default: "all" },
|
|
958
|
+
snapshot: { type: "boolean", default: false },
|
|
959
|
+
packet: { type: "boolean", default: false },
|
|
960
|
+
write: { type: "string" },
|
|
872
961
|
candidate: { type: "boolean", default: false },
|
|
873
962
|
"save-template": { type: "string" },
|
|
874
963
|
org: { type: "string" },
|
|
@@ -907,6 +996,21 @@ async function main() {
|
|
|
907
996
|
return exitWith(code);
|
|
908
997
|
}
|
|
909
998
|
if (subcommand === "sources") {
|
|
999
|
+
if (templateValues.snapshot
|
|
1000
|
+
|| templateValues.packet
|
|
1001
|
+
|| templateValues.write) {
|
|
1002
|
+
const { runSourceAssets } = await import("./commands/source-assets.js");
|
|
1003
|
+
const code = await runSourceAssets({
|
|
1004
|
+
projectDir: templateValues["project-dir"],
|
|
1005
|
+
sourceDirs: templateValues["source-dir"],
|
|
1006
|
+
sourceId: templatePositionals[0],
|
|
1007
|
+
snapshot: templateValues.snapshot,
|
|
1008
|
+
packet: templateValues.packet,
|
|
1009
|
+
write: templateValues.write,
|
|
1010
|
+
json: templateValues.json,
|
|
1011
|
+
});
|
|
1012
|
+
return exitWith(code);
|
|
1013
|
+
}
|
|
910
1014
|
const focus = templateValues.focus;
|
|
911
1015
|
if (!["all", "refresh", "gaps"].includes(focus)) {
|
|
912
1016
|
process.stderr.write("Error: --focus must be one of: all, refresh, gaps\n");
|
|
@@ -1024,7 +1128,9 @@ async function main() {
|
|
|
1024
1128
|
name: { type: "string" },
|
|
1025
1129
|
project: { type: "string" },
|
|
1026
1130
|
"sync-target": { type: "string" },
|
|
1131
|
+
target: { type: "string" },
|
|
1027
1132
|
"project-dir": { type: "string" },
|
|
1133
|
+
"dry-run": { type: "boolean", default: false },
|
|
1028
1134
|
force: { type: "boolean", default: false },
|
|
1029
1135
|
org: { type: "boolean", default: false },
|
|
1030
1136
|
json: { type: "boolean", default: false },
|
|
@@ -1033,6 +1139,56 @@ async function main() {
|
|
|
1033
1139
|
allowPositionals: true,
|
|
1034
1140
|
strict: false,
|
|
1035
1141
|
});
|
|
1142
|
+
const projectDir = workflowValues["project-dir"] ?? process.cwd();
|
|
1143
|
+
if (subcommand === "promote-candidate") {
|
|
1144
|
+
const candidatePath = workflowPositionals[0];
|
|
1145
|
+
const templateName = workflowValues["save-template"];
|
|
1146
|
+
if (!candidatePath || !templateName) {
|
|
1147
|
+
process.stderr.write("Error: promote-candidate requires <candidate-path> and --save-template <name>.\n");
|
|
1148
|
+
return exitWith(2);
|
|
1149
|
+
}
|
|
1150
|
+
try {
|
|
1151
|
+
const { promoteCandidate } = await import("./commands/candidate-promotion.js");
|
|
1152
|
+
const result = await promoteCandidate({
|
|
1153
|
+
projectDir,
|
|
1154
|
+
candidatePath,
|
|
1155
|
+
templateName,
|
|
1156
|
+
});
|
|
1157
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
1158
|
+
return exitWith(0);
|
|
1159
|
+
}
|
|
1160
|
+
catch (error) {
|
|
1161
|
+
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1162
|
+
return exitWith(1);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
if (subcommand === "project-candidate") {
|
|
1166
|
+
const candidatePath = workflowPositionals[0];
|
|
1167
|
+
const target = workflowValues.target;
|
|
1168
|
+
if (!candidatePath || !["claude", "codex"].includes(target ?? "")) {
|
|
1169
|
+
process.stderr.write("Error: project-candidate requires <candidate-path> and --target claude|codex.\n");
|
|
1170
|
+
return exitWith(2);
|
|
1171
|
+
}
|
|
1172
|
+
if (!workflowValues["dry-run"]) {
|
|
1173
|
+
process.stderr.write("Error: project-candidate requires --dry-run.\n");
|
|
1174
|
+
return exitWith(2);
|
|
1175
|
+
}
|
|
1176
|
+
try {
|
|
1177
|
+
const { projectCandidateDryRun } = await import("../workflow/candidate-projection.js");
|
|
1178
|
+
const result = await projectCandidateDryRun({
|
|
1179
|
+
candidatePath,
|
|
1180
|
+
projectDir,
|
|
1181
|
+
target: target,
|
|
1182
|
+
packageVersion: version,
|
|
1183
|
+
});
|
|
1184
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
1185
|
+
return exitWith(0);
|
|
1186
|
+
}
|
|
1187
|
+
catch (error) {
|
|
1188
|
+
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1189
|
+
return exitWith(1);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1036
1192
|
const { runWorkflow } = await import("./commands/workflow.js");
|
|
1037
1193
|
const code = await runWorkflow({
|
|
1038
1194
|
subcommand,
|
package/dist/compiler/cascade.js
CHANGED
|
@@ -251,7 +251,7 @@ export function cascadeDNA(layers) {
|
|
|
251
251
|
const ns = dna.namespace;
|
|
252
252
|
// Merge genes (cross-namespace: additive merge + warning)
|
|
253
253
|
const origin = originForDNA(dna);
|
|
254
|
-
for (const [name, rawGene] of Object.entries(dna.genes)) {
|
|
254
|
+
for (const [name, rawGene] of Object.entries(dna.genes ?? {})) {
|
|
255
255
|
const gene = withCodonOrigins(rawGene, origin);
|
|
256
256
|
if (origin.protected_threshold && gene.codons.some((codon) => codon.type === "threshold")) {
|
|
257
257
|
protectedThresholdGenes.add(name);
|
package/dist/hooks/cli.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ import type { HookEvent, HookOutput } from "./protocol.js";
|
|
|
19
19
|
import { blockOutput } from "./protocol.js";
|
|
20
20
|
import { readWorkflowState } from "./state.js";
|
|
21
21
|
import type { VerifierResultEntry } from "./state.js";
|
|
22
|
+
interface HookRuntimePaths {
|
|
23
|
+
projectDir: string;
|
|
24
|
+
irPath: string;
|
|
25
|
+
}
|
|
26
|
+
declare function resolveHookRuntimePaths(cwd: string, irPath?: string, explicitIRPath?: boolean): Promise<HookRuntimePaths>;
|
|
22
27
|
export interface SessionSummary {
|
|
23
28
|
total: number;
|
|
24
29
|
blocks: number;
|
|
@@ -91,6 +96,7 @@ export declare const recordProducedArtifactsForTest: typeof recordProducedArtifa
|
|
|
91
96
|
export declare const resolveWorkflowArtifactFactsForTest: typeof resolveWorkflowArtifactFacts;
|
|
92
97
|
export declare const readWorkflowStateForHookTest: typeof readWorkflowStateForHook;
|
|
93
98
|
export declare const runCodexHookWithLoadedIrForTest: typeof runCodexHookWithLoadedIr;
|
|
99
|
+
export declare const resolveHookRuntimePathsForTest: typeof resolveHookRuntimePaths;
|
|
94
100
|
export declare const inferWorkflowAssetFromIrForTest: typeof inferWorkflowAssetFromIr;
|
|
95
101
|
export declare const resolveWorkflowArtifactFactsForHookTest: typeof resolveWorkflowArtifactFactsForHook;
|
|
96
102
|
export declare const finalizeAndResolveArtifactsForHookTest: typeof finalizeAndResolveArtifactsForHook;
|