@lannguyensi/harness 0.48.0 → 0.50.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/CHANGELOG.md +825 -0
- package/dist/cli/add/index.js +15 -3
- package/dist/cli/add/index.js.map +1 -1
- package/dist/cli/apply/apply.js +19 -3
- package/dist/cli/apply/apply.js.map +1 -1
- package/dist/cli/approve/risk.d.ts +28 -2
- package/dist/cli/approve/risk.js +14 -4
- package/dist/cli/approve/risk.js.map +1 -1
- package/dist/cli/diff/index.js +22 -1
- package/dist/cli/diff/index.js.map +1 -1
- package/dist/cli/doctor/format.js +29 -2
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/index.js +62 -3
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/types.d.ts +57 -0
- package/dist/cli/explain-policy.d.ts +4 -1
- package/dist/cli/explain-policy.js +12 -2
- package/dist/cli/explain-policy.js.map +1 -1
- package/dist/cli/export.js +12 -1
- package/dist/cli/export.js.map +1 -1
- package/dist/cli/index.js +29 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/templates.d.ts +34 -1
- package/dist/cli/init/templates.js +137 -3
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/list.js +6 -0
- package/dist/cli/list.js.map +1 -1
- package/dist/cli/loader.js +15 -0
- package/dist/cli/loader.js.map +1 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.js +11 -6
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-post-tool-use.d.ts +6 -4
- package/dist/cli/pack/hook-post-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +23 -22
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/policy/intercept.js +59 -9
- package/dist/cli/policy/intercept.js.map +1 -1
- package/dist/cli/remove/index.d.ts +12 -0
- package/dist/cli/remove/index.js +89 -0
- package/dist/cli/remove/index.js.map +1 -1
- package/dist/cli/validate/checks.d.ts +49 -0
- package/dist/cli/validate/checks.js +416 -9
- package/dist/cli/validate/checks.js.map +1 -1
- package/dist/cli/validate/index.js +11 -0
- package/dist/cli/validate/index.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/index.d.ts +2 -2
- package/dist/policy-packs/builtin/understanding-before-execution/index.js +33 -27
- package/dist/policy-packs/builtin/understanding-before-execution/index.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/markers.js +2 -2
- package/dist/policy-packs/builtin/understanding-before-execution/markers.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.d.ts +46 -8
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js +71 -12
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js +6 -3
- package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js.map +1 -1
- package/dist/policy-packs/builtin/understanding-before-execution.js +9 -8
- package/dist/policy-packs/builtin/understanding-before-execution.js.map +1 -1
- package/dist/runtime/bash-prefix-parse.d.ts +12 -1
- package/dist/runtime/bash-prefix-parse.js +2 -2
- package/dist/runtime/bash-prefix-parse.js.map +1 -1
- package/dist/runtime/command-normalize.d.ts +112 -0
- package/dist/runtime/command-normalize.js +169 -55
- package/dist/runtime/command-normalize.js.map +1 -1
- package/dist/runtime/deletion-target-resolve.d.ts +28 -0
- package/dist/runtime/deletion-target-resolve.js +1055 -0
- package/dist/runtime/deletion-target-resolve.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/intercept.js +17 -1
- package/dist/runtime/intercept.js.map +1 -1
- package/dist/runtime/kubectl-target-parse.d.ts +31 -0
- package/dist/runtime/kubectl-target-parse.js +249 -0
- package/dist/runtime/kubectl-target-parse.js.map +1 -0
- package/dist/runtime/read-only-bash.d.ts +11 -0
- package/dist/runtime/read-only-bash.js +288 -7
- package/dist/runtime/read-only-bash.js.map +1 -1
- package/dist/runtime/risk-classifier.js +14 -1
- package/dist/runtime/risk-classifier.js.map +1 -1
- package/dist/runtime/when-eval.d.ts +11 -2
- package/dist/runtime/when-eval.js +25 -0
- package/dist/runtime/when-eval.js.map +1 -1
- package/dist/runtime/workflow-policies.d.ts +164 -0
- package/dist/runtime/workflow-policies.js +439 -0
- package/dist/runtime/workflow-policies.js.map +1 -0
- package/dist/schema/index.d.ts +24 -0
- package/dist/schema/policies.d.ts +25 -0
- package/dist/schema/policies.js +29 -0
- package/dist/schema/policies.js.map +1 -1
- package/dist/schema/risk.d.ts +6 -0
- package/dist/schema/risk.js +80 -0
- package/dist/schema/risk.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/remove/index.js
CHANGED
|
@@ -6,6 +6,8 @@ import { resolveHomeDir } from "../../runtime/home-dir.js";
|
|
|
6
6
|
import { withFileLock } from "../../io/lock.js";
|
|
7
7
|
import { unifiedDiff } from "../../io/patch.js";
|
|
8
8
|
import { formatValidationErrors, validateBeforeWrite, } from "../../io/validate-before-write.js";
|
|
9
|
+
import { ManifestParseError, parseManifest } from "../../schema/index.js";
|
|
10
|
+
import { deriveWorkflowGatePolicies, REVIEW_EVIDENCE_HOOK_BASH, REVIEW_EVIDENCE_HOOK_MCP, } from "../../runtime/workflow-policies.js";
|
|
9
11
|
import { EX_FAIL, EX_NOINPUT, HarnessExitError } from "../exit-codes.js";
|
|
10
12
|
import { applyRemove, planRemove } from "./mutate.js";
|
|
11
13
|
const DEFAULT_BASENAME = "harness.yaml";
|
|
@@ -20,6 +22,66 @@ function formatNameList(names) {
|
|
|
20
22
|
return "(none declared)";
|
|
21
23
|
return names.map((n) => ` - ${n}`).join("\n");
|
|
22
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* F8 (review round 2, 99f47307 Slice 1): `planRemove`'s
|
|
27
|
+
* `referencingPolicies` only ever sees HAND-authored `policies:` entries
|
|
28
|
+
* (it walks the raw YAML document). A `require-review-evidence[-bash]`
|
|
29
|
+
* hook referenced ONLY by a `workflows[]`-derived merge gate (no
|
|
30
|
+
* hand-authored policy names it) passed that check silently — `harness
|
|
31
|
+
* remove hook require-review-evidence` would delete the hook and the
|
|
32
|
+
* next `harness apply`/`policy intercept` would derive nothing for it
|
|
33
|
+
* (hasWiredMergeGateHooks requires BOTH hooks), a silent regression from
|
|
34
|
+
* "enforced" to "not enforced" for every workflow with `spawn:
|
|
35
|
+
* "required"`. This consults the SAME derivation `withDerivedPolicies`
|
|
36
|
+
* uses (`deriveWorkflowGatePolicies`) against the manifest as it stands
|
|
37
|
+
* BEFORE the removal, and returns the names of workflows whose derived
|
|
38
|
+
* gate references `hookName` — empty for any type/name that isn't one of
|
|
39
|
+
* the two evidence hooks, or when the manifest fails to parse (the
|
|
40
|
+
* existing schema-gate checks further down handle a malformed manifest;
|
|
41
|
+
* this is a best-effort pre-check, not the safety net).
|
|
42
|
+
*/
|
|
43
|
+
function derivedGateReferencingWorkflows(yamlText, type, hookName) {
|
|
44
|
+
if (type !== "hook")
|
|
45
|
+
return [];
|
|
46
|
+
if (hookName !== REVIEW_EVIDENCE_HOOK_MCP && hookName !== REVIEW_EVIDENCE_HOOK_BASH)
|
|
47
|
+
return [];
|
|
48
|
+
let manifest;
|
|
49
|
+
try {
|
|
50
|
+
manifest = parseManifest(parseYaml(yamlText));
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof ManifestParseError)
|
|
54
|
+
return [];
|
|
55
|
+
throw err;
|
|
56
|
+
}
|
|
57
|
+
// Non-empty only when BOTH evidence hooks are currently wired (see
|
|
58
|
+
// `hasWiredMergeGateHooks`) — if only one is present already, no
|
|
59
|
+
// workflow has an enforced gate to lose from removing the other.
|
|
60
|
+
const derivedPolicies = deriveWorkflowGatePolicies(manifest);
|
|
61
|
+
if (derivedPolicies.length === 0)
|
|
62
|
+
return [];
|
|
63
|
+
// F5 (review round 3 follow-up, 99f47307 Slice 1): this used to return
|
|
64
|
+
// every workflow matching `workflowRequiresMergeGate` (the SHAPE test),
|
|
65
|
+
// not the workflows the derivation actually produced a policy for (the
|
|
66
|
+
// dedupe an equivalent hand-authored policy already covers on the same
|
|
67
|
+
// surface derives NOTHING for; see `deriveWorkflowGates`'s `seen` set).
|
|
68
|
+
// A manifest with two qualifying workflows where only one is actually
|
|
69
|
+
// derived would name both here even though only one's gate is really
|
|
70
|
+
// lost. Project the workflow name back out of each derived policy's
|
|
71
|
+
// name instead (`workflow:<name>:review-before-merge[-bash]`), filtered
|
|
72
|
+
// to the hook being removed so a `require-review-evidence`-only removal
|
|
73
|
+
// does not also name workflows whose gate only depends on the bash hook.
|
|
74
|
+
const affected = new Set();
|
|
75
|
+
for (const policy of derivedPolicies) {
|
|
76
|
+
if (policy.hook !== hookName)
|
|
77
|
+
continue;
|
|
78
|
+
const match = /^workflow:(.+):review-before-merge(?:-bash)?$/.exec(policy.name);
|
|
79
|
+
const workflowName = match?.[1];
|
|
80
|
+
if (workflowName !== undefined)
|
|
81
|
+
affected.add(workflowName);
|
|
82
|
+
}
|
|
83
|
+
return manifest.workflows.filter((wf) => affected.has(wf.name)).map((wf) => wf.name);
|
|
84
|
+
}
|
|
23
85
|
export async function remove(type, name, opts = {}) {
|
|
24
86
|
const target = resolveTargetPath(opts);
|
|
25
87
|
if (!fs.existsSync(target)) {
|
|
@@ -35,6 +97,23 @@ export async function remove(type, name, opts = {}) {
|
|
|
35
97
|
const verb = plan.referencingPolicies.length === 1 ? "policy" : "policies";
|
|
36
98
|
throw new HarnessExitError(`${verb} ${refList} reference${plan.referencingPolicies.length === 1 ? "s" : ""} this hook; remove the ${verb} first or pass --force`, EX_FAIL);
|
|
37
99
|
}
|
|
100
|
+
// F8 (review round 2, 99f47307 Slice 1): the check above only sees
|
|
101
|
+
// hand-authored `policies:` entries; a hook referenced ONLY by a
|
|
102
|
+
// workflows[]-derived merge gate must get the same protection, or
|
|
103
|
+
// `harness remove hook require-review-evidence` silently disables the
|
|
104
|
+
// gate for every workflow with `spawn: "required"` (no dangling
|
|
105
|
+
// schema reference to catch it afterwards — see
|
|
106
|
+
// `derivedGateReferencingWorkflows`'s header for why there is no
|
|
107
|
+
// schema-level safety net here the way there is for hand policies).
|
|
108
|
+
const derivedGateWorkflows = derivedGateReferencingWorkflows(original, type, name);
|
|
109
|
+
if (derivedGateWorkflows.length > 0 && !opts.force) {
|
|
110
|
+
const wfList = derivedGateWorkflows.map((n) => `"${n}"`).join(", ");
|
|
111
|
+
const verb = derivedGateWorkflows.length === 1 ? "workflow" : "workflows";
|
|
112
|
+
throw new HarnessExitError(`${verb} ${wfList} derive${derivedGateWorkflows.length === 1 ? "s" : ""} a runtime merge gate ` +
|
|
113
|
+
`from this hook (a review_subagent step with spawn: "required" followed by a merge step); ` +
|
|
114
|
+
`removing it would silently disable that gate. Drop spawn: "required" on the workflow step ` +
|
|
115
|
+
"first, or pass --force.", EX_FAIL);
|
|
116
|
+
}
|
|
38
117
|
const proposed = applyRemove(original, type, name);
|
|
39
118
|
const diff = unifiedDiff({
|
|
40
119
|
fileName: path.basename(target),
|
|
@@ -52,6 +131,14 @@ export async function remove(type, name, opts = {}) {
|
|
|
52
131
|
if (!schemaResult.ok) {
|
|
53
132
|
throw new HarnessExitError(`proposed manifest fails schema validation:\n${formatValidationErrors(schemaResult.errors)}`, EX_FAIL);
|
|
54
133
|
}
|
|
134
|
+
// derivedGateWorkflows is non-empty here only under --force (the
|
|
135
|
+
// pre-check above threw otherwise), on BOTH paths: unlike a dangling
|
|
136
|
+
// policy.hook reference, nothing downstream refuses a --force'd
|
|
137
|
+
// derived-gate removal (see `derivedGateReferencingWorkflows`), so the
|
|
138
|
+
// write path must report it too, not only the dry-run (F3, review
|
|
139
|
+
// round 3; the round-2 code hard-coded `[]` on the write path and the
|
|
140
|
+
// CLI never printed either).
|
|
141
|
+
const derivedGateReferences = derivedGateWorkflows;
|
|
55
142
|
if (opts.dryRun) {
|
|
56
143
|
// forcedReferences is informational on dry-run: it shows the user which
|
|
57
144
|
// policies would have been overridden if the schema gate did not refuse.
|
|
@@ -64,6 +151,7 @@ export async function remove(type, name, opts = {}) {
|
|
|
64
151
|
diff,
|
|
65
152
|
applied: false,
|
|
66
153
|
forcedReferences: opts.force ? plan.referencingPolicies : [],
|
|
154
|
+
derivedGateReferences,
|
|
67
155
|
};
|
|
68
156
|
}
|
|
69
157
|
const lockPath = path.join(path.dirname(target), LOCK_BASENAME);
|
|
@@ -86,6 +174,7 @@ export async function remove(type, name, opts = {}) {
|
|
|
86
174
|
// hook, so the only way to reach here with --force is when there are no
|
|
87
175
|
// referencing policies to begin with.
|
|
88
176
|
forcedReferences: [],
|
|
177
|
+
derivedGateReferences,
|
|
89
178
|
};
|
|
90
179
|
}
|
|
91
180
|
export const KNOWN_REMOVE_TYPES = ["mcp", "cli", "skill", "hook"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/remove/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAmB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/remove/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,53 @@ declare function resolveOnPath(binary: string, pathEnv: string): string | null;
|
|
|
20
20
|
declare function compareVersions(actual: string, required: string): number;
|
|
21
21
|
export declare function checkPolicyGroundingMcp(manifest: Manifest): Diagnostic[];
|
|
22
22
|
export declare function checkSolutionAcceptanceProducer(manifest: Manifest): Diagnostic[];
|
|
23
|
+
export declare function checkWorkflowGateWiring(manifest: Manifest): Diagnostic[];
|
|
24
|
+
/**
|
|
25
|
+
* F1 (review round 2): a hand-authored policy on the identical trigger
|
|
26
|
+
* surface + ledger_tag as a derived block gate, but weaker than it
|
|
27
|
+
* (`enforcement: "warn"`/`"require_approval"`, or `when:`-scoped), no
|
|
28
|
+
* longer suppresses the derived gate (see `isAtLeastAsStrongAsDerivedGate`
|
|
29
|
+
* in workflow-policies.ts) — both apply. This check surfaces that overlap
|
|
30
|
+
* as a warning so an operator reading the weaker policy does not mistake
|
|
31
|
+
* it for the ONLY gate on the surface.
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkWorkflowGateWeakOverlap(manifest: Manifest): Diagnostic[];
|
|
34
|
+
/**
|
|
35
|
+
* F6 (review round 2): a workflow that declares BOTH a `merge` step and a
|
|
36
|
+
* `review_subagent` step with `spawn: "required"`, but with the review
|
|
37
|
+
* step coming AFTER the merge step, derives no gate at all
|
|
38
|
+
* (`workflowRequiresMergeGate` only looks for review-then-merge). That
|
|
39
|
+
* ordering is likely a mistake (a review that runs after the PR already
|
|
40
|
+
* merged cannot gate it), but step-ordering validation in general is out
|
|
41
|
+
* of scope for this slice (module doc, src/runtime/workflow-policies.ts).
|
|
42
|
+
* This warns instead of silently doing nothing.
|
|
43
|
+
*/
|
|
44
|
+
export declare function checkWorkflowMergeBeforeReview(manifest: Manifest): Diagnostic[];
|
|
45
|
+
/**
|
|
46
|
+
* Review round 3 (99f47307 Slice 1): a hand-authored policy whose name
|
|
47
|
+
* equals a derived policy's name (`workflow:<name>:review-before-merge[-
|
|
48
|
+
* bash]`) is not deduped by name (dedupe keys on surface, not name), so
|
|
49
|
+
* the derived view carries two policies with one name. This fires both
|
|
50
|
+
* when the hand-authored policy sits on a DIFFERENT surface (dedupe never
|
|
51
|
+
* even compares them), and when it sits on the SAME surface but is not
|
|
52
|
+
* `isAtLeastAsStrongAsDerivedGate` (weaker enforcement or a `when:` scope
|
|
53
|
+
* — that case IS a surface match, so `findWeakGatePolicyOverlaps` also
|
|
54
|
+
* reports it as an overlap; the two checks are not mutually exclusive).
|
|
55
|
+
* Either way the runtime evaluates both policies (fail-safe), but every
|
|
56
|
+
* by-name reader (`explain`, `explain-policy`, `audit`, `diff`'s
|
|
57
|
+
* name-keyed policy list) resolves the name to the hand-authored one and
|
|
58
|
+
* silently hides the derived gate. The schema's duplicate-name refinement
|
|
59
|
+
* cannot see this (it runs on the hand-authored view), so it is an error
|
|
60
|
+
* here.
|
|
61
|
+
*/
|
|
62
|
+
export declare function checkWorkflowDerivedNameCollision(manifest: Manifest): Diagnostic[];
|
|
63
|
+
/**
|
|
64
|
+
* Every `workflows[]` check in one list, so `harness validate`
|
|
65
|
+
* (`runAssetChecks`) and `harness doctor`'s Workflows section run the
|
|
66
|
+
* SAME set (review round 3, 99f47307 Slice 1: doctor previously picked
|
|
67
|
+
* two of the three by hand and was missing `checkWorkflowMergeBeforeReview`).
|
|
68
|
+
*/
|
|
69
|
+
export declare function checkWorkflows(manifest: Manifest): Diagnostic[];
|
|
23
70
|
/**
|
|
24
71
|
* Answers "is `relPath` git-ignored here?": `true` / `false`, or `null`
|
|
25
72
|
* when the question has no answer (not a git repository, git not
|
|
@@ -37,7 +84,9 @@ export declare function createDefaultGitIgnoreProbe(cwd?: string): GitIgnoreProb
|
|
|
37
84
|
export declare function checkSolutionAcceptanceKnobIgnored(manifest: Manifest, probe: GitIgnoreProbe): Diagnostic[];
|
|
38
85
|
export declare function checkPolicySelfAttestation(manifest: Manifest): Diagnostic[];
|
|
39
86
|
export declare function checkPolicyRiskWithoutEnvScope(manifest: Manifest): Diagnostic[];
|
|
87
|
+
export declare function checkSafeDeletionRootsSyntax(manifest: Manifest): Diagnostic[];
|
|
40
88
|
export declare function checkTemplatePolicyDrift(manifest: Manifest): Diagnostic[];
|
|
89
|
+
export declare function checkTriggerBoundaryDrift(manifest: Manifest): Diagnostic[];
|
|
41
90
|
export declare function checkHookBudgetLedgerMargin(manifest: Manifest): Diagnostic[];
|
|
42
91
|
export declare function runAssetChecks(manifest: Manifest, opts?: CheckOptions): Diagnostic[];
|
|
43
92
|
export declare const __testables: {
|