hunter-harness 0.2.18 → 0.2.20
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/bin.js +412 -112
- package/package.json +36 -36
package/dist/bin.js
CHANGED
|
@@ -164,7 +164,15 @@ var requestMetadataSchema = z2.object({
|
|
|
164
164
|
}).strict();
|
|
165
165
|
|
|
166
166
|
// ../contracts/dist/registry.js
|
|
167
|
-
var
|
|
167
|
+
var skillTargetAgentSchema = z3.enum(["claude-code", "codex", "cursor", "codebuddy"]);
|
|
168
|
+
var registryAgentSchema = z3.enum([
|
|
169
|
+
"claude-code",
|
|
170
|
+
"codex",
|
|
171
|
+
"cursor",
|
|
172
|
+
"codebuddy",
|
|
173
|
+
"generic",
|
|
174
|
+
"mcp"
|
|
175
|
+
]);
|
|
168
176
|
var registrySkillStatusSchema = z3.enum([
|
|
169
177
|
"draft",
|
|
170
178
|
"pending_review",
|
|
@@ -180,6 +188,7 @@ var registrySkillProposalStatusSchema = z3.enum([
|
|
|
180
188
|
var registrySemverSchema = z3.string().regex(/^\d+\.\d+\.\d+$/);
|
|
181
189
|
var registrySlugSchema = z3.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
|
|
182
190
|
var checkStatusSchema = z3.enum(["green", "yellow", "red"]);
|
|
191
|
+
var skillVariantStatusSchema = z3.enum(["ready", "degraded", "unsupported"]);
|
|
183
192
|
var sourceFileSchema = z3.object({
|
|
184
193
|
path: z3.string(),
|
|
185
194
|
content: z3.string()
|
|
@@ -204,6 +213,39 @@ var skillUsageExampleSchema = z3.object({
|
|
|
204
213
|
result: z3.string(),
|
|
205
214
|
files: z3.array(z3.string()).default([])
|
|
206
215
|
}).strict();
|
|
216
|
+
var sensitiveFindingViewSchema = z3.object({
|
|
217
|
+
rule_id: z3.string().min(1),
|
|
218
|
+
severity: z3.enum(["high", "medium", "low"]),
|
|
219
|
+
path: z3.string().min(1),
|
|
220
|
+
line: z3.number().int().positive(),
|
|
221
|
+
column: z3.number().int().positive(),
|
|
222
|
+
fingerprint: sha256Schema,
|
|
223
|
+
redacted_preview: z3.string(),
|
|
224
|
+
overridable: z3.boolean()
|
|
225
|
+
}).strict();
|
|
226
|
+
var sensitiveReviewSubmissionSchema = z3.object({
|
|
227
|
+
scanner_version: z3.string().min(1),
|
|
228
|
+
finding_fingerprints: z3.array(sha256Schema).min(1),
|
|
229
|
+
reason: z3.string().trim().min(3).max(500)
|
|
230
|
+
}).strict();
|
|
231
|
+
var sensitiveReviewEvidenceSchema = sensitiveReviewSubmissionSchema.extend({
|
|
232
|
+
actor: z3.string().min(1),
|
|
233
|
+
accepted_at: z3.iso.datetime()
|
|
234
|
+
}).strict();
|
|
235
|
+
var skillVariantSchema = z3.object({
|
|
236
|
+
agent: skillTargetAgentSchema,
|
|
237
|
+
status: skillVariantStatusSchema,
|
|
238
|
+
buildHash: sha256Schema.nullable(),
|
|
239
|
+
adapterVersion: z3.string().min(1),
|
|
240
|
+
components: z3.array(z3.string().min(1))
|
|
241
|
+
}).strict();
|
|
242
|
+
var skillReleaseSchema = z3.object({
|
|
243
|
+
version: registrySemverSchema,
|
|
244
|
+
packageName: z3.string().min(1),
|
|
245
|
+
packageDigest: z3.string().min(1),
|
|
246
|
+
variants: z3.partialRecord(skillTargetAgentSchema, skillVariantSchema),
|
|
247
|
+
created_at: z3.iso.datetime()
|
|
248
|
+
}).strict();
|
|
207
249
|
var agentSkillConfigSchema = z3.object({
|
|
208
250
|
agent: registryAgentSchema,
|
|
209
251
|
enabled: z3.boolean(),
|
|
@@ -250,6 +292,24 @@ var publishSkillRequestSchema = z3.object({
|
|
|
250
292
|
version: registrySemverSchema,
|
|
251
293
|
releaseNote: z3.string().optional()
|
|
252
294
|
}).strict();
|
|
295
|
+
var publishUnifiedSkillRequestSchema = z3.object({
|
|
296
|
+
version: registrySemverSchema,
|
|
297
|
+
sourceAgent: skillTargetAgentSchema,
|
|
298
|
+
draftRevision: z3.number().int().positive(),
|
|
299
|
+
releaseNote: z3.string().trim().min(1).max(2e3).optional()
|
|
300
|
+
}).strict();
|
|
301
|
+
var publishSkillResponseSchema = z3.object({
|
|
302
|
+
release: z3.object({
|
|
303
|
+
slug: registrySlugSchema,
|
|
304
|
+
version: registrySemverSchema
|
|
305
|
+
}).strict(),
|
|
306
|
+
npmRelease: z3.object({
|
|
307
|
+
status: z3.enum(["published", "idempotent"]),
|
|
308
|
+
packageName: z3.string().min(1),
|
|
309
|
+
version: registrySemverSchema,
|
|
310
|
+
tarballHash: z3.string().min(1)
|
|
311
|
+
}).strict()
|
|
312
|
+
}).strict();
|
|
253
313
|
var setDefaultAgentRequestSchema = z3.object({
|
|
254
314
|
defaultAgent: registryAgentSchema,
|
|
255
315
|
revision: z3.number().int().positive()
|
|
@@ -931,94 +991,148 @@ var semanticSearchHitSchema = z12.object({
|
|
|
931
991
|
project_id: z12.string()
|
|
932
992
|
}).strict();
|
|
933
993
|
|
|
934
|
-
// ../contracts/dist/
|
|
994
|
+
// ../contracts/dist/skill-package.js
|
|
935
995
|
import { z as z13 } from "zod";
|
|
936
|
-
var
|
|
937
|
-
|
|
996
|
+
var skillComponentRoleSchema = z13.enum(["skill", "subagent"]);
|
|
997
|
+
var skillBundlePathSchema = z13.string().min(1).refine((value) => {
|
|
998
|
+
if (value === ".")
|
|
999
|
+
return true;
|
|
1000
|
+
return !value.includes("\0") && !value.includes("\\") && !value.startsWith("/") && !/^[A-Za-z]:/.test(value) && value.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
1001
|
+
}, "path must be a normalized relative POSIX path");
|
|
1002
|
+
var skillBundleComponentSchema = z13.object({
|
|
1003
|
+
role: skillComponentRoleSchema,
|
|
1004
|
+
source: skillBundlePathSchema,
|
|
1005
|
+
name: registrySlugSchema.optional(),
|
|
1006
|
+
variants: z13.partialRecord(skillTargetAgentSchema, skillBundlePathSchema).optional()
|
|
1007
|
+
}).strict().superRefine((component, context) => {
|
|
1008
|
+
if (component.role === "skill" && component.variants !== void 0) {
|
|
1009
|
+
context.addIssue({ code: "custom", message: "skill components cannot define agent variants" });
|
|
1010
|
+
}
|
|
1011
|
+
if (component.role === "subagent" && (component.name === void 0 || component.variants === void 0 || Object.keys(component.variants).length === 0)) {
|
|
1012
|
+
context.addIssue({ code: "custom", message: "subagent components require a name and variants" });
|
|
1013
|
+
}
|
|
1014
|
+
}).superRefine((component, context) => {
|
|
1015
|
+
if (component.role === "subagent" && component.source !== ".") {
|
|
1016
|
+
context.addIssue({ code: "custom", message: "subagent source must be '.'; variants select native files" });
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
var authorSkillBundleManifestSchema = z13.object({
|
|
1020
|
+
apiVersion: z13.literal("hunter-harness/v1"),
|
|
1021
|
+
kind: z13.literal("SkillBundle"),
|
|
1022
|
+
components: z13.array(skillBundleComponentSchema).min(1)
|
|
1023
|
+
}).strict().superRefine((manifest, context) => {
|
|
1024
|
+
if (!manifest.components.some((component) => component.role === "skill")) {
|
|
1025
|
+
context.addIssue({ code: "custom", message: "bundle requires a skill component" });
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
var skillPackageFileSchema = z13.object({
|
|
1029
|
+
path: skillBundlePathSchema,
|
|
1030
|
+
sha256: sha256Schema,
|
|
1031
|
+
size: z13.number().int().nonnegative()
|
|
1032
|
+
}).strict();
|
|
1033
|
+
var skillPackageVariantSchema = z13.object({
|
|
1034
|
+
status: skillVariantStatusSchema,
|
|
1035
|
+
adapterVersion: z13.string().min(1),
|
|
1036
|
+
buildHash: sha256Schema.nullable(),
|
|
1037
|
+
components: z13.array(z13.string().min(1))
|
|
1038
|
+
}).strict();
|
|
1039
|
+
var skillPackageManifestV3Schema = z13.object({
|
|
1040
|
+
schema_version: z13.literal(3),
|
|
1041
|
+
slug: registrySlugSchema,
|
|
1042
|
+
version: registrySemverSchema,
|
|
1043
|
+
files: z13.array(skillPackageFileSchema),
|
|
1044
|
+
components: z13.array(skillBundleComponentSchema).min(1),
|
|
1045
|
+
variants: z13.record(skillTargetAgentSchema, skillPackageVariantSchema)
|
|
1046
|
+
}).strict();
|
|
1047
|
+
|
|
1048
|
+
// ../contracts/dist/workflow-family.js
|
|
1049
|
+
import { z as z14 } from "zod";
|
|
1050
|
+
var workflowBundleManifestSchema = z14.object({
|
|
1051
|
+
schema_version: z14.literal(1),
|
|
938
1052
|
profile: registrySlugSchema,
|
|
939
|
-
files:
|
|
940
|
-
path:
|
|
1053
|
+
files: z14.array(z14.object({
|
|
1054
|
+
path: z14.string().min(1),
|
|
941
1055
|
sha256: sha256Schema
|
|
942
1056
|
}).strict()).min(1)
|
|
943
1057
|
}).strict();
|
|
944
|
-
var workflowFamilyBundleArtifactSchema =
|
|
945
|
-
artifact_id:
|
|
1058
|
+
var workflowFamilyBundleArtifactSchema = z14.object({
|
|
1059
|
+
artifact_id: z14.string().regex(/^wfb_/),
|
|
946
1060
|
family_slug: registrySlugSchema,
|
|
947
1061
|
profile: registrySlugSchema,
|
|
948
1062
|
version: registrySemverSchema,
|
|
949
1063
|
content_sha256: sha256Schema,
|
|
950
|
-
size_bytes:
|
|
1064
|
+
size_bytes: z14.number().int().nonnegative(),
|
|
951
1065
|
bundle_manifest: workflowBundleManifestSchema,
|
|
952
|
-
created_at:
|
|
1066
|
+
created_at: z14.iso.datetime()
|
|
953
1067
|
}).strict();
|
|
954
|
-
var workflowFamilyVersionProfileSchema =
|
|
1068
|
+
var workflowFamilyVersionProfileSchema = z14.object({
|
|
955
1069
|
profile: registrySlugSchema,
|
|
956
1070
|
bundle_manifest: workflowBundleManifestSchema,
|
|
957
|
-
artifact_id:
|
|
958
|
-
sourceFiles:
|
|
1071
|
+
artifact_id: z14.string().regex(/^wfb_/),
|
|
1072
|
+
sourceFiles: z14.array(sourceFileSchema).default([])
|
|
959
1073
|
}).strict();
|
|
960
|
-
var workflowFamilyVersionSchema =
|
|
1074
|
+
var workflowFamilyVersionSchema = z14.object({
|
|
961
1075
|
family_slug: registrySlugSchema,
|
|
962
1076
|
version: registrySemverSchema,
|
|
963
|
-
profiles:
|
|
964
|
-
artifacts:
|
|
965
|
-
changeNote:
|
|
966
|
-
created_at:
|
|
1077
|
+
profiles: z14.array(workflowFamilyVersionProfileSchema).min(1),
|
|
1078
|
+
artifacts: z14.array(workflowFamilyBundleArtifactSchema),
|
|
1079
|
+
changeNote: z14.string().nullable(),
|
|
1080
|
+
created_at: z14.iso.datetime()
|
|
967
1081
|
}).strict();
|
|
968
|
-
var workflowFamilyDraftProfileSchema =
|
|
1082
|
+
var workflowFamilyDraftProfileSchema = z14.object({
|
|
969
1083
|
profile: registrySlugSchema,
|
|
970
|
-
sourceFiles:
|
|
1084
|
+
sourceFiles: z14.array(sourceFileSchema),
|
|
971
1085
|
bundle_manifest: workflowBundleManifestSchema
|
|
972
1086
|
}).strict();
|
|
973
|
-
var workflowFamilyDraftStateSchema =
|
|
1087
|
+
var workflowFamilyDraftStateSchema = z14.object({
|
|
974
1088
|
family_slug: registrySlugSchema,
|
|
975
|
-
profiles:
|
|
976
|
-
required_profiles:
|
|
1089
|
+
profiles: z14.array(workflowFamilyDraftProfileSchema),
|
|
1090
|
+
required_profiles: z14.array(registrySlugSchema),
|
|
977
1091
|
draftVersion: registrySemverSchema.nullable(),
|
|
978
1092
|
checks: skillCheckResultSchema.nullable(),
|
|
979
|
-
releaseNote:
|
|
980
|
-
revision:
|
|
981
|
-
created_at:
|
|
982
|
-
updated_at:
|
|
1093
|
+
releaseNote: z14.string().nullable(),
|
|
1094
|
+
revision: z14.number().int(),
|
|
1095
|
+
created_at: z14.string(),
|
|
1096
|
+
updated_at: z14.string()
|
|
983
1097
|
}).strict();
|
|
984
|
-
var workflowFamilySchema =
|
|
985
|
-
family_id:
|
|
1098
|
+
var workflowFamilySchema = z14.object({
|
|
1099
|
+
family_id: z14.string().regex(/^wff_/),
|
|
986
1100
|
slug: registrySlugSchema,
|
|
987
|
-
displayName:
|
|
988
|
-
description:
|
|
989
|
-
tags:
|
|
1101
|
+
displayName: z14.string().min(1).max(120),
|
|
1102
|
+
description: z14.string().min(1).max(1e3),
|
|
1103
|
+
tags: z14.array(registrySlugSchema).default([]),
|
|
990
1104
|
latest_version: registrySemverSchema.nullable(),
|
|
991
|
-
required_profiles:
|
|
992
|
-
revision:
|
|
993
|
-
npmReleases:
|
|
994
|
-
created_at:
|
|
995
|
-
updated_at:
|
|
1105
|
+
required_profiles: z14.array(registrySlugSchema).min(1),
|
|
1106
|
+
revision: z14.number().int().positive(),
|
|
1107
|
+
npmReleases: z14.array(npmReleaseRecordSchema).optional().default([]),
|
|
1108
|
+
created_at: z14.iso.datetime(),
|
|
1109
|
+
updated_at: z14.iso.datetime()
|
|
996
1110
|
}).strict();
|
|
997
|
-
var workflowFamilyMutationSchema =
|
|
1111
|
+
var workflowFamilyMutationSchema = z14.object({
|
|
998
1112
|
slug: registrySlugSchema,
|
|
999
|
-
displayName:
|
|
1000
|
-
description:
|
|
1001
|
-
tags:
|
|
1002
|
-
required_profiles:
|
|
1113
|
+
displayName: z14.string().min(1).max(120),
|
|
1114
|
+
description: z14.string().min(1).max(1e3),
|
|
1115
|
+
tags: z14.array(registrySlugSchema).default([]),
|
|
1116
|
+
required_profiles: z14.array(registrySlugSchema).min(1)
|
|
1003
1117
|
}).strict();
|
|
1004
|
-
var publishWorkflowFamilyRequestSchema =
|
|
1118
|
+
var publishWorkflowFamilyRequestSchema = z14.object({
|
|
1005
1119
|
version: registrySemverSchema,
|
|
1006
|
-
releaseNote:
|
|
1120
|
+
releaseNote: z14.string().optional()
|
|
1007
1121
|
}).strict();
|
|
1008
|
-
var registryProjectWorkflowBindingSchema =
|
|
1009
|
-
project_id:
|
|
1122
|
+
var registryProjectWorkflowBindingSchema = z14.object({
|
|
1123
|
+
project_id: z14.string().regex(/^prj_/),
|
|
1010
1124
|
family_slug: registrySlugSchema,
|
|
1011
1125
|
profile: registrySlugSchema,
|
|
1012
1126
|
version: registrySemverSchema.nullable().optional(),
|
|
1013
|
-
revision:
|
|
1014
|
-
updated_at:
|
|
1127
|
+
revision: z14.number().int().positive(),
|
|
1128
|
+
updated_at: z14.iso.datetime()
|
|
1015
1129
|
}).strict();
|
|
1016
|
-
var bindProjectWorkflowFamilyRequestSchema =
|
|
1017
|
-
schema_version:
|
|
1130
|
+
var bindProjectWorkflowFamilyRequestSchema = z14.object({
|
|
1131
|
+
schema_version: z14.literal(1),
|
|
1018
1132
|
family_slug: registrySlugSchema,
|
|
1019
1133
|
profile: registrySlugSchema,
|
|
1020
1134
|
version: registrySemverSchema.nullable().optional(),
|
|
1021
|
-
revision:
|
|
1135
|
+
revision: z14.number().int().nullable()
|
|
1022
1136
|
}).strict();
|
|
1023
1137
|
|
|
1024
1138
|
// ../core/dist/fs/hash.js
|
|
@@ -1030,6 +1144,10 @@ function sha256Bytes(content) {
|
|
|
1030
1144
|
async function sha256File(path) {
|
|
1031
1145
|
return sha256Bytes(await readFile(path));
|
|
1032
1146
|
}
|
|
1147
|
+
function aggregateInstalledContentHash(files) {
|
|
1148
|
+
const lines = [...files].sort((a, b) => a.relpath.localeCompare(b.relpath)).map((entry) => `${entry.relpath}:${entry.sha256}`);
|
|
1149
|
+
return createHash("sha256").update(lines.join("\n"), "utf8").digest("hex");
|
|
1150
|
+
}
|
|
1033
1151
|
|
|
1034
1152
|
// ../core/dist/fs/path-safety.js
|
|
1035
1153
|
import { lstat } from "node:fs/promises";
|
|
@@ -1613,7 +1731,7 @@ function decideUpdate(policy, dirty) {
|
|
|
1613
1731
|
|
|
1614
1732
|
// ../core/dist/project/initialize.js
|
|
1615
1733
|
import { createHash as createHash4 } from "node:crypto";
|
|
1616
|
-
import { readFile as readFile4, stat as stat2 } from "node:fs/promises";
|
|
1734
|
+
import { readFile as readFile4, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
|
|
1617
1735
|
import { basename, join as join5, resolve as resolve3 } from "node:path";
|
|
1618
1736
|
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
1619
1737
|
|
|
@@ -2311,6 +2429,27 @@ function uuidV7(now = Date.now()) {
|
|
|
2311
2429
|
}
|
|
2312
2430
|
|
|
2313
2431
|
// ../core/dist/project/initialize.js
|
|
2432
|
+
var CONTEXT_INDEX_PATH = ".harness/context-index.json";
|
|
2433
|
+
async function fileHex(path) {
|
|
2434
|
+
try {
|
|
2435
|
+
const data = await readFile4(path);
|
|
2436
|
+
return createHash4("sha256").update(data).digest("hex");
|
|
2437
|
+
} catch {
|
|
2438
|
+
return null;
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
async function readExistingSkillBundles(root) {
|
|
2442
|
+
const text = await readOptional(join5(root, CONTEXT_INDEX_PATH));
|
|
2443
|
+
if (text === "")
|
|
2444
|
+
return /* @__PURE__ */ new Map();
|
|
2445
|
+
try {
|
|
2446
|
+
const parsed = JSON.parse(text);
|
|
2447
|
+
const bundles = parsed.skill_bundles ?? {};
|
|
2448
|
+
return new Map(Object.entries(bundles));
|
|
2449
|
+
} catch {
|
|
2450
|
+
return /* @__PURE__ */ new Map();
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2314
2453
|
var TargetCollisionError = class extends Error {
|
|
2315
2454
|
code = "TARGET_COLLISION";
|
|
2316
2455
|
exitCode = 7;
|
|
@@ -2405,6 +2544,7 @@ async function initializeProject(options) {
|
|
|
2405
2544
|
const manifests = [];
|
|
2406
2545
|
const adaptersIndex = {};
|
|
2407
2546
|
const skillBundles = {};
|
|
2547
|
+
const existingContextBundles = await readExistingSkillBundles(root);
|
|
2408
2548
|
let primaryBundleHash = "";
|
|
2409
2549
|
let primaryRegistryVersion = "";
|
|
2410
2550
|
for (const agent of enabledAgents) {
|
|
@@ -2424,7 +2564,8 @@ async function initializeProject(options) {
|
|
|
2424
2564
|
});
|
|
2425
2565
|
skillBundles[agent] = {
|
|
2426
2566
|
registry_version: bundle.manifest.bundle_version,
|
|
2427
|
-
bundle_hash: bundleHash
|
|
2567
|
+
bundle_hash: bundleHash,
|
|
2568
|
+
...existingContextBundles.get(agent) ?? {}
|
|
2428
2569
|
};
|
|
2429
2570
|
adaptersIndex[agent] = adapter.contextIndex(adapterContext);
|
|
2430
2571
|
for (const target of targets) {
|
|
@@ -2541,6 +2682,7 @@ async function initializeProject(options) {
|
|
|
2541
2682
|
if (!options.dryRun) {
|
|
2542
2683
|
const writeOperations = await Promise.all([...files.entries()].map(async ([path, content]) => operationFor(root, path, content)));
|
|
2543
2684
|
await runTransaction(root, writeOperations, { kind: "init" });
|
|
2685
|
+
await enrichContextIndexWithVerification(root, enabledAgents, profile, options.resourcesRoot, adapterContext);
|
|
2544
2686
|
}
|
|
2545
2687
|
return {
|
|
2546
2688
|
projectConfig,
|
|
@@ -2549,6 +2691,52 @@ async function initializeProject(options) {
|
|
|
2549
2691
|
registryVersion: primaryRegistryVersion
|
|
2550
2692
|
};
|
|
2551
2693
|
}
|
|
2694
|
+
async function enrichContextIndexWithVerification(root, agents, profile, resourcesRoot, adapterContext) {
|
|
2695
|
+
const contextPath = join5(root, CONTEXT_INDEX_PATH);
|
|
2696
|
+
const existing = await readOptional(join5(contextPath));
|
|
2697
|
+
if (existing === "")
|
|
2698
|
+
return;
|
|
2699
|
+
let parsed;
|
|
2700
|
+
try {
|
|
2701
|
+
parsed = JSON.parse(existing);
|
|
2702
|
+
} catch {
|
|
2703
|
+
return;
|
|
2704
|
+
}
|
|
2705
|
+
const bundles = parsed.skill_bundles ?? {};
|
|
2706
|
+
for (const agent of agents) {
|
|
2707
|
+
const entry = bundles[agent];
|
|
2708
|
+
if (!entry)
|
|
2709
|
+
continue;
|
|
2710
|
+
let loadedBundle;
|
|
2711
|
+
try {
|
|
2712
|
+
loadedBundle = await loadAgentBundle(resourcesRoot, profile, agent);
|
|
2713
|
+
} catch {
|
|
2714
|
+
continue;
|
|
2715
|
+
}
|
|
2716
|
+
const targets = managedTargetsFor(getAdapter(agent), loadedBundle, adapterContext);
|
|
2717
|
+
const mismatches = [];
|
|
2718
|
+
const entries = [];
|
|
2719
|
+
for (const target of targets) {
|
|
2720
|
+
const rel = target.target_path.replace(/\\/g, "/");
|
|
2721
|
+
const actual = await fileHex(join5(root, target.target_path));
|
|
2722
|
+
entries.push({ relpath: rel, sha256: actual ?? "" });
|
|
2723
|
+
if (actual === null) {
|
|
2724
|
+
mismatches.push({ relpath: rel, expected: target.sha256, actual: "<missing>" });
|
|
2725
|
+
} else if (actual !== target.sha256) {
|
|
2726
|
+
mismatches.push({ relpath: rel, expected: target.sha256, actual });
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
entry.installedContentHash = aggregateInstalledContentHash(entries);
|
|
2730
|
+
const newStatus = mismatches.length === 0 ? "verified" : "degraded";
|
|
2731
|
+
if (newStatus === "verified" && typeof entry.verifiedAt === "string" && entry.verifiedAt !== "") {
|
|
2732
|
+
} else {
|
|
2733
|
+
entry.verifiedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2734
|
+
}
|
|
2735
|
+
entry.verificationStatus = newStatus;
|
|
2736
|
+
entry.mismatchDetails = mismatches;
|
|
2737
|
+
}
|
|
2738
|
+
await writeFile3(contextPath, JSON.stringify(parsed, null, 2) + "\n", "utf8");
|
|
2739
|
+
}
|
|
2552
2740
|
|
|
2553
2741
|
// ../core/dist/project/refresh.js
|
|
2554
2742
|
import { createHash as createHash5 } from "node:crypto";
|
|
@@ -2556,8 +2744,8 @@ import { readFile as readFile5, readdir as readdir3, rmdir } from "node:fs/promi
|
|
|
2556
2744
|
import { dirname as dirname3, join as join6, resolve as resolve4 } from "node:path";
|
|
2557
2745
|
import { parse as parseYaml3, stringify as stringifyYaml2 } from "yaml";
|
|
2558
2746
|
var INSTALLED_STATE_PATH = ".harness/state/local/installed-harness-bundle.json";
|
|
2559
|
-
var
|
|
2560
|
-
async function
|
|
2747
|
+
var CONTEXT_INDEX_PATH2 = ".harness/context-index.json";
|
|
2748
|
+
async function fileHex2(path) {
|
|
2561
2749
|
try {
|
|
2562
2750
|
return createHash5("sha256").update(await readFile5(path)).digest("hex");
|
|
2563
2751
|
} catch (error) {
|
|
@@ -2658,7 +2846,7 @@ async function readInstalledAgentConfiguration(projectRoot) {
|
|
|
2658
2846
|
};
|
|
2659
2847
|
}
|
|
2660
2848
|
async function readContextIndexBundleHash(root) {
|
|
2661
|
-
const content = await readOptionalText(join6(root,
|
|
2849
|
+
const content = await readOptionalText(join6(root, CONTEXT_INDEX_PATH2));
|
|
2662
2850
|
if (content === "")
|
|
2663
2851
|
return null;
|
|
2664
2852
|
try {
|
|
@@ -2713,8 +2901,20 @@ function conflict(target, reason, oldSha, incomingSha) {
|
|
|
2713
2901
|
function sortByTarget(items) {
|
|
2714
2902
|
return [...items].sort((left, right) => left.target_path.localeCompare(right.target_path));
|
|
2715
2903
|
}
|
|
2716
|
-
async function reconcileContextIndex(root, agents, profiles, manifests, codebuddySurface2) {
|
|
2717
|
-
const existing = await readOptionalText(join6(root,
|
|
2904
|
+
async function reconcileContextIndex(root, agents, profiles, manifests, codebuddySurface2, verifications) {
|
|
2905
|
+
const existing = await readOptionalText(join6(root, CONTEXT_INDEX_PATH2));
|
|
2906
|
+
let codebase = {
|
|
2907
|
+
map: ".harness/codebase/map",
|
|
2908
|
+
status: "missing"
|
|
2909
|
+
};
|
|
2910
|
+
try {
|
|
2911
|
+
const parsed = JSON.parse(existing);
|
|
2912
|
+
const current = parsed.codebase;
|
|
2913
|
+
if (typeof current?.map === "string" && (current.status === "missing" || current.status === "stale" || current.status === "fresh")) {
|
|
2914
|
+
codebase = { map: current.map, status: current.status };
|
|
2915
|
+
}
|
|
2916
|
+
} catch {
|
|
2917
|
+
}
|
|
2718
2918
|
const record = {
|
|
2719
2919
|
schema_version: 2,
|
|
2720
2920
|
project: {
|
|
@@ -2728,18 +2928,28 @@ async function reconcileContextIndex(root, agents, profiles, manifests, codebudd
|
|
|
2728
2928
|
]))
|
|
2729
2929
|
},
|
|
2730
2930
|
knowledge: { index: ".harness/knowledge/index.json" },
|
|
2731
|
-
codebase
|
|
2732
|
-
skill_bundles: Object.fromEntries(manifests.map((manifest) =>
|
|
2733
|
-
manifest.adapter
|
|
2734
|
-
|
|
2735
|
-
|
|
2931
|
+
codebase,
|
|
2932
|
+
skill_bundles: Object.fromEntries(manifests.map((manifest) => {
|
|
2933
|
+
const ver = verifications.get(manifest.adapter);
|
|
2934
|
+
return [
|
|
2935
|
+
manifest.adapter,
|
|
2936
|
+
{
|
|
2937
|
+
registry_version: manifest.bundle_version,
|
|
2938
|
+
bundle_hash: manifest.bundle_manifest_hash,
|
|
2939
|
+
installedContentHash: ver?.installedContentHash ?? null,
|
|
2940
|
+
verifiedAt: ver?.verifiedAt ?? null,
|
|
2941
|
+
verificationStatus: ver?.verificationStatus ?? "unknown",
|
|
2942
|
+
mismatchDetails: ver?.mismatchDetails ?? []
|
|
2943
|
+
}
|
|
2944
|
+
];
|
|
2945
|
+
}))
|
|
2736
2946
|
};
|
|
2737
2947
|
const next = JSON.stringify(record, null, 2) + "\n";
|
|
2738
2948
|
if (existing === next)
|
|
2739
2949
|
return null;
|
|
2740
2950
|
return {
|
|
2741
2951
|
operation: existing === "" ? "add" : "modify",
|
|
2742
|
-
path:
|
|
2952
|
+
path: CONTEXT_INDEX_PATH2,
|
|
2743
2953
|
content: next
|
|
2744
2954
|
};
|
|
2745
2955
|
}
|
|
@@ -2903,7 +3113,7 @@ async function refreshProject(options) {
|
|
|
2903
3113
|
const newStateFiles = installed.files.filter((entry) => entry.owner === "shared" || !selectedSet.has(entry.owner));
|
|
2904
3114
|
for (const target of newManaged) {
|
|
2905
3115
|
const incoming = target.sha256;
|
|
2906
|
-
const current = await
|
|
3116
|
+
const current = await fileHex2(join6(root, target.target_path));
|
|
2907
3117
|
if (current === null) {
|
|
2908
3118
|
applied.push(item(target, "add", "MISSING_TARGET", null, incoming));
|
|
2909
3119
|
ops.push({ operation: "add", path: target.target_path, content: target.bytes });
|
|
@@ -2931,7 +3141,7 @@ async function refreshProject(options) {
|
|
|
2931
3141
|
}
|
|
2932
3142
|
}
|
|
2933
3143
|
for (const target of oldOnly) {
|
|
2934
|
-
const current = await
|
|
3144
|
+
const current = await fileHex2(join6(root, target.target_path));
|
|
2935
3145
|
if (current === null) {
|
|
2936
3146
|
continue;
|
|
2937
3147
|
}
|
|
@@ -2957,7 +3167,48 @@ async function refreshProject(options) {
|
|
|
2957
3167
|
const projectOperation = await projectTransitionOperation(root, agents, profiles, codebuddySurface2);
|
|
2958
3168
|
if (projectOperation !== null)
|
|
2959
3169
|
ops.push(projectOperation);
|
|
2960
|
-
const
|
|
3170
|
+
const verifications = /* @__PURE__ */ new Map();
|
|
3171
|
+
for (const agent of selectedAgents) {
|
|
3172
|
+
const agentProfile = profiles.get(agent) ?? profile;
|
|
3173
|
+
let bundleForVerify;
|
|
3174
|
+
try {
|
|
3175
|
+
bundleForVerify = await loadAgentBundle(options.resourcesRoot, agentProfile, agent);
|
|
3176
|
+
} catch {
|
|
3177
|
+
continue;
|
|
3178
|
+
}
|
|
3179
|
+
const verifyTargets = managedTargetsFor(getAdapter(agent), bundleForVerify, {
|
|
3180
|
+
profile: agentProfile,
|
|
3181
|
+
codebuddySurface: codebuddySurface2
|
|
3182
|
+
});
|
|
3183
|
+
const verifyMismatches = [];
|
|
3184
|
+
const verifyEntries = [];
|
|
3185
|
+
for (const target of verifyTargets) {
|
|
3186
|
+
const rel = target.target_path.replace(/\\/g, "/");
|
|
3187
|
+
const actual = await fileHex2(join6(root, target.target_path));
|
|
3188
|
+
verifyEntries.push({ relpath: rel, sha256: actual ?? "" });
|
|
3189
|
+
if (actual === null) {
|
|
3190
|
+
verifyMismatches.push({ relpath: rel, expected: target.sha256, actual: "<missing>" });
|
|
3191
|
+
} else if (actual !== target.sha256) {
|
|
3192
|
+
verifyMismatches.push({ relpath: rel, expected: target.sha256, actual });
|
|
3193
|
+
}
|
|
3194
|
+
}
|
|
3195
|
+
verifications.set(agent, {
|
|
3196
|
+
adapter: agent,
|
|
3197
|
+
bundleVersion: bundleForVerify.manifest.bundle_version,
|
|
3198
|
+
installedBundleVersion: null,
|
|
3199
|
+
manifestHash: null,
|
|
3200
|
+
installedManifestHash: null,
|
|
3201
|
+
coreHash: null,
|
|
3202
|
+
installedCoreHash: null,
|
|
3203
|
+
adapterHash: null,
|
|
3204
|
+
installedAdapterHash: null,
|
|
3205
|
+
installedContentHash: aggregateInstalledContentHash(verifyEntries),
|
|
3206
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3207
|
+
verificationStatus: verifyMismatches.length === 0 ? "verified" : "degraded",
|
|
3208
|
+
mismatchDetails: verifyMismatches
|
|
3209
|
+
});
|
|
3210
|
+
}
|
|
3211
|
+
const contextOperation = await reconcileContextIndex(root, agents, profiles, manifests, codebuddySurface2, verifications);
|
|
2961
3212
|
if (contextOperation !== null)
|
|
2962
3213
|
ops.push(contextOperation);
|
|
2963
3214
|
const managedBlocks = [
|
|
@@ -3028,6 +3279,14 @@ async function refreshProject(options) {
|
|
|
3028
3279
|
function freshnessEntry(agent, profile, status, identity) {
|
|
3029
3280
|
return { agent, profile, status, identity, driftedFiles: [], missingFiles: [] };
|
|
3030
3281
|
}
|
|
3282
|
+
function emptyVerification() {
|
|
3283
|
+
return {
|
|
3284
|
+
installedContentHash: null,
|
|
3285
|
+
verifiedAt: null,
|
|
3286
|
+
verificationStatus: "unknown",
|
|
3287
|
+
mismatchDetails: []
|
|
3288
|
+
};
|
|
3289
|
+
}
|
|
3031
3290
|
var BUILD_MARKER_BUNDLE_PATH = ".harness-build.json";
|
|
3032
3291
|
function buildMarkerCoreHash(text) {
|
|
3033
3292
|
if (text === null || text === "")
|
|
@@ -3057,7 +3316,8 @@ async function collectFreshness(options) {
|
|
|
3057
3316
|
coreHash: null,
|
|
3058
3317
|
installedCoreHash: null,
|
|
3059
3318
|
adapterHash: null,
|
|
3060
|
-
installedAdapterHash: null
|
|
3319
|
+
installedAdapterHash: null,
|
|
3320
|
+
...emptyVerification()
|
|
3061
3321
|
};
|
|
3062
3322
|
let officialHash = null;
|
|
3063
3323
|
let officialVersion = null;
|
|
@@ -3084,13 +3344,29 @@ async function collectFreshness(options) {
|
|
|
3084
3344
|
identity.adapterHash = sha256Bytes(canonicalJson(targets.map((target) => ({ path: target.target_path.replace(/\\/g, "/"), sha256: target.sha256 })).sort((a, b) => a.path.localeCompare(b.path))));
|
|
3085
3345
|
const installedProjection = await Promise.all(targets.map(async (target) => ({
|
|
3086
3346
|
path: target.target_path.replace(/\\/g, "/"),
|
|
3087
|
-
sha256: await
|
|
3347
|
+
sha256: await fileHex2(join6(root, target.target_path))
|
|
3088
3348
|
})));
|
|
3089
3349
|
identity.installedAdapterHash = sha256Bytes(canonicalJson(installedProjection.sort((a, b) => a.path.localeCompare(b.path))));
|
|
3090
3350
|
const markerTarget = targets.find((target) => target.target_path.replace(/\\/g, "/").endsWith(`/${BUILD_MARKER_BUNDLE_PATH}`) || target.target_path === BUILD_MARKER_BUNDLE_PATH);
|
|
3091
3351
|
if (markerTarget !== void 0) {
|
|
3092
3352
|
identity.installedCoreHash = buildMarkerCoreHash(await readOptionalText(join6(root, markerTarget.target_path)));
|
|
3093
3353
|
}
|
|
3354
|
+
const mismatchDetails = [];
|
|
3355
|
+
const contentEntries = [];
|
|
3356
|
+
for (const target of targets) {
|
|
3357
|
+
const rel = target.target_path.replace(/\\/g, "/");
|
|
3358
|
+
const actual = await fileHex2(join6(root, target.target_path));
|
|
3359
|
+
contentEntries.push({ relpath: rel, sha256: actual ?? "" });
|
|
3360
|
+
if (actual === null) {
|
|
3361
|
+
mismatchDetails.push({ relpath: rel, expected: target.sha256, actual: "<missing>" });
|
|
3362
|
+
} else if (actual !== target.sha256) {
|
|
3363
|
+
mismatchDetails.push({ relpath: rel, expected: target.sha256, actual });
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
identity.installedContentHash = aggregateInstalledContentHash(contentEntries);
|
|
3367
|
+
identity.verifiedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3368
|
+
identity.verificationStatus = mismatchDetails.length === 0 ? "verified" : "degraded";
|
|
3369
|
+
identity.mismatchDetails = mismatchDetails;
|
|
3094
3370
|
if (requestedProfile !== installedProfile) {
|
|
3095
3371
|
agents.push(freshnessEntry(agent, installedProfile, "PROFILE_MISMATCH", identity));
|
|
3096
3372
|
continue;
|
|
@@ -3102,7 +3378,7 @@ async function collectFreshness(options) {
|
|
|
3102
3378
|
const drifted = [];
|
|
3103
3379
|
const missing = [];
|
|
3104
3380
|
for (const target of targets) {
|
|
3105
|
-
const current = await
|
|
3381
|
+
const current = await fileHex2(join6(root, target.target_path));
|
|
3106
3382
|
if (current === null) {
|
|
3107
3383
|
missing.push(target.target_path);
|
|
3108
3384
|
} else if (current !== target.sha256) {
|
|
@@ -3292,7 +3568,7 @@ function highEntropyCandidates(content) {
|
|
|
3292
3568
|
}
|
|
3293
3569
|
|
|
3294
3570
|
// ../core/dist/security/scanner.js
|
|
3295
|
-
var SENSITIVE_SCANNER_VERSION = "1.
|
|
3571
|
+
var SENSITIVE_SCANNER_VERSION = "1.1.0";
|
|
3296
3572
|
var RULES = [
|
|
3297
3573
|
{
|
|
3298
3574
|
id: "HH_PRIVATE_KEY",
|
|
@@ -3347,6 +3623,9 @@ function rawFindings(content) {
|
|
|
3347
3623
|
for (const rule of RULES) {
|
|
3348
3624
|
for (const match of content.matchAll(rule.pattern)) {
|
|
3349
3625
|
const value = match[rule.valueGroup ?? 0] ?? match[0];
|
|
3626
|
+
if (rule.id === "HH_PASSWORD_VALUE" && isObviousPlaceholder(value)) {
|
|
3627
|
+
continue;
|
|
3628
|
+
}
|
|
3350
3629
|
const relative3 = match[0].indexOf(value);
|
|
3351
3630
|
findings.push({
|
|
3352
3631
|
ruleId: rule.id,
|
|
@@ -3357,6 +3636,8 @@ function rawFindings(content) {
|
|
|
3357
3636
|
}
|
|
3358
3637
|
}
|
|
3359
3638
|
for (const candidate of highEntropyCandidates(content)) {
|
|
3639
|
+
if (!hasSensitiveLexicalContext(content, candidate.offset))
|
|
3640
|
+
continue;
|
|
3360
3641
|
findings.push({
|
|
3361
3642
|
ruleId: "HH_HIGH_ENTROPY",
|
|
3362
3643
|
severity: "high",
|
|
@@ -3366,6 +3647,17 @@ function rawFindings(content) {
|
|
|
3366
3647
|
}
|
|
3367
3648
|
return findings;
|
|
3368
3649
|
}
|
|
3650
|
+
function isObviousPlaceholder(value) {
|
|
3651
|
+
const trimmed = value.trim();
|
|
3652
|
+
return /^\$\([^)]+\)$/.test(trimmed) || /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(trimmed) || /^\{\{[^{}]+\}\}$/.test(trimmed) || /^<[^<>]+>$/.test(trimmed) || /^(?:example|placeholder|your[-_][a-z0-9_-]+)$/i.test(trimmed);
|
|
3653
|
+
}
|
|
3654
|
+
function hasSensitiveLexicalContext(content, offset) {
|
|
3655
|
+
const lineStart = content.lastIndexOf("\n", Math.max(0, offset - 1)) + 1;
|
|
3656
|
+
const nextLineBreak = content.indexOf("\n", offset);
|
|
3657
|
+
const lineEnd = nextLineBreak === -1 ? content.length : nextLineBreak;
|
|
3658
|
+
const line = content.slice(lineStart, lineEnd);
|
|
3659
|
+
return /(?:secret|token|password|passwd|pwd|api[_-]?key|credential|authorization|bearer)\s*[:=]\s*["']?[A-Za-z0-9._~+/-]{8,}/i.test(line);
|
|
3660
|
+
}
|
|
3369
3661
|
function scanSensitiveFiles(files, options = {}) {
|
|
3370
3662
|
const findings = [];
|
|
3371
3663
|
const evidence = [];
|
|
@@ -3424,6 +3716,8 @@ function scanSensitiveFiles(files, options = {}) {
|
|
|
3424
3716
|
return {
|
|
3425
3717
|
scanner_version: SENSITIVE_SCANNER_VERSION,
|
|
3426
3718
|
blocked: findings.some((finding) => finding.disposition === "blocked"),
|
|
3719
|
+
hard_blocked: findings.some((finding) => finding.disposition === "blocked" && finding.severity === "high"),
|
|
3720
|
+
review_required: findings.some((finding) => finding.disposition === "blocked" && finding.severity !== "high"),
|
|
3427
3721
|
findings,
|
|
3428
3722
|
override_evidence: Object.freeze(evidence)
|
|
3429
3723
|
};
|
|
@@ -3448,7 +3742,7 @@ function generateProposalPreview(input, scanOptions = {}) {
|
|
|
3448
3742
|
}
|
|
3449
3743
|
|
|
3450
3744
|
// ../core/dist/push/credentials.js
|
|
3451
|
-
import { readFile as readFile6, writeFile as
|
|
3745
|
+
import { readFile as readFile6, writeFile as writeFile4 } from "node:fs/promises";
|
|
3452
3746
|
import { join as join7 } from "node:path";
|
|
3453
3747
|
import { parse as parseYaml4, stringify as stringifyYaml3 } from "yaml";
|
|
3454
3748
|
var CREDENTIALS_LOCAL_RELATIVE = ".harness/credentials.local.yaml";
|
|
@@ -3530,7 +3824,7 @@ async function readLocalCredentials(projectRoot) {
|
|
|
3530
3824
|
}
|
|
3531
3825
|
async function writeLocalCredentials(projectRoot, credentials) {
|
|
3532
3826
|
const normalized = validateLocalCredentials(credentials);
|
|
3533
|
-
await
|
|
3827
|
+
await writeFile4(join7(projectRoot, CREDENTIALS_LOCAL_RELATIVE), stringifyYaml3(normalized, { sortMapEntries: true }) + "\n", "utf8");
|
|
3534
3828
|
}
|
|
3535
3829
|
async function ensureCredentialsGitignore(projectRoot) {
|
|
3536
3830
|
const gitignorePath = join7(projectRoot, ".gitignore");
|
|
@@ -3559,7 +3853,7 @@ async function ensureCredentialsGitignore(projectRoot) {
|
|
|
3559
3853
|
return;
|
|
3560
3854
|
}
|
|
3561
3855
|
const suffix = content.length === 0 || content.endsWith("\n") ? "" : "\n";
|
|
3562
|
-
await
|
|
3856
|
+
await writeFile4(gitignorePath, content + suffix + missing.join("\n") + "\n", "utf8");
|
|
3563
3857
|
}
|
|
3564
3858
|
function resolvePushAuth(input) {
|
|
3565
3859
|
const tokenEnv = input.tokenEnv ?? input.projectTokenEnv;
|
|
@@ -3601,7 +3895,7 @@ async function readBaseline(projectRoot) {
|
|
|
3601
3895
|
|
|
3602
3896
|
// ../core/dist/state/locks.js
|
|
3603
3897
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
3604
|
-
import { readFile as readFile8, rename as rename3, rm as rm3, writeFile as
|
|
3898
|
+
import { readFile as readFile8, rename as rename3, rm as rm3, writeFile as writeFile5 } from "node:fs/promises";
|
|
3605
3899
|
import { join as join9 } from "node:path";
|
|
3606
3900
|
async function readLock(path) {
|
|
3607
3901
|
return JSON.parse(await readFile8(path, "utf8"));
|
|
@@ -3621,7 +3915,7 @@ async function acquireProtocolLock(projectRoot, operation, options = {}) {
|
|
|
3621
3915
|
};
|
|
3622
3916
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
3623
3917
|
try {
|
|
3624
|
-
await
|
|
3918
|
+
await writeFile5(lockPath, JSON.stringify(record, null, 2), { flag: "wx" });
|
|
3625
3919
|
return {
|
|
3626
3920
|
path: lockPath,
|
|
3627
3921
|
operation,
|
|
@@ -4986,46 +5280,52 @@ async function cleanupProject(options) {
|
|
|
4986
5280
|
|
|
4987
5281
|
// ../core/dist/skill/frontmatter.js
|
|
4988
5282
|
import { parse as parseYaml6 } from "yaml";
|
|
4989
|
-
import { z as
|
|
5283
|
+
import { z as z15 } from "zod";
|
|
4990
5284
|
|
|
4991
5285
|
// ../core/dist/skill/fixer.js
|
|
4992
5286
|
import { parse as parseYaml7, stringify as stringifyYaml5 } from "yaml";
|
|
4993
5287
|
|
|
4994
|
-
// ../core/dist/skill/
|
|
4995
|
-
var
|
|
4996
|
-
"claude-code": {
|
|
5288
|
+
// ../core/dist/skill/agent-surfaces.js
|
|
5289
|
+
var SURFACES = Object.freeze({
|
|
5290
|
+
"claude-code": Object.freeze({
|
|
4997
5291
|
agent: "claude-code",
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5292
|
+
skillRoots: Object.freeze({ project: ".claude/skills", user: ".claude/skills" }),
|
|
5293
|
+
subagentRoots: Object.freeze({ project: ".claude/agents", user: ".claude/agents" }),
|
|
5294
|
+
subagentFormat: "markdown",
|
|
5295
|
+
subagentExtension: ".md",
|
|
5296
|
+
nativeSkillAliases: Object.freeze([])
|
|
5297
|
+
}),
|
|
5298
|
+
codex: Object.freeze({
|
|
5003
5299
|
agent: "codex",
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5300
|
+
skillRoots: Object.freeze({ project: ".agents/skills", user: ".agents/skills" }),
|
|
5301
|
+
subagentRoots: Object.freeze({ project: ".codex/agents", user: ".codex/agents" }),
|
|
5302
|
+
subagentFormat: "toml",
|
|
5303
|
+
subagentExtension: ".toml",
|
|
5304
|
+
nativeSkillAliases: Object.freeze([])
|
|
5305
|
+
}),
|
|
5306
|
+
cursor: Object.freeze({
|
|
5010
5307
|
agent: "cursor",
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5308
|
+
skillRoots: Object.freeze({ project: ".cursor/skills", user: ".cursor/skills" }),
|
|
5309
|
+
subagentRoots: Object.freeze({ project: ".cursor/agents", user: ".cursor/agents" }),
|
|
5310
|
+
subagentFormat: "markdown",
|
|
5311
|
+
subagentExtension: ".md",
|
|
5312
|
+
nativeSkillAliases: Object.freeze([".agents/skills"])
|
|
5313
|
+
}),
|
|
5314
|
+
codebuddy: Object.freeze({
|
|
5315
|
+
agent: "codebuddy",
|
|
5316
|
+
skillRoots: Object.freeze({ project: ".codebuddy/skills", user: ".codebuddy/skills" }),
|
|
5317
|
+
subagentRoots: Object.freeze({ project: ".codebuddy/agents", user: ".codebuddy/agents" }),
|
|
5318
|
+
subagentFormat: "markdown",
|
|
5319
|
+
subagentExtension: ".md",
|
|
5320
|
+
nativeSkillAliases: Object.freeze([])
|
|
5321
|
+
})
|
|
5322
|
+
});
|
|
5323
|
+
var SKILL_TARGET_AGENTS = Object.freeze([
|
|
5324
|
+
"claude-code",
|
|
5325
|
+
"codex",
|
|
5326
|
+
"cursor",
|
|
5327
|
+
"codebuddy"
|
|
5328
|
+
]);
|
|
5029
5329
|
|
|
5030
5330
|
// ../core/dist/transaction/recovery.js
|
|
5031
5331
|
import { readFile as readFile12, readdir as readdir6, rm as rm7, stat as stat3 } from "node:fs/promises";
|
|
@@ -5408,7 +5708,7 @@ function serializeCliResult(result) {
|
|
|
5408
5708
|
}
|
|
5409
5709
|
|
|
5410
5710
|
// src/config/codebuddy-setup.ts
|
|
5411
|
-
import { mkdir as mkdir4, readFile as readFile15, readdir as readdir7, stat as stat4, writeFile as
|
|
5711
|
+
import { mkdir as mkdir4, readFile as readFile15, readdir as readdir7, stat as stat4, writeFile as writeFile6 } from "node:fs/promises";
|
|
5412
5712
|
import { basename as basename2, dirname as dirname4, extname, join as join16 } from "node:path";
|
|
5413
5713
|
var MANAGED_RULE_NAMES = /* @__PURE__ */ new Set([
|
|
5414
5714
|
"harness-general.md",
|
|
@@ -5482,7 +5782,7 @@ async function applyCodeBuddySetup(options) {
|
|
|
5482
5782
|
continue;
|
|
5483
5783
|
}
|
|
5484
5784
|
await mkdir4(dirname4(target), { recursive: true });
|
|
5485
|
-
await
|
|
5785
|
+
await writeFile6(target, content, { encoding: "utf8", flag: "wx" });
|
|
5486
5786
|
result.copied.push(target);
|
|
5487
5787
|
}
|
|
5488
5788
|
}
|
|
@@ -5503,7 +5803,7 @@ async function applyCodeBuddySetup(options) {
|
|
|
5503
5803
|
codegraph: { command: "codegraph", args: ["serve", "--mcp"] }
|
|
5504
5804
|
}
|
|
5505
5805
|
};
|
|
5506
|
-
await
|
|
5806
|
+
await writeFile6(path, JSON.stringify(next, null, 2) + "\n", "utf8");
|
|
5507
5807
|
result.mcpUpdated = true;
|
|
5508
5808
|
}
|
|
5509
5809
|
}
|
package/package.json
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "hunter-harness",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Local-first, server-governed agent harness",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=22.12.0"
|
|
9
|
-
},
|
|
10
|
-
"bin": {
|
|
11
|
-
"hunter-harness": "dist/bin.js"
|
|
12
|
-
},
|
|
13
|
-
"files": [
|
|
14
|
-
"dist/bin.js"
|
|
15
|
-
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"build": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json && npm run bundle",
|
|
18
|
-
"bundle": "node ../../scripts/bundle-cli.mjs",
|
|
19
|
-
"typecheck": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json --noEmit",
|
|
20
|
-
"prepack": "npm run build"
|
|
21
|
-
},
|
|
22
|
-
"dependencies": {
|
|
23
|
-
"commander": "15.0.0",
|
|
24
|
-
"yaml": "2.9.0",
|
|
25
|
-
"zod": "4.4.3"
|
|
26
|
-
},
|
|
27
|
-
"optionalDependencies": {
|
|
28
|
-
"pacote": "21.4.0"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@hunter-harness/contracts": "*",
|
|
32
|
-
"@hunter-harness/core": "*",
|
|
33
|
-
"@types/pacote": "^11.1.8",
|
|
34
|
-
"esbuild": "^0.25.12"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "hunter-harness",
|
|
3
|
+
"version": "0.2.20",
|
|
4
|
+
"description": "Local-first, server-governed agent harness",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.12.0"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"hunter-harness": "dist/bin.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/bin.js"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json && npm run bundle",
|
|
18
|
+
"bundle": "node ../../scripts/bundle-cli.mjs",
|
|
19
|
+
"typecheck": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json --noEmit",
|
|
20
|
+
"prepack": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"commander": "15.0.0",
|
|
24
|
+
"yaml": "2.9.0",
|
|
25
|
+
"zod": "4.4.3"
|
|
26
|
+
},
|
|
27
|
+
"optionalDependencies": {
|
|
28
|
+
"pacote": "21.4.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@hunter-harness/contracts": "*",
|
|
32
|
+
"@hunter-harness/core": "*",
|
|
33
|
+
"@types/pacote": "^11.1.8",
|
|
34
|
+
"esbuild": "^0.25.12"
|
|
35
|
+
}
|
|
36
|
+
}
|