@harness-engineering/core 0.5.0 → 0.7.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/dist/index.d.mts +11 -51
- package/dist/index.d.ts +11 -51
- package/dist/index.js +331 -187
- package/dist/index.mjs +209 -56
- package/package.json +4 -3
- package/dist/.tsbuildinfo +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
export * from "@harness-engineering/types";
|
|
3
3
|
|
|
4
|
-
// src/shared/result.ts
|
|
5
|
-
var Ok = (value) => ({
|
|
6
|
-
ok: true,
|
|
7
|
-
value
|
|
8
|
-
});
|
|
9
|
-
function isOk(result) {
|
|
10
|
-
return result.ok === true;
|
|
11
|
-
}
|
|
12
|
-
var Err = (error) => ({
|
|
13
|
-
ok: false,
|
|
14
|
-
error
|
|
15
|
-
});
|
|
16
|
-
function isErr(result) {
|
|
17
|
-
return result.ok === false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
4
|
// src/shared/errors.ts
|
|
21
5
|
function createError(code, message, details = {}, suggestions = []) {
|
|
22
6
|
return { code, message, details, suggestions };
|
|
@@ -25,23 +9,26 @@ function createEntropyError(code, message, details = {}, suggestions = []) {
|
|
|
25
9
|
return { code, message, details, suggestions };
|
|
26
10
|
}
|
|
27
11
|
|
|
12
|
+
// src/shared/result.ts
|
|
13
|
+
import { Ok, Err, isOk, isErr } from "@harness-engineering/types";
|
|
14
|
+
|
|
28
15
|
// src/shared/fs-utils.ts
|
|
29
16
|
import { access, constants, readFile } from "fs";
|
|
30
17
|
import { promisify } from "util";
|
|
31
18
|
import { glob } from "glob";
|
|
32
19
|
var accessAsync = promisify(access);
|
|
33
20
|
var readFileAsync = promisify(readFile);
|
|
34
|
-
async function fileExists(
|
|
21
|
+
async function fileExists(path3) {
|
|
35
22
|
try {
|
|
36
|
-
await accessAsync(
|
|
23
|
+
await accessAsync(path3, constants.F_OK);
|
|
37
24
|
return true;
|
|
38
25
|
} catch {
|
|
39
26
|
return false;
|
|
40
27
|
}
|
|
41
28
|
}
|
|
42
|
-
async function readFileContent(
|
|
29
|
+
async function readFileContent(path3) {
|
|
43
30
|
try {
|
|
44
|
-
const content = await readFileAsync(
|
|
31
|
+
const content = await readFileAsync(path3, "utf-8");
|
|
45
32
|
return Ok(content);
|
|
46
33
|
} catch (error) {
|
|
47
34
|
return Err(error);
|
|
@@ -89,15 +76,15 @@ function validateConfig(data, schema) {
|
|
|
89
76
|
let message = "Configuration validation failed";
|
|
90
77
|
const suggestions = [];
|
|
91
78
|
if (firstError) {
|
|
92
|
-
const
|
|
93
|
-
const pathDisplay =
|
|
79
|
+
const path3 = firstError.path.join(".");
|
|
80
|
+
const pathDisplay = path3 ? ` at "${path3}"` : "";
|
|
94
81
|
if (firstError.code === "invalid_type") {
|
|
95
82
|
const received = firstError.received;
|
|
96
83
|
const expected = firstError.expected;
|
|
97
84
|
if (received === "undefined") {
|
|
98
85
|
code = "MISSING_FIELD";
|
|
99
86
|
message = `Missing required field${pathDisplay}: ${firstError.message}`;
|
|
100
|
-
suggestions.push(`Field "${
|
|
87
|
+
suggestions.push(`Field "${path3}" is required and must be of type "${expected}"`);
|
|
101
88
|
} else {
|
|
102
89
|
code = "INVALID_TYPE";
|
|
103
90
|
message = `Invalid type${pathDisplay}: ${firstError.message}`;
|
|
@@ -310,27 +297,27 @@ function extractSections(content) {
|
|
|
310
297
|
return result;
|
|
311
298
|
});
|
|
312
299
|
}
|
|
313
|
-
function isExternalLink(
|
|
314
|
-
return
|
|
300
|
+
function isExternalLink(path3) {
|
|
301
|
+
return path3.startsWith("http://") || path3.startsWith("https://") || path3.startsWith("#") || path3.startsWith("mailto:");
|
|
315
302
|
}
|
|
316
303
|
function resolveLinkPath(linkPath, baseDir) {
|
|
317
304
|
return linkPath.startsWith(".") ? join(baseDir, linkPath) : linkPath;
|
|
318
305
|
}
|
|
319
|
-
async function validateAgentsMap(
|
|
320
|
-
const contentResult = await readFileContent(
|
|
306
|
+
async function validateAgentsMap(path3 = "./AGENTS.md") {
|
|
307
|
+
const contentResult = await readFileContent(path3);
|
|
321
308
|
if (!contentResult.ok) {
|
|
322
309
|
return Err(
|
|
323
310
|
createError(
|
|
324
311
|
"PARSE_ERROR",
|
|
325
312
|
`Failed to read AGENTS.md: ${contentResult.error.message}`,
|
|
326
|
-
{ path:
|
|
313
|
+
{ path: path3 },
|
|
327
314
|
["Ensure the file exists", "Check file permissions"]
|
|
328
315
|
)
|
|
329
316
|
);
|
|
330
317
|
}
|
|
331
318
|
const content = contentResult.value;
|
|
332
319
|
const sections = extractSections(content);
|
|
333
|
-
const baseDir = dirname(
|
|
320
|
+
const baseDir = dirname(path3);
|
|
334
321
|
const sectionTitles = sections.map((s) => s.title);
|
|
335
322
|
const missingSections = REQUIRED_SECTIONS.filter(
|
|
336
323
|
(required) => !sectionTitles.some((title) => title.toLowerCase().includes(required.toLowerCase()))
|
|
@@ -458,8 +445,8 @@ async function checkDocCoverage(domain, options = {}) {
|
|
|
458
445
|
|
|
459
446
|
// src/context/knowledge-map.ts
|
|
460
447
|
import { join as join2, basename as basename2, relative as relative2 } from "path";
|
|
461
|
-
function suggestFix(
|
|
462
|
-
const targetName = basename2(
|
|
448
|
+
function suggestFix(path3, existingFiles) {
|
|
449
|
+
const targetName = basename2(path3).toLowerCase();
|
|
463
450
|
const similar = existingFiles.find((file) => {
|
|
464
451
|
const fileName = basename2(file).toLowerCase();
|
|
465
452
|
return fileName.includes(targetName) || targetName.includes(fileName);
|
|
@@ -467,7 +454,7 @@ function suggestFix(path2, existingFiles) {
|
|
|
467
454
|
if (similar) {
|
|
468
455
|
return `Did you mean "${similar}"?`;
|
|
469
456
|
}
|
|
470
|
-
return `Create the file "${
|
|
457
|
+
return `Create the file "${path3}" or remove the link`;
|
|
471
458
|
}
|
|
472
459
|
async function validateKnowledgeMap(rootDir = process.cwd()) {
|
|
473
460
|
const agentsPath = join2(rootDir, "AGENTS.md");
|
|
@@ -962,8 +949,8 @@ function createBoundaryValidator(schema, name) {
|
|
|
962
949
|
return Ok(result.data);
|
|
963
950
|
}
|
|
964
951
|
const suggestions = result.error.issues.map((issue) => {
|
|
965
|
-
const
|
|
966
|
-
return
|
|
952
|
+
const path3 = issue.path.join(".");
|
|
953
|
+
return path3 ? `${path3}: ${issue.message}` : issue.message;
|
|
967
954
|
});
|
|
968
955
|
return Err(
|
|
969
956
|
createError(
|
|
@@ -1032,11 +1019,11 @@ function walk(node, visitor) {
|
|
|
1032
1019
|
var TypeScriptParser = class {
|
|
1033
1020
|
name = "typescript";
|
|
1034
1021
|
extensions = [".ts", ".tsx", ".mts", ".cts"];
|
|
1035
|
-
async parseFile(
|
|
1036
|
-
const contentResult = await readFileContent(
|
|
1022
|
+
async parseFile(path3) {
|
|
1023
|
+
const contentResult = await readFileContent(path3);
|
|
1037
1024
|
if (!contentResult.ok) {
|
|
1038
1025
|
return Err(
|
|
1039
|
-
createParseError("NOT_FOUND", `File not found: ${
|
|
1026
|
+
createParseError("NOT_FOUND", `File not found: ${path3}`, { path: path3 }, [
|
|
1040
1027
|
"Check that the file exists",
|
|
1041
1028
|
"Verify the path is correct"
|
|
1042
1029
|
])
|
|
@@ -1046,7 +1033,7 @@ var TypeScriptParser = class {
|
|
|
1046
1033
|
const ast = parse(contentResult.value, {
|
|
1047
1034
|
loc: true,
|
|
1048
1035
|
range: true,
|
|
1049
|
-
jsx:
|
|
1036
|
+
jsx: path3.endsWith(".tsx"),
|
|
1050
1037
|
errorOnUnknownASTType: false
|
|
1051
1038
|
});
|
|
1052
1039
|
return Ok({
|
|
@@ -1057,7 +1044,7 @@ var TypeScriptParser = class {
|
|
|
1057
1044
|
} catch (e) {
|
|
1058
1045
|
const error = e;
|
|
1059
1046
|
return Err(
|
|
1060
|
-
createParseError("SYNTAX_ERROR", `Failed to parse ${
|
|
1047
|
+
createParseError("SYNTAX_ERROR", `Failed to parse ${path3}: ${error.message}`, { path: path3 }, [
|
|
1061
1048
|
"Check for syntax errors in the file",
|
|
1062
1049
|
"Ensure valid TypeScript syntax"
|
|
1063
1050
|
])
|
|
@@ -1341,22 +1328,22 @@ function extractInlineRefs(content) {
|
|
|
1341
1328
|
}
|
|
1342
1329
|
return refs;
|
|
1343
1330
|
}
|
|
1344
|
-
async function parseDocumentationFile(
|
|
1345
|
-
const contentResult = await readFileContent(
|
|
1331
|
+
async function parseDocumentationFile(path3) {
|
|
1332
|
+
const contentResult = await readFileContent(path3);
|
|
1346
1333
|
if (!contentResult.ok) {
|
|
1347
1334
|
return Err(
|
|
1348
1335
|
createEntropyError(
|
|
1349
1336
|
"PARSE_ERROR",
|
|
1350
|
-
`Failed to read documentation file: ${
|
|
1351
|
-
{ file:
|
|
1337
|
+
`Failed to read documentation file: ${path3}`,
|
|
1338
|
+
{ file: path3 },
|
|
1352
1339
|
["Check that the file exists"]
|
|
1353
1340
|
)
|
|
1354
1341
|
);
|
|
1355
1342
|
}
|
|
1356
1343
|
const content = contentResult.value;
|
|
1357
|
-
const type =
|
|
1344
|
+
const type = path3.endsWith(".md") ? "markdown" : "text";
|
|
1358
1345
|
return Ok({
|
|
1359
|
-
path:
|
|
1346
|
+
path: path3,
|
|
1360
1347
|
type,
|
|
1361
1348
|
content,
|
|
1362
1349
|
codeBlocks: extractCodeBlocks(content),
|
|
@@ -3867,8 +3854,183 @@ async function runMultiTurnPipeline(initialContext, turnExecutor, options) {
|
|
|
3867
3854
|
};
|
|
3868
3855
|
}
|
|
3869
3856
|
|
|
3857
|
+
// src/ci/check-orchestrator.ts
|
|
3858
|
+
import * as path2 from "path";
|
|
3859
|
+
var ALL_CHECKS = ["validate", "deps", "docs", "entropy", "phase-gate"];
|
|
3860
|
+
async function runSingleCheck(name, projectRoot, config) {
|
|
3861
|
+
const start = Date.now();
|
|
3862
|
+
const issues = [];
|
|
3863
|
+
try {
|
|
3864
|
+
switch (name) {
|
|
3865
|
+
case "validate": {
|
|
3866
|
+
const agentsPath = path2.join(projectRoot, config.agentsMapPath ?? "AGENTS.md");
|
|
3867
|
+
const result = await validateAgentsMap(agentsPath);
|
|
3868
|
+
if (!result.ok) {
|
|
3869
|
+
issues.push({ severity: "error", message: result.error.message });
|
|
3870
|
+
} else if (!result.value.valid) {
|
|
3871
|
+
if (result.value.errors) {
|
|
3872
|
+
for (const err of result.value.errors) {
|
|
3873
|
+
issues.push({ severity: "error", message: err.message });
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
for (const section of result.value.missingSections) {
|
|
3877
|
+
issues.push({ severity: "warning", message: `Missing section: ${section}` });
|
|
3878
|
+
}
|
|
3879
|
+
for (const link of result.value.brokenLinks) {
|
|
3880
|
+
issues.push({
|
|
3881
|
+
severity: "warning",
|
|
3882
|
+
message: `Broken link: ${link.text} \u2192 ${link.path}`,
|
|
3883
|
+
file: link.path
|
|
3884
|
+
});
|
|
3885
|
+
}
|
|
3886
|
+
}
|
|
3887
|
+
break;
|
|
3888
|
+
}
|
|
3889
|
+
case "deps": {
|
|
3890
|
+
const layers = config.layers;
|
|
3891
|
+
if (layers && layers.length > 0) {
|
|
3892
|
+
const parser = new TypeScriptParser();
|
|
3893
|
+
const result = await validateDependencies({
|
|
3894
|
+
layers,
|
|
3895
|
+
rootDir: projectRoot,
|
|
3896
|
+
parser
|
|
3897
|
+
});
|
|
3898
|
+
if (!result.ok) {
|
|
3899
|
+
issues.push({ severity: "error", message: result.error.message });
|
|
3900
|
+
} else if (result.value.violations.length > 0) {
|
|
3901
|
+
for (const v of result.value.violations) {
|
|
3902
|
+
issues.push({
|
|
3903
|
+
severity: "error",
|
|
3904
|
+
message: `${v.reason}: ${v.file} imports ${v.imports} (${v.fromLayer} \u2192 ${v.toLayer})`,
|
|
3905
|
+
file: v.file,
|
|
3906
|
+
line: v.line
|
|
3907
|
+
});
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
break;
|
|
3912
|
+
}
|
|
3913
|
+
case "docs": {
|
|
3914
|
+
const docsDir = path2.join(projectRoot, config.docsDir ?? "docs");
|
|
3915
|
+
const result = await checkDocCoverage("project", { docsDir });
|
|
3916
|
+
if (!result.ok) {
|
|
3917
|
+
issues.push({ severity: "warning", message: result.error.message });
|
|
3918
|
+
} else if (result.value.gaps.length > 0) {
|
|
3919
|
+
for (const gap of result.value.gaps) {
|
|
3920
|
+
issues.push({
|
|
3921
|
+
severity: "warning",
|
|
3922
|
+
message: `Undocumented: ${gap.file} (suggested: ${gap.suggestedSection})`,
|
|
3923
|
+
file: gap.file
|
|
3924
|
+
});
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
break;
|
|
3928
|
+
}
|
|
3929
|
+
case "entropy": {
|
|
3930
|
+
const analyzer = new EntropyAnalyzer({
|
|
3931
|
+
rootDir: projectRoot,
|
|
3932
|
+
analyze: { drift: true, deadCode: true, patterns: false }
|
|
3933
|
+
});
|
|
3934
|
+
const result = await analyzer.analyze();
|
|
3935
|
+
if (!result.ok) {
|
|
3936
|
+
issues.push({ severity: "warning", message: result.error.message });
|
|
3937
|
+
} else {
|
|
3938
|
+
const report = result.value;
|
|
3939
|
+
if (report.drift) {
|
|
3940
|
+
for (const drift of report.drift.drifts) {
|
|
3941
|
+
issues.push({
|
|
3942
|
+
severity: "warning",
|
|
3943
|
+
message: `Doc drift (${drift.type}): ${drift.details}`,
|
|
3944
|
+
file: drift.docFile,
|
|
3945
|
+
line: drift.line
|
|
3946
|
+
});
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
if (report.deadCode) {
|
|
3950
|
+
for (const dead of report.deadCode.deadExports) {
|
|
3951
|
+
issues.push({
|
|
3952
|
+
severity: "warning",
|
|
3953
|
+
message: `Dead export: ${dead.name}`,
|
|
3954
|
+
file: dead.file,
|
|
3955
|
+
line: dead.line
|
|
3956
|
+
});
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
}
|
|
3960
|
+
break;
|
|
3961
|
+
}
|
|
3962
|
+
case "phase-gate": {
|
|
3963
|
+
const phaseGates = config.phaseGates;
|
|
3964
|
+
if (!phaseGates?.enabled) {
|
|
3965
|
+
break;
|
|
3966
|
+
}
|
|
3967
|
+
issues.push({
|
|
3968
|
+
severity: "warning",
|
|
3969
|
+
message: "Phase gate is enabled but requires CLI context. Run `harness check-phase-gate` separately for full validation."
|
|
3970
|
+
});
|
|
3971
|
+
break;
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
} catch (error) {
|
|
3975
|
+
issues.push({
|
|
3976
|
+
severity: "error",
|
|
3977
|
+
message: `Check '${name}' threw: ${error instanceof Error ? error.message : String(error)}`
|
|
3978
|
+
});
|
|
3979
|
+
}
|
|
3980
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
3981
|
+
const hasWarnings = issues.some((i) => i.severity === "warning");
|
|
3982
|
+
const status = hasErrors ? "fail" : hasWarnings ? "warn" : "pass";
|
|
3983
|
+
return {
|
|
3984
|
+
name,
|
|
3985
|
+
status,
|
|
3986
|
+
issues,
|
|
3987
|
+
durationMs: Date.now() - start
|
|
3988
|
+
};
|
|
3989
|
+
}
|
|
3990
|
+
function buildSummary(checks) {
|
|
3991
|
+
return {
|
|
3992
|
+
total: checks.length,
|
|
3993
|
+
passed: checks.filter((c) => c.status === "pass").length,
|
|
3994
|
+
failed: checks.filter((c) => c.status === "fail").length,
|
|
3995
|
+
warnings: checks.filter((c) => c.status === "warn").length,
|
|
3996
|
+
skipped: checks.filter((c) => c.status === "skip").length
|
|
3997
|
+
};
|
|
3998
|
+
}
|
|
3999
|
+
function determineExitCode(summary, failOn = "error") {
|
|
4000
|
+
if (summary.failed > 0) return 1;
|
|
4001
|
+
if (failOn === "warning" && summary.warnings > 0) return 1;
|
|
4002
|
+
return 0;
|
|
4003
|
+
}
|
|
4004
|
+
async function runCIChecks(input) {
|
|
4005
|
+
const { projectRoot, config, skip = [], failOn = "error" } = input;
|
|
4006
|
+
try {
|
|
4007
|
+
const checks = [];
|
|
4008
|
+
for (const name of ALL_CHECKS) {
|
|
4009
|
+
if (skip.includes(name)) {
|
|
4010
|
+
checks.push({ name, status: "skip", issues: [], durationMs: 0 });
|
|
4011
|
+
} else {
|
|
4012
|
+
const result = await runSingleCheck(name, projectRoot, config);
|
|
4013
|
+
checks.push(result);
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
const summary = buildSummary(checks);
|
|
4017
|
+
const exitCode = determineExitCode(summary, failOn);
|
|
4018
|
+
const report = {
|
|
4019
|
+
version: 1,
|
|
4020
|
+
project: config.name ?? "unknown",
|
|
4021
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4022
|
+
checks,
|
|
4023
|
+
summary,
|
|
4024
|
+
exitCode
|
|
4025
|
+
};
|
|
4026
|
+
return Ok(report);
|
|
4027
|
+
} catch (error) {
|
|
4028
|
+
return Err(error instanceof Error ? error : new Error(String(error)));
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
|
|
3870
4032
|
// src/index.ts
|
|
3871
|
-
var VERSION = "0.
|
|
4033
|
+
var VERSION = "0.6.0";
|
|
3872
4034
|
export {
|
|
3873
4035
|
AgentActionEmitter,
|
|
3874
4036
|
ChecklistBuilder,
|
|
@@ -3876,7 +4038,6 @@ export {
|
|
|
3876
4038
|
DEFAULT_STATE,
|
|
3877
4039
|
EntropyAnalyzer,
|
|
3878
4040
|
EntropyConfigSchema,
|
|
3879
|
-
Err,
|
|
3880
4041
|
FailureEntrySchema,
|
|
3881
4042
|
FileSink,
|
|
3882
4043
|
GateConfigSchema,
|
|
@@ -3886,7 +4047,6 @@ export {
|
|
|
3886
4047
|
NoOpExecutor,
|
|
3887
4048
|
NoOpSink,
|
|
3888
4049
|
NoOpTelemetryAdapter,
|
|
3889
|
-
Ok,
|
|
3890
4050
|
PatternConfigSchema,
|
|
3891
4051
|
REQUIRED_SECTIONS,
|
|
3892
4052
|
TypeScriptParser,
|
|
@@ -3897,9 +4057,7 @@ export {
|
|
|
3897
4057
|
applyFixes,
|
|
3898
4058
|
archiveFailures,
|
|
3899
4059
|
buildDependencyGraph,
|
|
3900
|
-
buildReachabilityMap,
|
|
3901
4060
|
buildSnapshot,
|
|
3902
|
-
checkConfigPattern,
|
|
3903
4061
|
checkDocCoverage,
|
|
3904
4062
|
configureFeedback,
|
|
3905
4063
|
contextBudget,
|
|
@@ -3918,28 +4076,23 @@ export {
|
|
|
3918
4076
|
executeWorkflow,
|
|
3919
4077
|
extractMarkdownLinks,
|
|
3920
4078
|
extractSections,
|
|
3921
|
-
findPossibleMatches,
|
|
3922
4079
|
generateAgentsMap,
|
|
3923
4080
|
generateSuggestions,
|
|
3924
4081
|
getActionEmitter,
|
|
3925
4082
|
getFeedbackConfig,
|
|
3926
4083
|
getPhaseCategories,
|
|
3927
|
-
isErr,
|
|
3928
|
-
isOk,
|
|
3929
|
-
levenshteinDistance,
|
|
3930
4084
|
loadFailures,
|
|
3931
4085
|
loadHandoff,
|
|
3932
4086
|
loadRelevantLearnings,
|
|
3933
4087
|
loadState,
|
|
3934
4088
|
logAgentAction,
|
|
3935
4089
|
parseDiff,
|
|
3936
|
-
parseDocumentationFile,
|
|
3937
4090
|
previewFix,
|
|
3938
4091
|
requestMultiplePeerReviews,
|
|
3939
4092
|
requestPeerReview,
|
|
3940
4093
|
resetFeedbackConfig,
|
|
3941
|
-
resolveEntryPoints,
|
|
3942
4094
|
resolveFileToLayer,
|
|
4095
|
+
runCIChecks,
|
|
3943
4096
|
runMechanicalGate,
|
|
3944
4097
|
runMultiTurnPipeline,
|
|
3945
4098
|
runPipeline,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harness-engineering/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Core library for Harness Engineering toolkit",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"glob": "^10.3.0",
|
|
42
42
|
"minimatch": "^10.2.4",
|
|
43
43
|
"zod": "^3.22.0",
|
|
44
|
-
"@harness-engineering/types": "0.
|
|
44
|
+
"@harness-engineering/types": "0.1.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@vitest/coverage-v8": "^4.0.18",
|
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
"lint": "eslint src",
|
|
57
57
|
"typecheck": "tsc --noEmit",
|
|
58
58
|
"clean": "rm -rf dist",
|
|
59
|
-
"test": "vitest",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:watch": "vitest",
|
|
60
61
|
"test:coverage": "vitest run --coverage",
|
|
61
62
|
"test:ui": "vitest --ui"
|
|
62
63
|
}
|