Skip to content

FE-1230: Compare greenfield execution#345

Merged
kostandinang merged 8 commits into
nextfrom
ka/fe-1230-greenfield-execution-comparison-tracer
Jul 20, 2026
Merged

FE-1230: Compare greenfield execution#345
kostandinang merged 8 commits into
nextfrom
ka/fe-1230-greenfield-execution-comparison-tracer

Conversation

@kostandinang

@kostandinang kostandinang commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Why

Greenfield execution outputs need comparable evidence from the same frozen specification without exposing hidden evaluation criteria or landing generated code.

What

Add the Petri-net editor comparison case, controller-only oracles, immutable attempt evidence, and an isolated Brunch lane that stops at promotion_prepared. The tracer retains valid and invalid attempts and separates masked outcome evidence from unblinded process evidence.

How to test

  • npm run check
  • npm test -- src/dev/execution-comparison
  • npm run test:slow -- src/dev/execution-comparison/__tests__/browser-oracle.slow.test.ts
  • npm run verify:full

kostandinang commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@kostandinang kostandinang changed the title FE-1230: Freeze greenfield execution tracer contract FE-1230: Greenfield execution comparison tracer Jul 20, 2026
@semgrep-code-hashintel

Copy link
Copy Markdown

Semgrep found 6 detect-non-literal-regexp findings:

RegExp() called with a value function argument, this might allow an attacker to cause a Regular Expression Denial-of-Service (ReDoS) within your application as RegExP blocks the main thread. For this reason, it is recommended to use hardcoded regexes instead. If your regex is run on user-controlled input, consider performing input validation or use a regex checking/sanitization library such as https://www.npmjs.com/package/recheck to verify that the regex does not appear vulnerable to ReDoS.

View Dataflow Graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>src/dev/execution-comparison/case-contract.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L93 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 93] value</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L93 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 93] value</a>"]

            v3["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L99 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 99] requiredRecord</a>"]

            v4["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L164 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 164] value</a>"]

            v5["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L165 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 165] selected</a>"]

            v6["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L99 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 99] accessibility</a>"]

            v7["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L100 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 100] requiredRecord</a>"]

            v8["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L164 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 164] value</a>"]

            v9["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L165 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 165] selected</a>"]

            v10["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L100 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 100] dynamic</a>"]

            v11["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L121 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 121] accessiblePattern</a>"]

            v12["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L188 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 188] value</a>"]
        end
            v2 --> v3
            v3 --> v4
            v4 --> v5
            v5 --> v6
            v6 --> v7
            v7 --> v8
            v8 --> v9
            v9 --> v10
            v10 --> v11
            v11 --> v12
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/hashintel/brunch/blob/aa7a4ff9cc0191de086008ba3bf9ae59222daddf/src/dev/execution-comparison/case-contract.ts#L192 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 192] new RegExp(value[&apos;namePattern&apos;], &apos;u&apos;)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink

Loading

@kostandinang
kostandinang marked this pull request as ready for review July 20, 2026 15:26
@kostandinang kostandinang self-assigned this Jul 20, 2026
@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New dev-only evaluation path touches executor projection, workspace seeding, and headless browser oracles, but product runtime and host landing stay out of scope; risk is mainly harness correctness and accidental leakage of controller material into lanes.

Overview
Introduces the FE-1230 greenfield execution comparison tracer so Brunch Execute can be evaluated against the same frozen spec as other lanes without leaking hidden tests or landing generated code.

Case and contracts: testing/execution-comparisons/cases/minimal-petri-net-editor/ holds the approved spec.md, content-addressed public-contract.json (delivery, accessibility roles/names, budgets), and a controller-only oracle pack (manifest, invalid import fixtures, known-good reference app). Public packets are hashed and scanned so controller paths and oracle material never enter a lane cwd.

