harnery 0.11.0 → 0.12.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.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +2 -0
  4. package/dist/commands/browse.js +1 -3
  5. package/dist/commands/eml.d.ts.map +1 -1
  6. package/dist/commands/eml.js +11 -50
  7. package/dist/commands/policy.d.ts +6 -0
  8. package/dist/commands/policy.d.ts.map +1 -0
  9. package/dist/commands/policy.js +42 -0
  10. package/dist/commands/workflow.d.ts.map +1 -1
  11. package/dist/commands/workflow.js +18 -1
  12. package/dist/core/agents/coord-client.d.ts +7 -0
  13. package/dist/core/agents/coord-client.d.ts.map +1 -1
  14. package/dist/core/agents/coord-client.js +27 -1
  15. package/dist/core/policy/evaluate.d.ts +14 -0
  16. package/dist/core/policy/evaluate.d.ts.map +1 -0
  17. package/dist/core/policy/evaluate.js +238 -0
  18. package/dist/core/policy/file.d.ts +3 -0
  19. package/dist/core/policy/file.d.ts.map +1 -0
  20. package/dist/core/policy/file.js +20 -0
  21. package/dist/core/policy/index.d.ts +5 -0
  22. package/dist/core/policy/index.d.ts.map +1 -0
  23. package/dist/core/policy/index.js +3 -0
  24. package/dist/core/policy/types.d.ts +91 -0
  25. package/dist/core/policy/types.d.ts.map +1 -0
  26. package/dist/core/policy/types.js +1 -0
  27. package/dist/core/scratch/index.d.ts.map +1 -1
  28. package/dist/core/scratch/index.js +14 -4
  29. package/dist/core/workflow/engine.d.ts.map +1 -1
  30. package/dist/core/workflow/engine.js +261 -35
  31. package/dist/core/workflow/index.d.ts +1 -1
  32. package/dist/core/workflow/index.d.ts.map +1 -1
  33. package/dist/core/workflow/proof.d.ts +7 -0
  34. package/dist/core/workflow/proof.d.ts.map +1 -1
  35. package/dist/core/workflow/proof.js +33 -0
  36. package/dist/core/workflow/types.d.ts +33 -0
  37. package/dist/core/workflow/types.d.ts.map +1 -1
  38. package/dist/lib/browser/client.d.ts +1 -1
  39. package/dist/lib/browser/client.d.ts.map +1 -1
  40. package/dist/lib/browser/client.js +7 -1
  41. package/package.json +9 -4
  42. package/src/commander.ts +2 -0
  43. package/src/commands/browse.ts +1 -5
  44. package/src/commands/eml.ts +11 -62
  45. package/src/commands/policy.ts +50 -0
  46. package/src/commands/workflow.ts +29 -1
  47. package/src/core/agents/coord-client.ts +28 -1
  48. package/src/core/policy/evaluate.ts +311 -0
  49. package/src/core/policy/file.ts +20 -0
  50. package/src/core/policy/index.ts +26 -0
  51. package/src/core/policy/types.ts +107 -0
  52. package/src/core/scratch/index.ts +20 -4
  53. package/src/core/workflow/engine.ts +283 -41
  54. package/src/core/workflow/index.ts +1 -0
  55. package/src/core/workflow/proof.ts +51 -0
  56. package/src/core/workflow/types.ts +43 -0
  57. package/src/lib/browser/client.ts +6 -1
@@ -1,6 +1,7 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
+ import { policyDigest } from "../policy/index.js";
4
5
  import { WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.js";
5
6
  const MAX_ACCEPTANCE_CRITERIA = 50;
6
7
  const MAX_EVIDENCE_RECORDS = 200;
@@ -131,6 +132,7 @@ export function buildWorkflowProof(input) {
131
132
  acceptance,
132
133
  agents,
133
134
  evidence: input.evidence,
135
+ policy: input.policy ? buildPolicyProof(input.policy) : undefined,
134
136
  repository,
135
137
  harnesses,
136
138
  unknowns,
@@ -143,6 +145,33 @@ export function buildWorkflowProof(input) {
143
145
  },
144
146
  };
145
147
  }
