harness-for-rea 0.1.0 → 0.1.2

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/main.js CHANGED
@@ -76524,8 +76524,78 @@ function applyPatch(dataDir, id, sourceRoot) {
76524
76524
  return changes.map((c) => c.path);
76525
76525
  }
76526
76526
 
76527
- // raw:C:/Users/prode/harness-for-rea/sandbox/specialist-base/AGENTS.md
76528
- var AGENTS_default = "# Operating guide \u2014 the specialist as a harness of REA\r\n\r\nYou analyse with REA, the reverse engineering MCP server attached to this session. Its tools are\r\nnamed `mcp__rea__<tool>`. This guide says how you use them. REA's own skill says what each tool is\r\nfor. Read `/opt/hfr/rea-skill/SKILL.md` before your first REA call, and its `references/` when a\r\ntarget needs them.\r\n\r\n## The environment\r\n\r\n- REA is already connected and its catalog is fixed. Never run `rea setup`, `rea update` or\r\n `npx rea-agents`, and never ask for a restart. The skill's \"connect only when needed\" steps do\r\n not apply here.\r\n- These engines are installed and REA finds them:\r\n - Ghidra 12.1.4 (`$GHIDRA_INSTALL_DIR`) with JDK 21 (`$JAVA_HOME`);\r\n - jadx-headless-mcp (`$REA_JADX_MCP_JAR`);\r\n - Apktool (`$REA_APKTOOL_COMMAND`).\r\n- Hopper, JEB, IDA, Frida, ADB and the macOS tools are not available. Do not try them.\r\n- You are root with a shell and the internet. Install another tool only when REA cannot answer\r\n the question, and say so in the report.\r\n- `/work` holds the files you were given. Keep everything you extract, build or export in\r\n `/root/out`, which the task keeps, or in `/tmp`, never in `/work`.\r\n\r\n## How an analysis runs\r\n\r\n1. Call `binary_session {}` once to see what this server can do.\r\n2. Turn the objective into a checklist of the questions you must answer.\r\n3. Route the target before analysing it. The input decides the first tool:\r\n - an ASAR or Electron app goes to `analyze_javascript_application`;\r\n - an APK goes to `inspect_android_package`;\r\n - a .NET assembly goes to `inspect_managed_artifact`;\r\n - firmware goes to `inspect_firmware_regions`;\r\n - an archive goes to `open_binary` and `inspect_artifact`;\r\n - a native binary goes to `open_binary`.\r\n4. Work summary first. Request `detail: \"summary\"`, then page what was retained with\r\n `inspect_analysis_view` and its `parent_evidence_id`. Never repeat an identical call: reuse the\r\n session's state.\r\n5. Corroborate every claim with the kind of evidence it needs. Static analysis never shows what\r\n happened at run time; only a run or a capture does.\r\n6. Keep a finding ledger as you go: each conclusion, its evidence IDs, its authority and\r\n confidence, how far you searched, and what remains unknown.\r\n7. Before finishing:\r\n - Export the evidence bundle with `export_evidence_bundle` to `/root/out/evidence/`. REA's\r\n ledger lives in its process and is gone when this run ends.\r\n - Close the target with `close_binary`.\r\n - Mark each checklist question answered, partial or unresolved.\r\n\r\n## Unknowns\r\n\r\n- Record every question you cannot settle with `record_unknown`: what would settle it, and the\r\n evidence for and against. Do not guess.\r\n- Revise an unknown with `update_unknown` against its current revision. On a revision conflict,\r\n read it again rather than retrying.\r\n- Call an unknown resolved only after `verify_unknown_resolution` confirms the evidence behind it.\r\n\r\n## Evidence rules\r\n\r\n- Missing evidence is never proof that something is absent or does not happen.\r\n- Mark a value as estimated only after you looked for it, and say where you looked.\r\n- Label every claim as an observation, an inference or an unknown.\r\n- Cite REA's identifiers verbatim: `ev_` and 64 hex digits for evidence, `unk_` and 64 hex digits\r\n for unknowns.\r\n\r\nIn the report's Evidence section, write one line per claim, in one of these forms:\r\n\r\n```\r\n- <path>:<start line>-<end line> \u2014 <claim> a range of a text file in /work\r\n- <path>@0x<address> \u2014 <claim> an address in a binary in /work\r\n- ev_<64 hex> \u2014 <claim> an REA evidence record\r\n- unk_<64 hex> \u2014 <what is still unknown> an REA unknown\r\n```\r\n";
76527
+ // raw:/home/runner/work/harness-for-rea/harness-for-rea/sandbox/specialist-base/AGENTS.md
76528
+ var AGENTS_default = `# Operating guide \u2014 the specialist as a harness of REA
76529
+
76530
+ You analyse with REA, the reverse engineering MCP server attached to this session. Its tools are
76531
+ named \`mcp__rea__<tool>\`. This guide says how you use them. REA's own skill says what each tool is
76532
+ for. Read \`/opt/hfr/rea-skill/SKILL.md\` before your first REA call, and its \`references/\` when a
76533
+ target needs them.
76534
+
76535
+ ## The environment
76536
+
76537
+ - REA is already connected and its catalog is fixed. Never run \`rea setup\`, \`rea update\` or
76538
+ \`npx rea-agents\`, and never ask for a restart. The skill's "connect only when needed" steps do
76539
+ not apply here.
76540
+ - These engines are installed and REA finds them:
76541
+ - Ghidra 12.1.4 (\`$GHIDRA_INSTALL_DIR\`) with JDK 21 (\`$JAVA_HOME\`);
76542
+ - jadx-headless-mcp (\`$REA_JADX_MCP_JAR\`);
76543
+ - Apktool (\`$REA_APKTOOL_COMMAND\`).
76544
+ - Hopper, JEB, IDA, Frida, ADB and the macOS tools are not available. Do not try them.
76545
+ - You are root with a shell and the internet. Install another tool only when REA cannot answer
76546
+ the question, and say so in the report.
76547
+ - \`/work\` holds the files you were given. Keep everything you extract, build or export in
76548
+ \`/root/out\`, which the task keeps, or in \`/tmp\`, never in \`/work\`.
76549
+
76550
+ ## How an analysis runs
76551
+
76552
+ 1. Call \`binary_session {}\` once to see what this server can do.
76553
+ 2. Turn the objective into a checklist of the questions you must answer.
76554
+ 3. Route the target before analysing it. The input decides the first tool:
76555
+ - an ASAR or Electron app goes to \`analyze_javascript_application\`;
76556
+ - an APK goes to \`inspect_android_package\`;
76557
+ - a .NET assembly goes to \`inspect_managed_artifact\`;
76558
+ - firmware goes to \`inspect_firmware_regions\`;
76559
+ - an archive goes to \`open_binary\` and \`inspect_artifact\`;
76560
+ - a native binary goes to \`open_binary\`.
76561
+ 4. Work summary first. Request \`detail: "summary"\`, then page what was retained with
76562
+ \`inspect_analysis_view\` and its \`parent_evidence_id\`. Never repeat an identical call: reuse the
76563
+ session's state.
76564
+ 5. Corroborate every claim with the kind of evidence it needs. Static analysis never shows what
76565
+ happened at run time; only a run or a capture does.
76566
+ 6. Keep a finding ledger as you go: each conclusion, its evidence IDs, its authority and
76567
+ confidence, how far you searched, and what remains unknown.
76568
+ 7. Before finishing:
76569
+ - Export the evidence bundle with \`export_evidence_bundle\` to \`/root/out/evidence/\`. REA's
76570
+ ledger lives in its process and is gone when this run ends.
76571
+ - Close the target with \`close_binary\`.
76572
+ - Mark each checklist question answered, partial or unresolved.
76573
+
76574
+ ## Unknowns
76575
+
76576
+ - Record every question you cannot settle with \`record_unknown\`: what would settle it, and the
76577
+ evidence for and against. Do not guess.
76578
+ - Revise an unknown with \`update_unknown\` against its current revision. On a revision conflict,
76579
+ read it again rather than retrying.
76580
+ - Call an unknown resolved only after \`verify_unknown_resolution\` confirms the evidence behind it.
76581
+
76582
+ ## Evidence rules
76583
+
76584
+ - Missing evidence is never proof that something is absent or does not happen.
76585
+ - Mark a value as estimated only after you looked for it, and say where you looked.
76586
+ - Label every claim as an observation, an inference or an unknown.
76587
+ - Cite REA's identifiers verbatim: \`ev_\` and 64 hex digits for evidence, \`unk_\` and 64 hex digits
76588
+ for unknowns.
76589
+
76590
+ In the report's Evidence section, write one line per claim, in one of these forms:
76591
+
76592
+ \`\`\`
76593
+ - <path>:<start line>-<end line> \u2014 <claim> a range of a text file in /work
76594
+ - <path>@0x<address> \u2014 <claim> an address in a binary in /work
76595
+ - ev_<64 hex> \u2014 <claim> an REA evidence record
76596
+ - unk_<64 hex> \u2014 <what is still unknown> an REA unknown
76597
+ \`\`\`
76598
+ `;
76529
76599
 
