hunter-harness 0.2.16 → 0.2.18
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 +135 -0
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -1929,6 +1929,11 @@ function validateRelativeBundlePath(path) {
|
|
|
1929
1929
|
throw new Error("invalid Harness Bundle path");
|
|
1930
1930
|
}
|
|
1931
1931
|
}
|
|
1932
|
+
function validateChangeId(changeId) {
|
|
1933
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(changeId) || changeId === "." || changeId === "..") {
|
|
1934
|
+
throw new Error(`invalid Harness change id: ${changeId}`);
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1932
1937
|
function ruleTarget(sourcePath, targetPath, content) {
|
|
1933
1938
|
return {
|
|
1934
1939
|
source_path: sourcePath,
|
|
@@ -1981,6 +1986,15 @@ function makeAdapter(spec) {
|
|
|
1981
1986
|
agentsRoot: spec.agentsRoot,
|
|
1982
1987
|
commandsRoot: spec.commandsRoot,
|
|
1983
1988
|
supportsExecutableHooks: false,
|
|
1989
|
+
worktreeFor(changeId) {
|
|
1990
|
+
validateChangeId(changeId);
|
|
1991
|
+
return {
|
|
1992
|
+
root: spec.worktreeRoot,
|
|
1993
|
+
path: `${spec.worktreeRoot}/${changeId}`,
|
|
1994
|
+
branchPrefix: spec.branchPrefix,
|
|
1995
|
+
branch: `${spec.branchPrefix}${changeId}`
|
|
1996
|
+
};
|
|
1997
|
+
},
|
|
1984
1998
|
projectInstructionTargets() {
|
|
1985
1999
|
return ["AGENTS.md", ...spec.extraInstructionFiles];
|
|
1986
2000
|
},
|
|
@@ -2032,6 +2046,8 @@ var ADAPTERS = {
|
|
|
2032
2046
|
agentsRoot: ".claude/agents",
|
|
2033
2047
|
commandsRoot: null,
|
|
2034
2048
|
instructions: "CLAUDE.md",
|
|
2049
|
+
worktreeRoot: ".claude/worktrees",
|
|
2050
|
+
branchPrefix: "claude/",
|
|
2035
2051
|
extraInstructionFiles: ["CLAUDE.md"],
|
|
2036
2052
|
ruleExt: ".md"
|
|
2037
2053
|
}),
|
|
@@ -2042,6 +2058,8 @@ var ADAPTERS = {
|
|
|
2042
2058
|
agentsRoot: null,
|
|
2043
2059
|
commandsRoot: null,
|
|
2044
2060
|
instructions: "AGENTS.md",
|
|
2061
|
+
worktreeRoot: ".codex/worktrees",
|
|
2062
|
+
branchPrefix: "codex/",
|
|
2045
2063
|
extraInstructionFiles: [],
|
|
2046
2064
|
ruleExt: null
|
|
2047
2065
|
}),
|
|
@@ -2052,6 +2070,8 @@ var ADAPTERS = {
|
|
|
2052
2070
|
agentsRoot: null,
|
|
2053
2071
|
commandsRoot: ".cursor/commands",
|
|
2054
2072
|
instructions: "AGENTS.md",
|
|
2073
|
+
worktreeRoot: ".cursor/worktrees",
|
|
2074
|
+
branchPrefix: "cursor/",
|
|
2055
2075
|
extraInstructionFiles: [],
|
|
2056
2076
|
ruleExt: ".mdc"
|
|
2057
2077
|
}),
|
|
@@ -2062,6 +2082,8 @@ var ADAPTERS = {
|
|
|
2062
2082
|
agentsRoot: ".codebuddy/agents",
|
|
2063
2083
|
commandsRoot: ".codebuddy/commands",
|
|
2064
2084
|
instructions: "CODEBUDDY.md",
|
|
2085
|
+
worktreeRoot: ".codebuddy/worktrees",
|
|
2086
|
+
branchPrefix: "codebuddy/",
|
|
2065
2087
|
extraInstructionFiles: ["CODEBUDDY.md"],
|
|
2066
2088
|
ruleExt: null
|
|
2067
2089
|
})
|
|
@@ -3003,6 +3025,111 @@ async function refreshProject(options) {
|
|
|
3003
3025
|
conflicts: sortByTarget(conflicts)
|
|
3004
3026
|
};
|
|
3005
3027
|
}
|
|
3028
|
+
function freshnessEntry(agent, profile, status, identity) {
|
|
3029
|
+
return { agent, profile, status, identity, driftedFiles: [], missingFiles: [] };
|
|
3030
|
+
}
|
|
3031
|
+
var BUILD_MARKER_BUNDLE_PATH = ".harness-build.json";
|
|
3032
|
+
function buildMarkerCoreHash(text) {
|
|
3033
|
+
if (text === null || text === "")
|
|
3034
|
+
return null;
|
|
3035
|
+
try {
|
|
3036
|
+
const parsed = JSON.parse(text);
|
|
3037
|
+
return typeof parsed.coreHash === "string" && parsed.coreHash.length > 0 ? parsed.coreHash : null;
|
|
3038
|
+
} catch {
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
async function collectFreshness(options) {
|
|
3043
|
+
const root = resolve4(options.projectRoot);
|
|
3044
|
+
const installed = await readInstalledState(root);
|
|
3045
|
+
const codebuddySurface2 = options.codebuddySurface ?? "both";
|
|
3046
|
+
const agents = [];
|
|
3047
|
+
for (const agent of sortHarnessAgents(options.agents)) {
|
|
3048
|
+
const installedProfile = installed.profiles.get(agent) ?? installed.profile;
|
|
3049
|
+
const requestedProfile = options.profile ?? installedProfile ?? "general";
|
|
3050
|
+
const installedManifest = installed.manifests.find((entry) => entry.adapter === agent);
|
|
3051
|
+
const identity = {
|
|
3052
|
+
adapter: agent,
|
|
3053
|
+
bundleVersion: null,
|
|
3054
|
+
installedBundleVersion: installedManifest?.bundle_version ?? null,
|
|
3055
|
+
manifestHash: null,
|
|
3056
|
+
installedManifestHash: installedManifest?.bundle_manifest_hash ?? null,
|
|
3057
|
+
coreHash: null,
|
|
3058
|
+
installedCoreHash: null,
|
|
3059
|
+
adapterHash: null,
|
|
3060
|
+
installedAdapterHash: null
|
|
3061
|
+
};
|
|
3062
|
+
let officialHash = null;
|
|
3063
|
+
let officialVersion = null;
|
|
3064
|
+
let bundle;
|
|
3065
|
+
try {
|
|
3066
|
+
bundle = await loadAgentBundle(options.resourcesRoot, requestedProfile, agent);
|
|
3067
|
+
officialHash = sha256Bytes(canonicalJson(bundle.manifest.files));
|
|
3068
|
+
officialVersion = bundle.manifest.bundle_version;
|
|
3069
|
+
identity.bundleVersion = officialVersion;
|
|
3070
|
+
identity.manifestHash = officialHash;
|
|
3071
|
+
const markerBytes = bundle.files.get(BUILD_MARKER_BUNDLE_PATH);
|
|
3072
|
+
identity.coreHash = markerBytes === void 0 ? null : buildMarkerCoreHash(new TextDecoder().decode(markerBytes));
|
|
3073
|
+
} catch {
|
|
3074
|
+
bundle = null;
|
|
3075
|
+
}
|
|
3076
|
+
if (installed.schemaVersion === null || !installed.adapters.includes(agent) || installedProfile === null || installedProfile === void 0 || installedManifest === void 0 || bundle === null) {
|
|
3077
|
+
agents.push(freshnessEntry(agent, installedProfile ?? null, "UNVERIFIABLE", identity));
|
|
3078
|
+
continue;
|
|
3079
|
+
}
|
|
3080
|
+
const targets = managedTargetsFor(getAdapter(agent), bundle, {
|
|
3081
|
+
profile: installedProfile,
|
|
3082
|
+
codebuddySurface: codebuddySurface2
|
|
3083
|
+
});
|
|
3084
|
+
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
|
+
const installedProjection = await Promise.all(targets.map(async (target) => ({
|
|
3086
|
+
path: target.target_path.replace(/\\/g, "/"),
|
|
3087
|
+
sha256: await fileHex(join6(root, target.target_path))
|
|
3088
|
+
})));
|
|
3089
|
+
identity.installedAdapterHash = sha256Bytes(canonicalJson(installedProjection.sort((a, b) => a.path.localeCompare(b.path))));
|
|
3090
|
+
const markerTarget = targets.find((target) => target.target_path.replace(/\\/g, "/").endsWith(`/${BUILD_MARKER_BUNDLE_PATH}`) || target.target_path === BUILD_MARKER_BUNDLE_PATH);
|
|
3091
|
+
if (markerTarget !== void 0) {
|
|
3092
|
+
identity.installedCoreHash = buildMarkerCoreHash(await readOptionalText(join6(root, markerTarget.target_path)));
|
|
3093
|
+
}
|
|
3094
|
+
if (requestedProfile !== installedProfile) {
|
|
3095
|
+
agents.push(freshnessEntry(agent, installedProfile, "PROFILE_MISMATCH", identity));
|
|
3096
|
+
continue;
|
|
3097
|
+
}
|
|
3098
|
+
if (installedManifest.bundle_manifest_hash !== officialHash || installedManifest.bundle_version !== officialVersion) {
|
|
3099
|
+
agents.push(freshnessEntry(agent, installedProfile, "VERSION_BEHIND", identity));
|
|
3100
|
+
continue;
|
|
3101
|
+
}
|
|
3102
|
+
const drifted = [];
|
|
3103
|
+
const missing = [];
|
|
3104
|
+
for (const target of targets) {
|
|
3105
|
+
const current = await fileHex(join6(root, target.target_path));
|
|
3106
|
+
if (current === null) {
|
|
3107
|
+
missing.push(target.target_path);
|
|
3108
|
+
} else if (current !== target.sha256) {
|
|
3109
|
+
drifted.push(target.target_path);
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
if (missing.length > 0) {
|
|
3113
|
+
const entry = freshnessEntry(agent, installedProfile, "MISSING", identity);
|
|
3114
|
+
entry.missingFiles = missing.sort();
|
|
3115
|
+
entry.driftedFiles = drifted.sort();
|
|
3116
|
+
agents.push(entry);
|
|
3117
|
+
continue;
|
|
3118
|
+
}
|
|
3119
|
+
if (drifted.length > 0) {
|
|
3120
|
+
const entry = freshnessEntry(agent, installedProfile, "LOCALLY_MODIFIED", identity);
|
|
3121
|
+
entry.driftedFiles = drifted.sort();
|
|
3122
|
+
agents.push(entry);
|
|
3123
|
+
continue;
|
|
3124
|
+
}
|
|
3125
|
+
agents.push(freshnessEntry(agent, installedProfile, "CURRENT", identity));
|
|
3126
|
+
}
|
|
3127
|
+
return {
|
|
3128
|
+
schema_version: 1,
|
|
3129
|
+
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3130
|
+
agents
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3006
3133
|
|
|
3007
3134
|
// ../core/dist/proposal/diff.js
|
|
3008
3135
|
function operationPath(operation) {
|
|
@@ -5554,6 +5681,14 @@ async function runRefresh(options, dependencies) {
|
|
|
5554
5681
|
forceManaged: options.forceManaged === true
|
|
5555
5682
|
});
|
|
5556
5683
|
const output = summarize(result);
|
|
5684
|
+
const freshness = await collectFreshness({
|
|
5685
|
+
projectRoot: dependencies.cwd,
|
|
5686
|
+
resourcesRoot: dependencies.resourcesRoot,
|
|
5687
|
+
...targetProfile === void 0 ? {} : { profile: targetProfile },
|
|
5688
|
+
agents: targetAgents,
|
|
5689
|
+
codebuddySurface: codebuddySurface(detection.config, options.codebuddySurface)
|
|
5690
|
+
});
|
|
5691
|
+
output.freshness = freshness.agents;
|
|
5557
5692
|
if (options.json === true) {
|
|
5558
5693
|
dependencies.stdout(serializeCliResult({ ...output, request_id: requestId }));
|
|
5559
5694
|
} else {
|