148
+ function buildPolicyProof(input) {
149
+ const decisions = input.decisions.map((decision) => ({
150
+ ...decision,
151
+ reason: clipped(decision.reason, MAX_SUMMARY_CHARS),
152
+ request: {
153
+ ...decision.request,
154
+ action: clipped(decision.request.action, MAX_REF_CHARS),
155
+ path: clippedOptional(decision.request.path, MAX_REF_CHARS),
156
+ target: clippedOptional(decision.request.target, MAX_REF_CHARS),
157
+ },
158
+ }));
159
+ return {
160
+ schema_version: input.config.schema_version,
161
+ name: input.config.name,
162
+ sha256: policyDigest(input.config),
163
+ isolation: input.isolation,
164
+ network_access: input.networkAccess,
165
+ config: input.config,
166
+ decisions,
167
+ summary: {
168
+ allowed: decisions.filter((decision) => decision.verdict === "allow").length,
169
+ denied: decisions.filter((decision) => decision.verdict === "deny").length,
170
+ asked: decisions.filter((decision) => decision.initial_verdict === "ask").length,
171
+ total: decisions.length,
172
+ },
173
+ };
174
+ }
146
175
  export function writeWorkflowProof(path, proof) {
147
176
  const body = `${JSON.stringify(proof, null, 2)}\n`;
148
177
  const bytes = Buffer.byteLength(body);
@@ -198,6 +227,10 @@ export function renderWorkflowProof(proof) {
198
227
  lines.push(` ${mark} ${criterion.id}: ${criterion.statement}${refs}`);
199
228
  }
200
229
  lines.push(`evidence: ${proof.evidence.length} record(s); agents: ${proof.agents.length}`);
230
+ if (proof.policy) {
231
+ lines.push(`policy: ${proof.policy.name}; ${proof.policy.summary.allowed} allowed, ` +
232
+ `${proof.policy.summary.denied} denied, ${proof.policy.summary.asked} asked`);
233
+ }
201
234
  const repo = proof.repository;
202
235
  const drift = repo.drift;
203
236
  lines.push(`repository: branch ${repo.before.branch ?? "unknown"} -> ${repo.after.branch ?? "unknown"}; ` +
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * Design record: decision 0015 (portable coordination-aware workflows).
8
8
  */
9
+ import type { DispatchCostEstimator, ExternalMutationRequest, NormalizedPolicy, PolicyAskResolver, PolicyDecision, PolicyIsolation, PolicyNetworkAccess, PolicySpec } from "../policy/index.js";
9
10
  import type { BillingMode, BillingProber } from "./billing.js";
10
11
  export declare const WORKFLOW_PROOF_SCHEMA_VERSION: 1;
11
12
  export type EvidenceKind = "test" | "command" | "artifact" | "change" | "review" | "observation";
@@ -131,6 +132,7 @@ export interface WorkflowProof {
131
132
  };
132
133
  agents: WorkflowAgentProof[];
133
134
  evidence: WorkflowEvidenceRecord[];
135
+ policy?: WorkflowPolicyProof;
134
136
  repository: WorkflowRepoEvidence;
135
137
  harnesses: HarnessEvidenceCoverage[];
136
138
  unknowns: WorkflowProofUnknown[];
@@ -142,6 +144,21 @@ export interface WorkflowProof {
142
144
  };
143
145
  };
144
146
  }
147
+ export interface WorkflowPolicyProof {
148
+ schema_version: 1;
149
+ name: string;
150
+ sha256: string;
151
+ isolation: PolicyIsolation;
152
+ network_access: PolicyNetworkAccess;
153
+ config: NormalizedPolicy;
154
+ decisions: PolicyDecision[];
155
+ summary: {
156
+ allowed: number;
157
+ denied: number;
158
+ asked: number;
159
+ total: number;
160
+ };
161
+ }
145
162
  export interface HarnessEvidenceCapability {
146
163
  toolEvidence: HarnessEvidenceCoverage["tool_evidence"];
147
164
  }
