@harness-engineering/cli 3.1.0 → 4.0.1
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/dist/agents/personas/harness-pm.yaml +33 -0
- package/dist/agents/skills/claude-code/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/claude-code/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/claude-code/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/claude-code/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/claude-code/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/claude-code/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/claude-code/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/claude-code/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/claude-code/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/claude-code/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/codex/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/codex/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/codex/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/codex/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/codex/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/codex/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/codex/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/codex/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/codex/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/codex/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/codex/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/codex/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/codex/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/codex/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/codex/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/codex/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/codex/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/codex/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/codex/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/cursor/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/cursor/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/cursor/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/cursor/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/cursor/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/cursor/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/cursor/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/cursor/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/cursor/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/cursor/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/cursor/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/cursor/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/cursor/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/cursor/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/cursor/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/cursor/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/cursor/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/cursor/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/cursor/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/gemini-cli/acceptance-eval/SKILL.md +92 -0
- package/dist/agents/skills/gemini-cli/acceptance-eval/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/harness-brainstorming/SKILL.md +46 -38
- package/dist/agents/skills/gemini-cli/harness-brainstorming/skill.yaml +1 -0
- package/dist/agents/skills/gemini-cli/harness-code-review/SKILL.md +10 -11
- package/dist/agents/skills/gemini-cli/harness-execution/SKILL.md +24 -26
- package/dist/agents/skills/gemini-cli/harness-integration/SKILL.md +21 -19
- package/dist/agents/skills/gemini-cli/harness-maintenance-pipeline/SKILL.md +173 -0
- package/dist/agents/skills/gemini-cli/harness-maintenance-pipeline/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-onboarding/SKILL.md +2 -0
- package/dist/agents/skills/gemini-cli/harness-planning/SKILL.md +17 -40
- package/dist/agents/skills/gemini-cli/harness-pulse/SKILL.md +1 -1
- package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +17 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap-pilot/SKILL.md +8 -0
- package/dist/agents/skills/gemini-cli/harness-verification/SKILL.md +9 -12
- package/dist/agents/skills/gemini-cli/initialize-harness-project/SKILL.md +112 -126
- package/dist/agents/skills/gemini-cli/outcome-eval/SKILL.md +1 -0
- package/dist/agents/skills/gemini-cli/product-advisor/SKILL.md +202 -0
- package/dist/agents/skills/gemini-cli/product-advisor/skill.yaml +74 -0
- package/dist/agents/skills/tests/interaction-channel.test.ts +64 -0
- package/dist/{agents-md-YYCLGMBF.js → agents-md-VJLYEH2S.js} +4 -4
- package/dist/{analyzer-V633GUHY-MBCQWKDU.js → analyzer-V633GUHY-OV335HGM.js} +2 -2
- package/dist/{architecture-5KPP4ID4.js → architecture-YQH2NYXY.js} +5 -5
- package/dist/{assess-project-B6ENHUAU.js → assess-project-KOTAPAHD.js} +1 -1
- package/dist/bin/harness-mcp.js +19 -18
- package/dist/bin/harness.js +31 -29
- package/dist/{check-phase-gate-REG3HWYC.js → check-phase-gate-CHU2E3OU.js} +6 -5
- package/dist/{chunk-UBTMPO5H.js → chunk-36GQREOE.js} +3 -3
- package/dist/{chunk-CLI4K2CH.js → chunk-4U5LDFCY.js} +1 -1
- package/dist/{chunk-IF3JK3G5.js → chunk-4VXFZSYF.js} +1 -1
- package/dist/{chunk-TE5YHHHZ.js → chunk-5RSXUAMN.js} +1 -1
- package/dist/{chunk-YF3AY6KS.js → chunk-6SCYTIF4.js} +6 -6
- package/dist/{chunk-N55WOGN3.js → chunk-6YFHUIGT.js} +1 -1
- package/dist/{chunk-RGQXHCCH.js → chunk-7PJCK7UE.js} +8 -8
- package/dist/{chunk-LMZ2JTNP.js → chunk-7TIJXWG3.js} +5 -9
- package/dist/chunk-AAUY53CC.js +61 -0
- package/dist/{chunk-XEOSSKIB.js → chunk-AX5KGRM6.js} +48 -4
- package/dist/{chunk-FUH4J43G.js → chunk-E5EW5HVJ.js} +2 -2
- package/dist/{chunk-C2ZGWMTN.js → chunk-EYMOPFSD.js} +2 -2
- package/dist/{chunk-FL5SLUKZ.js → chunk-GHBFNLV2.js} +2374 -1095
- package/dist/{chunk-HIPBU2Q4.js → chunk-I3CGCZJF.js} +9 -9
- package/dist/{chunk-OQFEFVIN.js → chunk-JPVOI7GP.js} +7 -7
- package/dist/{chunk-DNX35Q5K.js → chunk-M7F2PPN3.js} +3 -3
- package/dist/{chunk-A65QO5KN.js → chunk-MMLQPHZ5.js} +3032 -1166
- package/dist/{chunk-ERZCC5VH.js → chunk-OQ6KOQEV.js} +9 -9
- package/dist/{chunk-ZOUJP3EY.js → chunk-RG3TNIUB.js} +1659 -808
- package/dist/{chunk-PZX2Y3RV.js → chunk-SDMV4QHM.js} +5 -5
- package/dist/{chunk-XZ2Q4UTW.js → chunk-SEA2PFVI.js} +1 -1
- package/dist/{chunk-TCVQVHEF.js → chunk-T746REAE.js} +1 -1
- package/dist/{chunk-6B6UN6SG.js → chunk-UTJJJDNN.js} +11 -1
- package/dist/{chunk-BXKNWSG4.js → chunk-UWVMJEUJ.js} +1 -1
- package/dist/{chunk-WWACIIBA.js → chunk-V3ZQUCRH.js} +1 -1
- package/dist/{chunk-27AJKSQY.js → chunk-WBVCN35T.js} +1 -1
- package/dist/{chunk-PP6ZRL5T.js → chunk-WZJR6SOI.js} +536 -422
- package/dist/{chunk-YQAFKOOL.js → chunk-XAVMTAUT.js} +2 -2
- package/dist/chunk-Y6SUQC32.js +9 -0
- package/dist/{chunk-ZRKFDE6M.js → chunk-YANR2RL7.js} +1 -1
- package/dist/{chunk-2N4OENGE.js → chunk-YYFSFSB3.js} +1 -1
- package/dist/{ci-workflow-JEYYCBOC.js → ci-workflow-HO4WKGNG.js} +4 -4
- package/dist/{dist-3HW4LCHE.js → dist-6D2F2J57.js} +73 -17
- package/dist/{dist-OWHMNL4W.js → dist-DWBTZXR5.js} +1 -1
- package/dist/{docs-YRMW7UED.js → docs-FP47JONV.js} +5 -5
- package/dist/{engine-E7H5U3AC.js → engine-YUA6IYOG.js} +4 -4
- package/dist/{entropy-3JBKCGJJ.js → entropy-DBW2INZU.js} +4 -4
- package/dist/{feedback-U6VJ6AUJ.js → feedback-BPHADTRQ.js} +1 -1
- package/dist/{generate-agent-definitions-S2FRZF4Y.js → generate-agent-definitions-KPVGBGDY.js} +6 -6
- package/dist/{glob-helper-GLZAURJC.js → glob-helper-VR6UCZZB.js} +1 -1
- package/dist/{graph-loader-HHXN5FLP.js → graph-loader-STFGYKZH.js} +1 -1
- package/dist/hooks/adoption-tracker.js +6 -5
- package/dist/hooks/protect-config.js +15 -5
- package/dist/{index-builder-3AOQ3ZII.js → index-builder-52IJJHJC.js} +2 -2
- package/dist/index.d.ts +8 -8
- package/dist/index.js +31 -29
- package/dist/{loader-RGQJYERV.js → loader-QOJQ6NZM.js} +4 -4
- package/dist/{mcp-NDTFZXWF.js → mcp-ZPX6O767.js} +21 -20
- package/dist/{performance-FPWKC4CN.js → performance-FXYTGJGQ.js} +5 -5
- package/dist/{review-pipeline-WUHG7PHO.js → review-pipeline-2TFQ5OAE.js} +4 -4
- package/dist/{runtime-Q3ORD7LW.js → runtime-XK6ZCHKE.js} +4 -4
- package/dist/{scan-P7YFKB77.js → scan-IYSVRPD2.js} +1 -1
- package/dist/{security-JDHTRBGC.js → security-4W2P5ZGI.js} +1 -1
- package/dist/{skill-executor-MOCUIAYS.js → skill-executor-BGUCAVBU.js} +2 -2
- package/dist/state-events-ECQAIZLU.js +25 -0
- package/dist/{validate-G3LKBOYA.js → validate-64KTEGIE.js} +5 -5
- package/dist/{validate-cross-check-4ITA72DF.js → validate-cross-check-J5PVGICB.js} +4 -4
- package/package.json +7 -7
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: product-advisor
|
|
2
|
+
version: "0.1.0"
|
|
3
|
+
description: Upstream client-inception skill. Ingests a diagram + client conversation notes, drafts a Business Requirements Document (BRD), detects gaps against a fixed completeness rubric, resolves them through a one-question-at-a-time interview with the solution architect, then fans the BRD out into candidate roadmap items and offers a STRATEGY.md seed. Reads but never writes STRATEGY.md; never authors specs (harness-brainstorming owns that). The pre-inception front door to the harness pipeline.
|
|
4
|
+
stability: static
|
|
5
|
+
cognitive_mode: configuration-interviewer
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
- cursor
|
|
12
|
+
- codex
|
|
13
|
+
tools:
|
|
14
|
+
- Bash
|
|
15
|
+
- Read
|
|
16
|
+
- Write
|
|
17
|
+
- Edit
|
|
18
|
+
- Glob
|
|
19
|
+
- Grep
|
|
20
|
+
cli:
|
|
21
|
+
command: harness skill run product-advisor
|
|
22
|
+
args:
|
|
23
|
+
- name: engagement
|
|
24
|
+
description: Short name/slug for the client engagement. Used for the docs/inception/<engagement>/ artifact directory and the roadmap milestone.
|
|
25
|
+
required: false
|
|
26
|
+
- name: diagram
|
|
27
|
+
description: Path to a diagram (Mermaid/D2/PlantUML source or an image attachment) to ingest. Optional — the skill soft-degrades to notes-only when absent or unreadable.
|
|
28
|
+
required: false
|
|
29
|
+
- name: notes
|
|
30
|
+
description: Path to client conversation notes / call transcript to ingest.
|
|
31
|
+
required: false
|
|
32
|
+
mcp:
|
|
33
|
+
tool: run_skill
|
|
34
|
+
input:
|
|
35
|
+
skill: product-advisor
|
|
36
|
+
path: string
|
|
37
|
+
type: rigid
|
|
38
|
+
tier: 1
|
|
39
|
+
phases:
|
|
40
|
+
- name: ingest
|
|
41
|
+
description: Load diagram(s) + client conversation notes; reuse the business-knowledge diagram/vision path; normalize into a structured intake (entities, flows, notes). Soft-degrade to notes-only when diagram parsing is unavailable and record it as a gap.
|
|
42
|
+
required: true
|
|
43
|
+
- name: draft-brd
|
|
44
|
+
description: Synthesize a first BRD from intake into docs/inception/<engagement>/brd.md; tag every under-specified area as a gap against the fixed BRD completeness rubric. Behavioral requirements use EARS phrasing.
|
|
45
|
+
required: true
|
|
46
|
+
- name: gap-interview
|
|
47
|
+
description: Walk the solution architect through the gap queue one question at a time (plain-text tables); fold each answer back into the BRD; mark unresolved gaps as client-facing questions.
|
|
48
|
+
required: true
|
|
49
|
+
- name: finalize
|
|
50
|
+
description: Write brd.md + gaps.md (Resolved vs Open/client-facing); offer a STRATEGY.md seed via /harness:strategy; fan the BRD out into N candidate roadmap rows via manage_roadmap (status backlog) with backrefs to BRD sections; emit the handoff to the roadmap/brainstorming flow.
|
|
51
|
+
required: true
|
|
52
|
+
state:
|
|
53
|
+
persistent: true
|
|
54
|
+
files:
|
|
55
|
+
- docs/inception/
|
|
56
|
+
depends_on:
|
|
57
|
+
- harness-strategy
|
|
58
|
+
- harness-brainstorming
|
|
59
|
+
related_skills:
|
|
60
|
+
- harness-strategy
|
|
61
|
+
- harness-brainstorming
|
|
62
|
+
- harness-ideate
|
|
63
|
+
- harness-roadmap-pilot
|
|
64
|
+
keywords:
|
|
65
|
+
- product-advisor
|
|
66
|
+
- BRD
|
|
67
|
+
- business-requirements
|
|
68
|
+
- requirements-elicitation
|
|
69
|
+
- gap-analysis
|
|
70
|
+
- diagram-ingestion
|
|
71
|
+
- roadmap-decomposition
|
|
72
|
+
- pre-inception
|
|
73
|
+
- solution-architect
|
|
74
|
+
- upstream-grounding
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// agents/skills/tests/interaction-channel.test.ts
|
|
2
|
+
//
|
|
3
|
+
// Guards the UX-channel invariant for skill prompts.
|
|
4
|
+
//
|
|
5
|
+
// `emit_interaction` with `type: 'question'` or `type: 'confirmation'` renders and
|
|
6
|
+
// records a prompt but does NOT display it to the human: the client collapses the
|
|
7
|
+
// call to "Called harness" and the rendered text only returns to the model. A skill
|
|
8
|
+
// that routes a user-facing ask through it leaves the human staring at "Called
|
|
9
|
+
// harness" while the agent narrates a question they cannot answer.
|
|
10
|
+
//
|
|
11
|
+
// User-facing asks must be made in PLAIN TEXT in the agent's own reply — the only
|
|
12
|
+
// channel that reliably reaches the human across every platform (Claude Code,
|
|
13
|
+
// Cursor, Codex, Gemini CLI). `AskUserQuestion` is Claude-Code-only and caps headers
|
|
14
|
+
// at 12 chars / 4 options, so it is not a portable substitute either.
|
|
15
|
+
//
|
|
16
|
+
// `type: 'transition'` is exempt: it does real work (saveHandoff + telemetry) and is
|
|
17
|
+
// not a question posed to the human.
|
|
18
|
+
|
|
19
|
+
import { describe, it, expect } from 'vitest';
|
|
20
|
+
import { glob } from 'glob';
|
|
21
|
+
import { readFileSync } from 'fs';
|
|
22
|
+
import { resolve, dirname } from 'path';
|
|
23
|
+
import { fileURLToPath } from 'url';
|
|
24
|
+
|
|
25
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
const SKILLS_DIR = resolve(__dirname, '..');
|
|
27
|
+
|
|
28
|
+
// Matches `type: "question"`, `type: 'confirmation'`, and inline `type: \`question\``
|
|
29
|
+
// forms — i.e. an emit_interaction ask aimed at the human. Does NOT match the prose
|
|
30
|
+
// rationale that names the tool ("do NOT route this through `emit_interaction`"),
|
|
31
|
+
// which never writes `type: question`.
|
|
32
|
+
const FORBIDDEN_ASK = /type:\s*["'`](question|confirmation)["'`]/;
|
|
33
|
+
|
|
34
|
+
describe('skill prompts use a human-visible channel', () => {
|
|
35
|
+
const skillMdFiles = glob.sync('**/SKILL.md', {
|
|
36
|
+
cwd: SKILLS_DIR,
|
|
37
|
+
ignore: ['**/node_modules/**', '**/tests/**'],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (skillMdFiles.length === 0) {
|
|
41
|
+
it.skip('no SKILL.md files found yet', () => {});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
it.each(skillMdFiles)(
|
|
46
|
+
'%s does not route a user-facing ask through emit_interaction (question/confirmation)',
|
|
47
|
+
(file) => {
|
|
48
|
+
const content = readFileSync(resolve(SKILLS_DIR, file), 'utf-8');
|
|
49
|
+
const offending = content
|
|
50
|
+
.split('\n')
|
|
51
|
+
.map((line, i) => ({ line, n: i + 1 }))
|
|
52
|
+
.filter(({ line }) => FORBIDDEN_ASK.test(line));
|
|
53
|
+
|
|
54
|
+
expect(
|
|
55
|
+
offending,
|
|
56
|
+
`${file} asks the human via emit_interaction at line(s) ` +
|
|
57
|
+
`${offending.map((o) => o.n).join(', ')}. ` +
|
|
58
|
+
`Ask in plain text in the reply instead — emit_interaction does not display ` +
|
|
59
|
+
`the prompt to the human (it collapses to "Called harness"). ` +
|
|
60
|
+
`type: 'transition' is exempt and uses a different type literal.`
|
|
61
|
+
).toHaveLength(0);
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateAgentsMd
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-T746REAE.js";
|
|
4
|
+
import "./chunk-MMLQPHZ5.js";
|
|
5
|
+
import "./chunk-6YFHUIGT.js";
|
|
6
6
|
import "./chunk-BDGTZRZ6.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-WZJR6SOI.js";
|
|
8
8
|
import "./chunk-QCLOIUMX.js";
|
|
9
9
|
import "./chunk-XARGEOJV.js";
|
|
10
10
|
import "./chunk-KFQGP6VL.js";
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
EntropyAnalyzer,
|
|
3
3
|
init_chunk_MUWJHO2S,
|
|
4
4
|
init_chunk_S4DTDJ6J
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6YFHUIGT.js";
|
|
6
6
|
import "./chunk-BDGTZRZ6.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-WZJR6SOI.js";
|
|
8
8
|
import {
|
|
9
9
|
init_chunk_7P6ASYW6
|
|
10
10
|
} from "./chunk-XARGEOJV.js";
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkDependenciesDefinition,
|
|
3
3
|
handleCheckDependencies
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-XZ2Q4UTW.js";
|
|
4
|
+
} from "./chunk-JPVOI7GP.js";
|
|
6
5
|
import "./chunk-RC3OI5NK.js";
|
|
6
|
+
import "./chunk-SEA2PFVI.js";
|
|
7
7
|
import "./chunk-W6Y7ZW3Y.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-MMLQPHZ5.js";
|
|
9
|
+
import "./chunk-6YFHUIGT.js";
|
|
10
10
|
import "./chunk-BDGTZRZ6.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-WZJR6SOI.js";
|
|
12
12
|
import "./chunk-QCLOIUMX.js";
|
|
13
13
|
import "./chunk-XARGEOJV.js";
|
|
14
14
|
import "./chunk-KFQGP6VL.js";
|
package/dist/bin/harness-mcp.js
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startServer
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-RG3TNIUB.js";
|
|
5
|
+
import "../chunk-OQ6KOQEV.js";
|
|
6
|
+
import "../chunk-M7F2PPN3.js";
|
|
7
|
+
import "../chunk-EYMOPFSD.js";
|
|
8
|
+
import "../chunk-6SCYTIF4.js";
|
|
9
|
+
import "../chunk-I3CGCZJF.js";
|
|
10
|
+
import "../chunk-SDMV4QHM.js";
|
|
11
|
+
import "../chunk-7PJCK7UE.js";
|
|
10
12
|
import "../chunk-IOW3MW2K.js";
|
|
11
|
-
import "../chunk-ERZCC5VH.js";
|
|
12
13
|
import "../chunk-3ISINLYT.js";
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
15
|
-
import "../chunk-
|
|
16
|
-
import "../chunk-XZ2Q4UTW.js";
|
|
17
|
-
import "../chunk-HIPBU2Q4.js";
|
|
14
|
+
import "../chunk-4U5LDFCY.js";
|
|
15
|
+
import "../chunk-36GQREOE.js";
|
|
16
|
+
import "../chunk-JPVOI7GP.js";
|
|
18
17
|
import "../chunk-RC3OI5NK.js";
|
|
18
|
+
import "../chunk-SEA2PFVI.js";
|
|
19
19
|
import "../chunk-W6Y7ZW3Y.js";
|
|
20
|
-
import "../chunk-
|
|
21
|
-
import "../chunk-
|
|
20
|
+
import "../chunk-WBVCN35T.js";
|
|
21
|
+
import "../chunk-UTJJJDNN.js";
|
|
22
22
|
import "../chunk-HIK6OEUF.js";
|
|
23
|
-
import "../chunk-
|
|
23
|
+
import "../chunk-Y6SUQC32.js";
|
|
24
|
+
import "../chunk-XAVMTAUT.js";
|
|
24
25
|
import "../chunk-ZCZD7FHU.js";
|
|
25
26
|
import "../chunk-EBJQ6N4M.js";
|
|
26
27
|
import "../chunk-3WGJMBKH.js";
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
28
|
+
import "../chunk-MMLQPHZ5.js";
|
|
29
|
+
import "../chunk-6YFHUIGT.js";
|
|
29
30
|
import "../chunk-BDGTZRZ6.js";
|
|
30
|
-
import "../chunk-
|
|
31
|
+
import "../chunk-WZJR6SOI.js";
|
|
31
32
|
import "../chunk-QCLOIUMX.js";
|
|
32
33
|
import "../chunk-XARGEOJV.js";
|
|
33
34
|
import "../chunk-KFQGP6VL.js";
|
package/dist/bin/harness.js
CHANGED
|
@@ -3,47 +3,49 @@ import {
|
|
|
3
3
|
createProgram,
|
|
4
4
|
installCommandTelemetry,
|
|
5
5
|
printFirstRunWelcome
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-
|
|
11
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-GHBFNLV2.js";
|
|
7
|
+
import "../chunk-YANR2RL7.js";
|
|
8
|
+
import "../chunk-T746REAE.js";
|
|
9
|
+
import "../chunk-AX5KGRM6.js";
|
|
10
|
+
import "../chunk-AAUY53CC.js";
|
|
11
|
+
import "../chunk-4VXFZSYF.js";
|
|
12
|
+
import "../chunk-E5EW5HVJ.js";
|
|
12
13
|
import "../chunk-KET4QQZB.js";
|
|
13
|
-
import "../chunk-
|
|
14
|
-
import "../chunk-
|
|
14
|
+
import "../chunk-YYFSFSB3.js";
|
|
15
|
+
import "../chunk-UWVMJEUJ.js";
|
|
15
16
|
import "../chunk-CQ553GZO.js";
|
|
16
17
|
import "../chunk-ZP5E7YET.js";
|
|
17
|
-
import "../chunk-
|
|
18
|
+
import "../chunk-5RSXUAMN.js";
|
|
18
19
|
import "../chunk-GISMXMVL.js";
|
|
19
|
-
import "../chunk-
|
|
20
|
+
import "../chunk-V3ZQUCRH.js";
|
|
20
21
|
import "../chunk-TEFCFC4H.js";
|
|
21
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-7TIJXWG3.js";
|
|
22
23
|
import {
|
|
23
24
|
dispatchSkillsFromGit
|
|
24
|
-
} from "../chunk-
|
|
25
|
-
import "../chunk-
|
|
26
|
-
import "../chunk-
|
|
27
|
-
import "../chunk-
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
25
|
+
} from "../chunk-RG3TNIUB.js";
|
|
26
|
+
import "../chunk-OQ6KOQEV.js";
|
|
27
|
+
import "../chunk-M7F2PPN3.js";
|
|
28
|
+
import "../chunk-EYMOPFSD.js";
|
|
29
|
+
import "../chunk-6SCYTIF4.js";
|
|
30
|
+
import "../chunk-I3CGCZJF.js";
|
|
31
|
+
import "../chunk-SDMV4QHM.js";
|
|
32
|
+
import "../chunk-7PJCK7UE.js";
|
|
30
33
|
import "../chunk-IOW3MW2K.js";
|
|
31
|
-
import "../chunk-ERZCC5VH.js";
|
|
32
34
|
import "../chunk-3ISINLYT.js";
|
|
33
|
-
import "../chunk-
|
|
34
|
-
import "../chunk-
|
|
35
|
-
import "../chunk-
|
|
36
|
-
import "../chunk-XZ2Q4UTW.js";
|
|
37
|
-
import "../chunk-HIPBU2Q4.js";
|
|
35
|
+
import "../chunk-4U5LDFCY.js";
|
|
36
|
+
import "../chunk-36GQREOE.js";
|
|
37
|
+
import "../chunk-JPVOI7GP.js";
|
|
38
38
|
import "../chunk-RC3OI5NK.js";
|
|
39
|
+
import "../chunk-SEA2PFVI.js";
|
|
39
40
|
import "../chunk-W6Y7ZW3Y.js";
|
|
40
|
-
import "../chunk-
|
|
41
|
-
import "../chunk-
|
|
41
|
+
import "../chunk-WBVCN35T.js";
|
|
42
|
+
import "../chunk-UTJJJDNN.js";
|
|
42
43
|
import "../chunk-HIK6OEUF.js";
|
|
44
|
+
import "../chunk-Y6SUQC32.js";
|
|
43
45
|
import {
|
|
44
46
|
findConfigFile,
|
|
45
47
|
loadConfig
|
|
46
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-XAVMTAUT.js";
|
|
47
49
|
import "../chunk-ZCZD7FHU.js";
|
|
48
50
|
import "../chunk-EBJQ6N4M.js";
|
|
49
51
|
import {
|
|
@@ -56,13 +58,13 @@ import {
|
|
|
56
58
|
readCheckState,
|
|
57
59
|
shouldRunCheck,
|
|
58
60
|
spawnBackgroundCheck
|
|
59
|
-
} from "../chunk-
|
|
61
|
+
} from "../chunk-MMLQPHZ5.js";
|
|
60
62
|
import {
|
|
61
63
|
CLI_VERSION
|
|
62
64
|
} from "../chunk-BM3PWGXQ.js";
|
|
63
|
-
import "../chunk-
|
|
65
|
+
import "../chunk-6YFHUIGT.js";
|
|
64
66
|
import "../chunk-BDGTZRZ6.js";
|
|
65
|
-
import "../chunk-
|
|
67
|
+
import "../chunk-WZJR6SOI.js";
|
|
66
68
|
import "../chunk-QCLOIUMX.js";
|
|
67
69
|
import "../chunk-XARGEOJV.js";
|
|
68
70
|
import "../chunk-KFQGP6VL.js";
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCheckPhaseGateCommand,
|
|
3
3
|
runCheckPhaseGate
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-7TIJXWG3.js";
|
|
5
|
+
import "./chunk-Y6SUQC32.js";
|
|
6
|
+
import "./chunk-XAVMTAUT.js";
|
|
6
7
|
import "./chunk-ZCZD7FHU.js";
|
|
7
8
|
import "./chunk-EBJQ6N4M.js";
|
|
8
9
|
import "./chunk-3WGJMBKH.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-MMLQPHZ5.js";
|
|
11
|
+
import "./chunk-6YFHUIGT.js";
|
|
11
12
|
import "./chunk-BDGTZRZ6.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-WZJR6SOI.js";
|
|
13
14
|
import "./chunk-QCLOIUMX.js";
|
|
14
15
|
import "./chunk-XARGEOJV.js";
|
|
15
16
|
import "./chunk-KFQGP6VL.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveProjectConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SEA2PFVI.js";
|
|
4
4
|
import {
|
|
5
5
|
sanitizePath
|
|
6
6
|
} from "./chunk-W6Y7ZW3Y.js";
|
|
@@ -49,7 +49,7 @@ async function handleValidateProject(input) {
|
|
|
49
49
|
checks.config = "pass";
|
|
50
50
|
const config = configResult.value;
|
|
51
51
|
try {
|
|
52
|
-
const core = await import("./dist-
|
|
52
|
+
const core = await import("./dist-6D2F2J57.js");
|
|
53
53
|
if (typeof core.validateFileStructure === "function" && Array.isArray(config.conventions)) {
|
|
54
54
|
const conventions = config.conventions;
|
|
55
55
|
const structureResult = await core.validateFileStructure(projectPath, conventions);
|
|
@@ -68,7 +68,7 @@ async function handleValidateProject(input) {
|
|
|
68
68
|
} catch {
|
|
69
69
|
}
|
|
70
70
|
try {
|
|
71
|
-
const core = await import("./dist-
|
|
71
|
+
const core = await import("./dist-6D2F2J57.js");
|
|
72
72
|
if (typeof core.validateAgentsMap === "function") {
|
|
73
73
|
const agentsMapPath = path.join(projectPath, "AGENTS.md");
|
|
74
74
|
const agentsResult = await core.validateAgentsMap(agentsMapPath);
|
|
@@ -15,7 +15,7 @@ function evictIfNeeded() {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
async function doLoadGraphStore(projectRoot) {
|
|
18
|
-
const { GraphStore } = await import("./dist-
|
|
18
|
+
const { GraphStore } = await import("./dist-DWBTZXR5.js");
|
|
19
19
|
const graphDir = path.join(projectRoot, ".harness", "graph");
|
|
20
20
|
const store = new GraphStore();
|
|
21
21
|
const loaded = await store.load(graphDir);
|
|
@@ -75,7 +75,7 @@ async function handleAssessProject(input) {
|
|
|
75
75
|
let validateResult = null;
|
|
76
76
|
if (checksToRun.has("validate")) {
|
|
77
77
|
try {
|
|
78
|
-
const { handleValidateProject } = await import("./validate-
|
|
78
|
+
const { handleValidateProject } = await import("./validate-64KTEGIE.js");
|
|
79
79
|
const result = await handleValidateProject({ path: projectPath });
|
|
80
80
|
const out = parseToolResponse(result, "validate");
|
|
81
81
|
if ("error" in out) {
|
|
@@ -104,7 +104,7 @@ async function handleAssessProject(input) {
|
|
|
104
104
|
parallelChecks.push(
|
|
105
105
|
(async () => {
|
|
106
106
|
try {
|
|
107
|
-
const { handleCheckDependencies } = await import("./architecture-
|
|
107
|
+
const { handleCheckDependencies } = await import("./architecture-YQH2NYXY.js");
|
|
108
108
|
const result = await handleCheckDependencies({ path: projectPath });
|
|
109
109
|
const out = parseToolResponse(result, "deps");
|
|
110
110
|
if ("error" in out) return out.error;
|
|
@@ -132,7 +132,7 @@ async function handleAssessProject(input) {
|
|
|
132
132
|
parallelChecks.push(
|
|
133
133
|
(async () => {
|
|
134
134
|
try {
|
|
135
|
-
const { handleCheckDocs } = await import("./docs-
|
|
135
|
+
const { handleCheckDocs } = await import("./docs-FP47JONV.js");
|
|
136
136
|
const result = await handleCheckDocs({ path: projectPath, scope: "coverage" });
|
|
137
137
|
const out = parseToolResponse(result, "docs");
|
|
138
138
|
if ("error" in out) return out.error;
|
|
@@ -160,7 +160,7 @@ async function handleAssessProject(input) {
|
|
|
160
160
|
parallelChecks.push(
|
|
161
161
|
(async () => {
|
|
162
162
|
try {
|
|
163
|
-
const { handleDetectEntropy } = await import("./entropy-
|
|
163
|
+
const { handleDetectEntropy } = await import("./entropy-DBW2INZU.js");
|
|
164
164
|
const result = await handleDetectEntropy({ path: projectPath, type: "all" });
|
|
165
165
|
const out = parseToolResponse(result, "entropy");
|
|
166
166
|
if ("error" in out) return out.error;
|
|
@@ -191,7 +191,7 @@ async function handleAssessProject(input) {
|
|
|
191
191
|
parallelChecks.push(
|
|
192
192
|
(async () => {
|
|
193
193
|
try {
|
|
194
|
-
const { handleRunSecurityScan } = await import("./security-
|
|
194
|
+
const { handleRunSecurityScan } = await import("./security-4W2P5ZGI.js");
|
|
195
195
|
const result = await handleRunSecurityScan({ path: projectPath });
|
|
196
196
|
const out = parseToolResponse(result, "security");
|
|
197
197
|
if ("error" in out) return out.error;
|
|
@@ -224,7 +224,7 @@ async function handleAssessProject(input) {
|
|
|
224
224
|
parallelChecks.push(
|
|
225
225
|
(async () => {
|
|
226
226
|
try {
|
|
227
|
-
const { handleCheckPerformance } = await import("./performance-
|
|
227
|
+
const { handleCheckPerformance } = await import("./performance-FXYTGJGQ.js");
|
|
228
228
|
const result = await handleCheckPerformance({ path: projectPath });
|
|
229
229
|
if ("isError" in result && result.isError) {
|
|
230
230
|
const msg = result.content[0]?.text ?? "Performance check failed";
|
|
@@ -7,10 +7,10 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
findConfigFile,
|
|
9
9
|
loadConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XAVMTAUT.js";
|
|
11
11
|
import {
|
|
12
12
|
init_dist
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-MMLQPHZ5.js";
|
|
14
14
|
import {
|
|
15
15
|
Ok
|
|
16
16
|
} from "./chunk-BDGTZRZ6.js";
|
|
@@ -35,7 +35,7 @@ var checkPerformanceDefinition = {
|
|
|
35
35
|
};
|
|
36
36
|
async function handleCheckPerformance(input) {
|
|
37
37
|
try {
|
|
38
|
-
const { EntropyAnalyzer } = await import("./dist-
|
|
38
|
+
const { EntropyAnalyzer } = await import("./dist-6D2F2J57.js");
|
|
39
39
|
const typeFilter = input.type ?? "all";
|
|
40
40
|
const projectPath = sanitizePath(input.path);
|
|
41
41
|
let entryPoints;
|
|
@@ -58,10 +58,10 @@ async function handleCheckPerformance(input) {
|
|
|
58
58
|
});
|
|
59
59
|
let graphOptions;
|
|
60
60
|
try {
|
|
61
|
-
const { loadGraphStore } = await import("./graph-loader-
|
|
61
|
+
const { loadGraphStore } = await import("./graph-loader-STFGYKZH.js");
|
|
62
62
|
const store = await loadGraphStore(projectPath);
|
|
63
63
|
if (store) {
|
|
64
|
-
const { GraphComplexityAdapter, GraphCouplingAdapter } = await import("./dist-
|
|
64
|
+
const { GraphComplexityAdapter, GraphCouplingAdapter } = await import("./dist-DWBTZXR5.js");
|
|
65
65
|
const complexityAdapter = new GraphComplexityAdapter(store);
|
|
66
66
|
const couplingAdapter = new GraphCouplingAdapter(store);
|
|
67
67
|
graphOptions = {
|
|
@@ -98,7 +98,7 @@ var getPerfBaselinesDefinition = {
|
|
|
98
98
|
};
|
|
99
99
|
async function handleGetPerfBaselines(input) {
|
|
100
100
|
try {
|
|
101
|
-
const { BaselineManager } = await import("./dist-
|
|
101
|
+
const { BaselineManager } = await import("./dist-6D2F2J57.js");
|
|
102
102
|
const manager = new BaselineManager(sanitizePath(input.path));
|
|
103
103
|
const baselines = manager.load();
|
|
104
104
|
return resultToMcpResponse(
|
|
@@ -146,7 +146,7 @@ var updatePerfBaselinesDefinition = {
|
|
|
146
146
|
};
|
|
147
147
|
async function handleUpdatePerfBaselines(input) {
|
|
148
148
|
try {
|
|
149
|
-
const { BaselineManager } = await import("./dist-
|
|
149
|
+
const { BaselineManager } = await import("./dist-6D2F2J57.js");
|
|
150
150
|
const manager = new BaselineManager(sanitizePath(input.path));
|
|
151
151
|
manager.save(input.results, input.commitHash);
|
|
152
152
|
const updated = manager.load();
|
|
@@ -176,7 +176,7 @@ var getCriticalPathsDefinition = {
|
|
|
176
176
|
};
|
|
177
177
|
async function handleGetCriticalPaths(input) {
|
|
178
178
|
try {
|
|
179
|
-
const { CriticalPathResolver } = await import("./dist-
|
|
179
|
+
const { CriticalPathResolver } = await import("./dist-6D2F2J57.js");
|
|
180
180
|
const resolver = new CriticalPathResolver(sanitizePath(input.path));
|
|
181
181
|
const result = await resolver.resolve();
|
|
182
182
|
return resultToMcpResponse(Ok(result));
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findFiles
|
|
3
|
+
} from "./chunk-Y6SUQC32.js";
|
|
1
4
|
import {
|
|
2
5
|
resolveConfig
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-XAVMTAUT.js";
|
|
4
7
|
import {
|
|
5
8
|
logger
|
|
6
9
|
} from "./chunk-EBJQ6N4M.js";
|
|
@@ -9,7 +12,7 @@ import {
|
|
|
9
12
|
} from "./chunk-3WGJMBKH.js";
|
|
10
13
|
import {
|
|
11
14
|
init_dist
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-MMLQPHZ5.js";
|
|
13
16
|
import {
|
|
14
17
|
Ok
|
|
15
18
|
} from "./chunk-BDGTZRZ6.js";
|
|
@@ -20,12 +23,6 @@ import { Command } from "commander";
|
|
|
20
23
|
import * as path from "path";
|
|
21
24
|
import * as fs from "fs";
|
|
22
25
|
|
|
23
|
-
// src/utils/files.ts
|
|
24
|
-
import { glob } from "glob";
|
|
25
|
-
async function findFiles(pattern, cwd = process.cwd()) {
|
|
26
|
-
return glob(pattern, { cwd, absolute: true });
|
|
27
|
-
}
|
|
28
|
-
|
|
29
26
|
// src/output/formatter.ts
|
|
30
27
|
import chalk from "chalk";
|
|
31
28
|
var OutputMode = {
|
|
@@ -248,7 +245,6 @@ function createCheckPhaseGateCommand() {
|
|
|
248
245
|
export {
|
|
249
246
|
OutputMode,
|
|
250
247
|
OutputFormatter,
|
|
251
|
-
findFiles,
|
|
252
248
|
runCheckPhaseGate,
|
|
253
249
|
createCheckPhaseGateCommand
|
|
254
250
|
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
event_sourcing_exports,
|
|
3
|
+
init_dist
|
|
4
|
+
} from "./chunk-MMLQPHZ5.js";
|
|
5
|
+
import {
|
|
6
|
+
Ok
|
|
7
|
+
} from "./chunk-BDGTZRZ6.js";
|
|
8
|
+
|
|
9
|
+
// src/shared/state-events.ts
|
|
10
|
+
init_dist();
|
|
11
|
+
var { importLegacyState, readSnapshot, toHarnessState, emitEvent, formatAuditTimeline } = event_sourcing_exports;
|
|
12
|
+
async function readHarnessState(projectPath, scope) {
|
|
13
|
+
await importLegacyState(projectPath, scope);
|
|
14
|
+
const snap = await readSnapshot(projectPath, scope);
|
|
15
|
+
if (!snap.ok) return snap;
|
|
16
|
+
return Ok(toHarnessState(snap.value.coreState));
|
|
17
|
+
}
|
|
18
|
+
function isEmptyHarnessState(s) {
|
|
19
|
+
return s.decisions.length === 0 && s.blockers.length === 0 && Object.keys(s.progress).length === 0 && !s.position.phase && !s.position.task && !s.lastSession;
|
|
20
|
+
}
|
|
21
|
+
async function emitCoreEvent(projectPath, event, scope) {
|
|
22
|
+
await importLegacyState(projectPath, scope);
|
|
23
|
+
return emitEvent(projectPath, event, scope);
|
|
24
|
+
}
|
|
25
|
+
async function emitUserInputCaptured(projectPath, text, interactionId, scope) {
|
|
26
|
+
const payload = interactionId ? { text, interactionId } : { text };
|
|
27
|
+
return emitCoreEvent(
|
|
28
|
+
projectPath,
|
|
29
|
+
{ type: "user_input_captured", payload },
|
|
30
|
+
scope
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
async function emitApprovalRequested(projectPath, interactionId, kind, prompt, scope) {
|
|
34
|
+
return emitCoreEvent(
|
|
35
|
+
projectPath,
|
|
36
|
+
{ type: "approval_requested", payload: { interactionId, kind, prompt } },
|
|
37
|
+
scope
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
async function emitApprovalResolved(projectPath, interactionId, response, scope) {
|
|
41
|
+
return emitCoreEvent(
|
|
42
|
+
projectPath,
|
|
43
|
+
{ type: "approval_resolved", payload: { interactionId, response } },
|
|
44
|
+
scope
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
async function readAuditTimeline(projectPath, scope) {
|
|
48
|
+
const snap = await readSnapshot(projectPath, scope);
|
|
49
|
+
if (!snap.ok) return "";
|
|
50
|
+
return formatAuditTimeline(snap.value.audit);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
readHarnessState,
|
|
55
|
+
isEmptyHarnessState,
|
|
56
|
+
emitCoreEvent,
|
|
57
|
+
emitUserInputCaptured,
|
|
58
|
+
emitApprovalRequested,
|
|
59
|
+
emitApprovalResolved,
|
|
60
|
+
readAuditTimeline
|
|
61
|
+
};
|