76530
76600
  // src/main/sandbox/prompt.ts
76531
76601
  var WORK = "/work";
@@ -95712,8 +95782,8 @@ function lockDataFolder(dataDir, app, pid = process.pid, isAlive = alive) {
95712
95782
  }
95713
95783
  var ATTEMPTS = 20;
95714
95784
  var PAUSE_MS = 50;
95715
- var UNREADABLE_STALE_MS = 2000;
95716
- var GUARD_STALE_MS = 5000;
95785
+ var UNREADABLE_STALE_MS = 5000;
95786
+ var GUARD_STALE_MS = 1e4;
95717
95787
  function pause() {
95718
95788
  Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, PAUSE_MS);
95719
95789
  }
@@ -129366,8 +129436,11 @@ class SandboxService {
129366
129436
  this.onChange = onChange;
129367
129437
  }
129368
129438
  set(patch) {
129369
- this.current = { ...this.current, ...patch };
129370
- this.onChange(this.current);
129439
+ const next = { ...this.current, ...patch };
129440
+ const changed = JSON.stringify(next) !== JSON.stringify(this.current);
129441
+ this.current = next;
129442
+ if (changed)
129443
+ this.onChange(this.current);
129371
129444
  return this.current;
129372
129445
  }
129373
129446
  async status() {
@@ -129419,9 +129492,14 @@ class LoginService {
129419
129492
  error: this.error
129420
129493
  };
129421
129494
  }
129495
+ pushed = "";
129422
129496
  changed() {
129423
129497
  const s = this.current();
129424
- this.onChange(s);
129498
+ const key = JSON.stringify(s);
129499
+ if (key !== this.pushed) {
129500
+ this.pushed = key;
129501
+ this.onChange(s);
129502
+ }
129425
129503
  return s;
129426
129504
  }
129427
129505
  async refresh() {
@@ -130293,7 +130371,7 @@ var package_default = {
130293
130371
  name: "harness-for-rea",
130294
130372
  productName: "Harness for REA",
130295
130373
  private: true,
130296
- version: "0.1.0",
130374
+ version: "0.1.2",
130297
130375
  description: "Desktop app where an OpenRouter orchestrator delegates deep analysis to a sandboxed Claude Code specialist.",
130298
130376
  license: "MIT",
130299
130377
  main: "./out/main/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-for-rea",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Terminal UI of Harness for REA: an orchestrator that delegates deep analysis to a sandboxed Claude Code specialist.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,42 +1,42 @@
1
- # The specialist image: the pinned base pulled from GHCR (adr:0012-pull-the-specialists-base-image-from-ghcr)
2
- # plus the pinned Claude Code CLI for Linux, verified at build time against the release manifest,
3
- # whose gpg signature is checked against Anthropic's release key
4
- # (adr:0006-run-the-specialist-inside-a-container-per-task, specs/task-sandbox R2.6). Built locally,
5
- # so the binary is never redistributed.
6
-
7
- ARG BASE
8
-
9
- FROM debian:bookworm-slim AS verify
10
- ARG CLAUDE_CODE_VERSION
11
- ARG REPOSITORY=https://downloads.claude.ai/claude-code-releases
12
- ARG RELEASE_SIGNER_URL=https://downloads.claude.ai/keys/claude-code.asc
13
- # The fingerprint published on Claude Code's setup page.
14
- ARG FINGERPRINT=31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE
15
- ARG PLATFORM=linux-x64
16
-
17
- RUN apt-get update \
18
- && apt-get install -y --no-install-recommends ca-certificates curl gnupg jq \
19
- && rm -rf /var/lib/apt/lists/*
20
-
21
- WORKDIR /verify
22
- RUN test -n "$CLAUDE_CODE_VERSION" \
23
- && export GNUPGHOME="$(mktemp -d)" \
24
- && curl -fsSL "$RELEASE_SIGNER_URL" -o key.asc \
25
- && gpg --batch --import key.asc \
26
- && curl -fsSL "$REPOSITORY/$CLAUDE_CODE_VERSION/manifest.json" -o manifest.json \
27
- && curl -fsSL "$REPOSITORY/$CLAUDE_CODE_VERSION/manifest.json.sig" -o manifest.json.sig \
28
- && gpg --batch --status-fd 1 --verify manifest.json.sig manifest.json > status.txt \
29
- && grep -E "^\[GNUPG:\] VALIDSIG .* $FINGERPRINT$|^\[GNUPG:\] VALIDSIG $FINGERPRINT " status.txt \
30
- && test "$(jq -r .version manifest.json)" = "$CLAUDE_CODE_VERSION" \
31
- && checksum="$(jq -r --arg p "$PLATFORM" '.platforms[$p].checksum' manifest.json)" \
32
- && echo "$checksum" | grep -Eq '^[0-9a-f]{64}$' \
33
- && curl -fsSL "$REPOSITORY/$CLAUDE_CODE_VERSION/$PLATFORM/claude" -o claude \
34
- && echo "$checksum claude" | sha256sum -c - \
35
- && chmod 0755 claude
36
-
37
- FROM ${BASE}
38
- ARG BASE
39
- ARG CLAUDE_CODE_VERSION
40
- LABEL hfr.claude-code="$CLAUDE_CODE_VERSION" hfr.base="$BASE"
41
-
42
- COPY --from=verify /verify/claude /usr/local/bin/claude
1
+ # The specialist image: the pinned base pulled from GHCR (adr:0012-pull-the-specialists-base-image-from-ghcr)
2
+ # plus the pinned Claude Code CLI for Linux, verified at build time against the release manifest,
3
+ # whose gpg signature is checked against Anthropic's release key
4
+ # (adr:0006-run-the-specialist-inside-a-container-per-task, specs/task-sandbox R2.6). Built locally,
5
+ # so the binary is never redistributed.
6
+
7
+ ARG BASE
8
+
9
+ FROM debian:bookworm-slim AS verify
10
+ ARG CLAUDE_CODE_VERSION
11
+ ARG REPOSITORY=https://downloads.claude.ai/claude-code-releases
12
+ ARG RELEASE_SIGNER_URL=https://downloads.claude.ai/keys/claude-code.asc
13
+ # The fingerprint published on Claude Code's setup page.
14
+ ARG FINGERPRINT=31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE
15
+ ARG PLATFORM=linux-x64
16
+
17
+ RUN apt-get update \
18
+ && apt-get install -y --no-install-recommends ca-certificates curl gnupg jq \
19
+ && rm -rf /var/lib/apt/lists/*
20
+
21
+ WORKDIR /verify
22
+ RUN test -n "$CLAUDE_CODE_VERSION" \
23
+ && export GNUPGHOME="$(mktemp -d)" \
24
+ && curl -fsSL "$RELEASE_SIGNER_URL" -o key.asc \
25
+ && gpg --batch --import key.asc \
26
+ && curl -fsSL "$REPOSITORY/$CLAUDE_CODE_VERSION/manifest.json" -o manifest.json \
27
+ && curl -fsSL "$REPOSITORY/$CLAUDE_CODE_VERSION/manifest.json.sig" -o manifest.json.sig \
28
+ && gpg --batch --status-fd 1 --verify manifest.json.sig manifest.json > status.txt \
29
+ && grep -E "^\[GNUPG:\] VALIDSIG .* $FINGERPRINT$|^\[GNUPG:\] VALIDSIG $FINGERPRINT " status.txt \
30
+ && test "$(jq -r .version manifest.json)" = "$CLAUDE_CODE_VERSION" \
31
+ && checksum="$(jq -r --arg p "$PLATFORM" '.platforms[$p].checksum' manifest.json)" \
32
+ && echo "$checksum" | grep -Eq '^[0-9a-f]{64}$' \
33
+ && curl -fsSL "$REPOSITORY/$CLAUDE_CODE_VERSION/$PLATFORM/claude" -o claude \
34
+ && echo "$checksum claude" | sha256sum -c - \
35
+ && chmod 0755 claude
36
+
37
+ FROM ${BASE}
38
+ ARG BASE
39
+ ARG CLAUDE_CODE_VERSION
40
+ LABEL hfr.claude-code="$CLAUDE_CODE_VERSION" hfr.base="$BASE"
41
+
42
+ COPY --from=verify /verify/claude /usr/local/bin/claude