@@ -226,6 +243,8 @@ export interface WorkflowContext {
226
243
  log: (message: string) => void;
227
244
  /** Attach a bounded, sourced receipt to the run and optional acceptance criteria. */
228
245
  evidence: (input: WorkflowEvidenceInput) => string;
246
+ /** Authorize one host-mediated external mutation before performing it. */
247
+ authorize: (input: ExternalMutationRequest) => Promise<PolicyDecision>;
229
248
  }
230
249
  export interface WorkflowMeta {
231
250
  name: string;
@@ -272,6 +291,18 @@ export interface EngineOpts {
272
291
  /** Capability claims used to state whether adapter-native tool evidence was
273
292
  * available. Missing claims remain unknown. */
274
293
  harnessEvidence?: Readonly<Record<HarnessName, HarnessEvidenceCapability | undefined>>;
294
+ /** Immutable host policy. Workflow scripts and model prompts cannot replace it. */
295
+ policy?: PolicySpec | NormalizedPolicy;
296
+ /** Host callback for ASK. Missing, invalid, throwing, or timed-out resolution denies. */
297
+ resolvePolicyAsk?: PolicyAskResolver;
298
+ /** Host-owned cost projection. Required to allow budgeted dispatches with known pricing. */
299
+ estimateDispatchCost?: DispatchCostEstimator;
300
+ /** Maximum wait for an ASK resolver (default 60 seconds). */
301
+ policyAskTimeoutMs?: number;
302
+ /** Execution boundary created by the host (default shared). */
303
+ isolation?: PolicyIsolation;
304
+ /** Network state of spawned harness subprocesses (default unknown). */
305
+ networkAccess?: PolicyNetworkAccess;
275
306
  }
276
307
  export interface RunReport {
277
308
  runId: string;
@@ -295,5 +326,7 @@ export interface RunReport {
295
326
  harness: HarnessName;
296
327
  mode: BillingMode;
297
328
  }>;
329
+ /** Policy verdict totals when the host supplied a policy. */
330
+ policy?: WorkflowPolicyProof["summary"];
298
331
  }
299
332
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE/D,eAAO,MAAM,6BAA6B,EAAG,CAAU,CAAC;AAExD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;AACjG,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAC1E,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,QAAQ,CAAC;AACnD,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;AACvE,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,QAAQ,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC3D,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0EAA0E;IAC1E,OAAO,EAAE,cAAc,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,KAAK,EAAE,oBAAoB,CAAC;IAC5B,KAAK,EAAE;QACL,cAAc,EAAE,OAAO,CAAC;QACxB,YAAY,EAAE,OAAO,CAAC;QACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;QAC5B,mBAAmB,EAAE,MAAM,EAAE,CAAC;QAC9B,oBAAoB,EAAE,MAAM,EAAE,CAAC;QAC/B,kFAAkF;QAClF,UAAU,EAAE,OAAO,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,WAAW,CAAC;IACrB,aAAa,EAAE;QACb,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,SAAS,CAAC;QAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EACA,2BAA2B,GAC3B,iCAAiC,GACjC,uBAAuB,GACvB,0BAA0B,GAC1B,6BAA6B,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,OAAO,6BAA6B,CAAC;IACrD,GAAG,EAAE;QACH,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,iBAAiB,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,YAAY,CAAC;KACvB,CAAC;IACF,UAAU,EAAE;QACV,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,OAAO,EAAE,iBAAiB,CAAC;KAC5B,CAAC;IACF,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAC7B,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IACnC,UAAU,EAAE,oBAAoB,CAAC;IACjC,SAAS,EAAE,uBAAuB,EAAE,CAAC;IACrC,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,SAAS,EAAE;QACT,OAAO,EAAE;YACP,IAAI,EAAE,eAAe,CAAC;YACtB,MAAM,EAAE,MAAM,CAAC;YACf,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,uBAAuB,CAAC,eAAe,CAAC,CAAC;CACxD;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3D,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,qDAAqD;IACrD,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,SAAS;IACxB;;8EAE0E;IAC1E,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,iFAAiF;IACjF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;uDACmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;sDACkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;kBAEc;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;kCAEkC;AAClC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;8DAC0D;IAC1D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;8EAC8E;AAC9E,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAElE;+EAC+E;AAC/E,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,8EAA8E;IAC9E,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IAC3E,+DAA+D;IAC/D,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,2CAA2C;IAC3C,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,qFAAqF;IACrF,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,MAAM,CAAC;CACpD;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;CACpC;AAED,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,UAAU;IACzB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB;iDAC6C;IAC7C,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC;IAC7D,kFAAkF;IAClF,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B;;6EAEyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B;;+BAE2B;IAC3B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;iCAG6B;IAC7B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,yEAAyE;IACzE,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B;mDAC+C;IAC/C,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,yBAAyB,GAAG,SAAS,CAAC,CAAC,CAAC;CACxF;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,iBAAiB,CAAC;IAC9B;;gFAE4E;IAC5E,6BAA6B,EAAE,MAAM,CAAC;IACtC,6EAA6E;IAC7E,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;CAC7D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/types.ts"],"names":[],"mappings":"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"}
@@ -137,7 +137,7 @@ export declare class Browser {
137
137
  * on screen" signal for LLM iteration loops. For richer extraction, use
138
138
  * `htmlContent()` and pipe through a readability filter.
139
139
  */
140
- textSnapshot(): Promise<string>;
140
+ textSnapshot(selector?: string): Promise<string>;
141
141
  /** Raw outer HTML of the page (or a selector if provided). */
142
142
  htmlContent(selector?: string): Promise<string>;
143
143
  click(selector: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/client.ts"],"names":[],"mappings":"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"}
@@ -157,8 +157,14 @@ export class Browser {
157
157
  * on screen" signal for LLM iteration loops. For richer extraction, use
158
158
  * `htmlContent()` and pipe through a readability filter.
159
159
  */
160
- async textSnapshot() {
160
+ async textSnapshot(selector) {
161
161
  const page = this.currentPage;
162
+ if (selector) {
163
+ const el = await page.$(selector);
164
+ if (!el)
165
+ throw new Error(`Selector matched nothing: ${selector}`);
166
+ return await el.evaluate((node) => node.innerText ?? "");
167
+ }
162
168
  return await page.evaluate(() => document.body?.innerText ?? "");
163
169
  }
164
170
  /** Raw outer HTML of the page (or a selector if provided). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harnery",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "description": "Multi-agent coordination for AI coding agents - Claude Code, Cursor, and Codex.",
5
5
  "license": "MIT",
6
6
  "author": "Ryan Kelly",
@@ -67,6 +67,11 @@
67
67
  "types": "./dist/core/workflow/index.d.ts",
68
68
  "import": "./dist/core/workflow/index.js"
69
69
  },
70
+ "./core/policy": {
71
+ "bun": "./src/core/policy/index.ts",
72
+ "types": "./dist/core/policy/index.d.ts",
73
+ "import": "./dist/core/policy/index.js"
74
+ },
70
75
  "./lib/agent-browser": {
71
76
  "bun": "./src/lib/agent-browser/index.ts",
72
77
  "types": "./dist/lib/agent-browser/index.d.ts",
@@ -152,15 +157,15 @@
152
157
  "test:web": "cd web && bun install && bun test",
153
158
  "test:integration": "bash tests/integration/run.sh",
154
159
  "smoke": "node scripts/smoke-test.mjs",
155
- "docs:dev": "bun run --bun --cwd docs dev",
156
- "docs:build": "bun run --bun --cwd docs build",
160
+ "docs:dev": "bun run --cwd docs dev",
161
+ "docs:build": "bun run --cwd docs build",
157
162
  "brand:showcase": "node scripts/build-brand-showcase.mjs"
158
163
  },
159
164
  "dependencies": {
160
165
  "@mozilla/readability": "^0.6.0",
161
166
  "commander": "^14.0.3",
162
167
  "gpt-tokenizer": "^3.4.0",
163
- "js-yaml": "^4.1.1",
168
+ "js-yaml": "^4.3.0",
164
169
  "linkedom": "^0.18.0",
165
170
  "mailparser": "^3.9.14",
166
171
  "pixelmatch": "^7.2.0",
package/src/commander.ts CHANGED
@@ -42,6 +42,7 @@ import { registerGrepCommand } from "./commands/grep.ts";
42
42
  import { registerHarnessCommand } from "./commands/harness.ts";
43
43
  import { registerInitCommand } from "./commands/init.ts";
44
44
  import { registerOutlineCommand } from "./commands/outline.ts";
45
+ import { registerPolicyCommand } from "./commands/policy.ts";
45
46
  import { registerPresenceCommand } from "./commands/presence.ts";
46
47
  import { registerReadCommand } from "./commands/read.ts";
47
48
  import { registerRelayCommand } from "./commands/relay.ts";
@@ -264,6 +265,7 @@ export function createHarneryProgram(opts: HarneryContextOpts = {}): Command {
264
265
  registerEditBatchCommand(program, emit);
265
266
  registerGrepCommand(program, emit, opts.context);
266
267
  registerHarnessCommand(program, emit);
268
+ registerPolicyCommand(program, emit);
267
269
  registerCookiesCommand(program, emit);
268
270
  registerFetchCommand(program, emit, opts.context);
269
271
  registerReadCommand(program, emit);
@@ -650,11 +650,7 @@ async function runPrintMode(
650
650
  if (opts.html) {
651
651
  body = await browser.htmlContent(opts.selector);
652
652
  } else if (opts.snapshot) {
653
- body = opts.selector
654
- ? await browser.evaluate<string>(
655
- `(() => { const el = document.querySelector(${JSON.stringify(opts.selector)}); return el ? el.innerText : ''; })()`,
656
- )
657
- : await browser.textSnapshot();
653
+ body = await browser.textSnapshot(opts.selector);
658
654
  }
659
655
 
660
656
  if (opts.json) {
@@ -1,5 +1,6 @@
1
1
  import { readFileSync, writeFileSync } from "node:fs";
2
2
  import type { Command } from "commander";
3
+ import { parseHTML } from "linkedom";
3
4
  import { type ParsedMail, simpleParser } from "mailparser";
4
5
  import type { EmitContext } from "../commander.ts";
5
6
 
@@ -322,12 +323,12 @@ function parseAttribution(text: string): { name: string; date: Date | null } {
322
323
  const nameMatch = cleaned.match(/(?:AM|PM)\s+(.+?)(?:\s*<[^>]+>)?\s+wrote:/i);
323
324
  let name = "Unknown";
324
325
  if (nameMatch) {
325
- name = nameMatch[1].replace(/<[^>]+>/g, "").trim();
326
+ name = nameMatch[1].trim();
326
327
  } else {
327
328
  // Try simpler pattern without AM/PM
328
329
  const simpleMatch = cleaned.match(/at\s+[\d:]+\s+(.+?)(?:\s*<[^>]+>)?\s+wrote:/i);
329
330
  if (simpleMatch) {
330
- name = simpleMatch[1].replace(/<[^>]+>/g, "").trim();
331
+ name = simpleMatch[1].trim();
331
332
  }
332
333
  }
333
334
 
@@ -338,23 +339,11 @@ function parseAttribution(text: string): { name: string; date: Date | null } {
338
339
  * Strip HTML tags, decode entities, and normalize whitespace.
339
340
  */
340
341
  function stripHtml(html: string): string {
341
- let text = html;
342
-
343
- // Replace <br>, <br/>, <br /> with newlines
344
- text = text.replace(/<br\s*\/?>/gi, "\n");
345
-
346
- // Replace block-level elements with newlines
347
- text = text.replace(/<\/(p|div|tr|li|h[1-6])>/gi, "\n");
348
- text = text.replace(/<(p|div|tr|li|h[1-6])\b[^>]*>/gi, "\n");
349
-
350
- // Replace <td> with tab
351
- text = text.replace(/<\/td>/gi, "\t");
352
-
353
- // Remove all remaining HTML tags
354
- text = text.replace(/<[^>]+>/g, "");
355
-
356
- // Decode HTML entities
357
- text = decodeEntities(text);
342
+ const { document } = parseHTML(`<html><body>${html}</body></html>`);
343
+ for (const unsafe of document.querySelectorAll("script, style, template, noscript")) {
344
+ unsafe.remove();
345
+ }
346
+ let text = document.body?.innerText ?? "";
358
347
 
359
348
  // Normalize whitespace (but preserve newlines)
360
349
  text = text
@@ -365,44 +354,6 @@ function stripHtml(html: string): string {
365
354
  return text;
366
355
  }
367
356
 
368
- /**
369
- * Decode common HTML entities.
370
- */
371
- function decodeEntities(text: string): string {
372
- const entities: Record<string, string> = {
373
- "&amp;": "&",
374
- "&lt;": "<",
375
- "&gt;": ">",
376
- "&quot;": '"',
377
- "&#39;": "'",
378
- "&apos;": "'",
379
- "&nbsp;": " ",
380
- "&#160;": " ",
381
- "&ndash;": "-",
382
- "&mdash;": "-",
383
- "&laquo;": "<<",
384
- "&raquo;": ">>",
385
- "&bull;": "*",
386
- "&hellip;": "...",
387
- "&copy;": "(c)",
388
- "&reg;": "(R)",
389
- "&trade;": "(TM)",
390
- };
391
-
392
- let result = text;
393
- for (const [entity, char] of Object.entries(entities)) {
394
- result = result.replaceAll(entity, char);
395
- }
396
-
397
- // Decode numeric entities (&#NNN; and &#xHHH;)
398
- result = result.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number.parseInt(code, 10)));
399
- result = result.replace(/&#x([0-9a-fA-F]+);/g, (_, code) =>
400
- String.fromCharCode(Number.parseInt(code, 16)),
401
- );
402
-
403
- return result;
404
- }
405
-
406
357
  /**
407
358
  * Clean up message body text.
408
359
  */
@@ -426,11 +377,9 @@ function cleanBody(text: string): string {
426
377
  }
427
378
  }
428
379
 
429
- // Remove stray partial HTML tags at the end of the body
430
- body = body.replace(/<\w+\s*$/, "");
431
-
432
- // Remove any remaining HTML tags that slipped through
433
- body = body.replace(/<[^>]+>/g, "");
380
+ // The renderer emits Markdown. Neutralize raw HTML in both DOM-derived and
381
+ // plain-text messages so decoded entities cannot become executable markup.
382
+ body = body.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
434
383
 
435
384
  // Collapse 3+ consecutive newlines into 2
436
385
  body = body.replace(/\n{3,}/g, "\n\n");
@@ -0,0 +1,50 @@
1
+ import type { Command } from "commander";
2
+ import type { EmitContext } from "../commander.ts";
3
+ import type { NormalizedPolicy } from "../core/policy/index.ts";
4
+ import { loadPolicyFile, policyDigest } from "../core/policy/index.ts";
5
+
6
+ interface PolicyCheckOpts {
7
+ json?: boolean;
8
+ }
9
+
10
+ export function registerPolicyCommand(program: Command, emit: EmitContext): void {
11
+ const command = program
12
+ .command("policy")
13
+ .description("Inspect host-enforced workflow policy documents.");
14
+
15
+ command
16
+ .command("check <file>")
17
+ .description("Validate and print a normalized policy without running a workflow.")
18
+ .option("--json", "Emit the normalized policy and digest as JSON")
19
+ .action((file: string, opts: PolicyCheckOpts) => {
20
+ try {
21
+ const policy = loadPolicyFile(file);
22
+ const result = { policy, sha256: policyDigest(policy) };
23
+ if (opts.json) {
24
+ emit.config({ format: "json" });
25
+ emit.data(result);
26
+ } else {
27
+ emit.text(renderPolicy(policy, result.sha256));
28
+ }
29
+ } catch (error) {
30
+ emit.error({ code: "policy_invalid", message: (error as Error).message });
31
+ emit.setExitCode(1);
32
+ }
33
+ });
34
+ }
35
+
36
+ export function renderPolicy(policy: Readonly<NormalizedPolicy>, digest: string): string {
37
+ const lines = [
38
+ `${policy.name} (schema ${policy.schema_version})`,
39
+ `sha256: ${digest}`,
40
+ `cost ceiling: ${policy.max_cost_usd === undefined ? "none" : `$${policy.max_cost_usd.toFixed(4)}`}`,
41
+ `unknown cost: ${policy.unknown_cost}`,
42
+ `network: ${policy.network}`,
43
+ `external actions: ${policy.external_actions}`,
44
+ `harnesses: ${policy.allowed_harnesses?.join(", ") ?? "any"}`,
45
+ `models: ${policy.allowed_models?.join(", ") ?? "any"}`,
46
+ `paths: ${policy.allowed_paths?.join(", ") ?? "any"}`,
47
+ `isolation: ${policy.allowed_isolation?.join(", ") ?? "any"}`,
48
+ ];
49
+ return `${lines.join("\n")}\n`;
50
+ }
@@ -3,6 +3,8 @@ import type { EmitContext } from "../commander.ts";
3
3
  import { workflowSubscriptionOnly } from "../core/config.ts";
4
4
  import { createBuiltinHarnessRegistry } from "../core/harnesses/index.ts";
5
5
  import { findCoordRoot } from "../core/hooks/resolve/coord-root.ts";
6
+ import type { PolicyIsolation } from "../core/policy/index.ts";
7
+ import { loadPolicyFile } from "../core/policy/index.ts";
6
8
 
7
9
  /**
8
10
  * `workflow run <script>`: execute a workflow script — bounded, schema-gated,
@@ -22,6 +24,8 @@ interface WorkflowRunOpts {
22
24
  resumeFrom?: string;
23
25
  subscriptionOnly?: boolean;
24
26
  allowApiBilling?: boolean;
27
+ policy?: string;
28
+ isolation?: PolicyIsolation;
25
29
  json?: boolean;
26
30
  }
27
31
 
@@ -39,7 +43,7 @@ export function registerWorkflowCommand(program: Command, emit: EmitContext): vo
39
43
  workflow
40
44
  .command("run <script>")
41
45
  .description(
42
- "Execute a workflow script (plain JS: `export default async ({agent, parallel, stage, log, evidence}) => …`). " +
46
+ "Execute a workflow script (plain JS: `export default async ({agent, parallel, stage, log, evidence, authorize}) => …`). " +
43
47
  "Subagents spawn as headless harness-CLI subprocesses, coordination-registered.",
44
48
  )
45
49
  .option("--max-agents <n>", "Total-agent ceiling for the run (default 50)")
@@ -63,6 +67,14 @@ export function registerWorkflowCommand(program: Command, emit: EmitContext): vo
63
67
  "Permit an exported API key to override a stored subscription login (per-token billing); " +
64
68
  "without this the engine refuses that silent-override state",
65
69
  )
70
+ .option(
71
+ "--policy <file>",
72
+ "Host policy JSON/JSONC applied before dispatch and external mutation",
73
+ )
74
+ .option(
75
+ "--isolation <mode>",
76
+ "Host-created execution boundary: shared | worktree | sandbox | remote (default shared)",
77
+ )
66
78
  .option("--json", "Emit the full RunReport as JSON")
67
79
  .action(async (script: string, opts: WorkflowRunOpts) => {
68
80
  const coordRoot = findCoordRoot();
@@ -80,6 +92,16 @@ export function registerWorkflowCommand(program: Command, emit: EmitContext): vo
80
92
  });
81
93
  process.exit(1);
82
94
  }
95
+ if (
96
+ opts.isolation &&
97
+ !(["shared", "worktree", "sandbox", "remote"] as const).includes(opts.isolation)
98
+ ) {
99
+ emit.error({
100
+ code: "bad_isolation",
101
+ message: `unknown isolation ${JSON.stringify(opts.isolation)} (expected: shared | worktree | sandbox | remote)`,
102
+ });
103
+ process.exit(1);
104
+ }
83
105
  // Flag beats config; the two flags contradict each other by design.
84
106
  const subscriptionOnly = opts.subscriptionOnly || workflowSubscriptionOnly(coordRoot);
85
107
  if (subscriptionOnly && opts.allowApiBilling) {
@@ -111,6 +133,12 @@ export function registerWorkflowCommand(program: Command, emit: EmitContext): vo
111
133
  { toolEvidence: adapter.profile.capabilities.toolEvidence },
112
134
  ]),
113
135
  ),
136
+ policy: opts.policy ? loadPolicyFile(opts.policy) : undefined,
137
+ isolation: opts.isolation,
138
+ // CLI harness subprocesses inherit the host network. A policy that
139
+ // forbids network must therefore deny dispatch unless a future host
140
+ // adapter creates and declares a network-disabled boundary.
141
+ networkAccess: "enabled",
114
142
  });
115
143
  if (opts.json) {
116
144
  emit.config({ format: "json" });
@@ -10,9 +10,36 @@
10
10
  import { spawnSync } from "node:child_process";
11
11
  import { existsSync, readdirSync, readFileSync } from "node:fs";
12
12
  import { resolve } from "node:path";
13
+
13
14
  // NOTE: kept dependency-free (node builtins only); this file is vendored verbatim into
14
15
  // a downstream consumer, so it cannot import the coordEnv helper.
15
16
 
17
+ const MAX_INSTANCE_ID_LENGTH = 128;
18
+
19
+ /**
20
+ * Instance IDs become coordination filenames, so only one portable basename
21
+ * alphabet is accepted at every filesystem boundary. UUIDs, test IDs, and
22
+ * legacy hex IDs all fit this contract; separators and dot segments do not.
23
+ */
24
+ export function isSafeInstanceId(value: unknown): value is string {
25
+ if (typeof value !== "string" || value.length === 0 || value.length > MAX_INSTANCE_ID_LENGTH) {
26
+ return false;
27
+ }
28
+ for (let index = 0; index < value.length; index++) {
29
+ const code = value.charCodeAt(index);
30
+ const alpha = (code >= 65 && code <= 90) || (code >= 97 && code <= 122);
31
+ const digit = code >= 48 && code <= 57;
32
+ if (!alpha && !digit && code !== 45 && code !== 95) return false;
33
+ }
34
+ return true;
35
+ }
36
+
37
+ export function assertSafeInstanceId(value: unknown): asserts value is string {
38
+ if (!isSafeInstanceId(value)) {
39
+ throw new Error("instance_id must be 1-128 ASCII letters, digits, hyphens, or underscores");
40
+ }
41
+ }
42
+
16
43
  export interface Heartbeat {
17
44
  instance_id: string;
18
45
  name?: string;
@@ -339,7 +366,7 @@ export function resolveSingleActiveOwner(root: string): string | null {
339
366
  * `.harnery/active/<id>.json` (the canonical location every reader expects).
340
367
  */
341
368
  export function readHeartbeat(instanceId: string): Heartbeat | null {
342
- if (!instanceId) return null;
369
+ if (!isSafeInstanceId(instanceId)) return null;
343
370
  const root = monorepoRoot();
344
371
  if (!root) return null;
345
372
  return readJsonHeartbeatFile(resolve(root, ".harnery", "active", `${instanceId}.json`));