Dev harness (src/dev/execution-comparison/): Loads and validates the public packet; builds a Brunch graph seed from the approved spec plus public delivery/accessibility constraints; prepares an empty workspace with only the public packet copied under .brunch/execution-comparison/public. Immutable attempt schema (artifact-contract) enforces retention, not_assessable metrics, and rejects landed. Masked outcome vs unblinded process packets (packet-redaction) split judgment evidence. A weighted P/T reference model (petri-reference) supports independent Petri checks. Browser oracle (browser-oracle, playwright-core) runs npm test/build, serves dist/, and drives role/name-based journeys (create/drag, fire/reset/reload, import/export, invalid ops) against lane output.

Brunch entry: execution-comparison-brunch.ts launches the real TUI with pinned anthropic/claude-opus-4-8 and greenfield session preflight for manual/smoke execution toward promotion_prepared.

Docs and release: memory/PLAN.md, memory/SPEC.md, and a new execution card document verification tiers, oracle boundaries, and blind spots; changeset marks a minor @hashintel/brunch feature for compare greenfield execution.

Reviewed by Cursor Bugbot for commit 0180267. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread src/dev/execution-comparison/browser-oracle.ts Outdated
Comment thread src/dev/execution-comparison-brunch.ts Outdated
kostandinang and others added 4 commits July 20, 2026 21:36
Record the approved Petri editor input and bounded oracle-smoke scope so implementation proceeds against a durable comparison boundary.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add the public and controller-only contracts, browser/reference oracles, immutable evidence packets, and a pinned Opus Brunch lane so matched execution attempts can be judged reproducibly.

Co-authored-by: Cursor <cursoragent@cursor.com>
Treat the browser's implicit favicon request as harness noise so execution outputs are judged only on public application behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Accept either public feedback role, reject malformed CLI option values, and compile only the frozen accessible-name patterns so the oracle stays portable and bounded.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kostandinang
kostandinang force-pushed the ka/fe-1230-greenfield-execution-comparison-tracer branch from aa7a4ff to 9c014bf Compare July 20, 2026 19:42
Comment thread src/dev/execution-comparison/browser-oracle.ts
Comment thread src/dev/execution-comparison-brunch.ts
Record that the controller-only execution comparison tooling does not require a package version bump so the release-intent gate can distinguish it from shipped changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/dev/execution-comparison/browser-oracle.ts
@kostandinang kostandinang changed the title FE-1230: Greenfield execution comparison tracer FE-1230: Compare greenfield execution Jul 20, 2026
kostandinang and others added 2 commits July 20, 2026 21:52
Use canonical module identity for the lane entrypoint and platform-aware path containment for static assets so compiled and Windows runs preserve the same harness behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Declare the greenfield execution comparison framework for the next alpha release.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/dev/execution-comparison/brunch-lane.ts
Comment thread .changeset/execution-comparison-tracer.md Outdated
Strip leading section metadata before applying title fallback so body-less decisions seed meaningful chosen options, and remove the redundant empty changeset now that release intent is explicit.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kostandinang
kostandinang merged commit 7af7009 into next Jul 20, 2026
7 checks passed
@kostandinang
kostandinang deleted the ka/fe-1230-greenfield-execution-comparison-tracer branch July 20, 2026 20:03

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0180267. Configure here.

const input = page.getByRole('button', { name: 'Import JSON', exact: true });
await input.setInputFiles(path);
await feedback(page, /Import rejected/iu).waitFor();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale import feedback race

Medium Severity

importFile waits for /Import rejected/ feedback that may already be on screen from a prior failed import. On the second invalid import in invalid-and-cascade, that wait can resolve before the new async import finishes, so the net-unchanged assertion can run too early and miss a lane that incorrectly accepts schema-invalid.json.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0180267. Configure here.

headless: true,
});
const context = await browser.newContext({ acceptDownloads: true });
const page = await context.newPage();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Server leak on browser launch failure

Medium Severity

The static server is started before Chrome resolution and browser/context creation, but cleanup only runs inside the later try/finally. If resolveChromeExecutable or chromium.launch fails, the listening server is never closed, leaking ports across slow oracle runs.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0180267. Configure here.

@hash-worker hash-worker Bot mentioned this pull request Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant