Skip to content

Tier A hardening: close five silent-failure paths in demo rendering - #11

Merged
OrionArchitekton merged 4 commits into
masterfrom
codex/demo-video-tier-a-20260725
Jul 26, 2026
Merged

Tier A hardening: close five silent-failure paths in demo rendering#11
OrionArchitekton merged 4 commits into
masterfrom
codex/demo-video-tier-a-20260725

Conversation

@OrionArchitekton

@OrionArchitekton OrionArchitekton commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Five changes that close paths where the pipeline completes successfully and still ships a defective video. Each fixes a failure this pipeline has already produced in a real render. Sourced from a benchmark against two external video-production systems (knowledge-vault/research/2026-07-25-demo-video-production-pipeline-benchmark.md, PR #94 there); ideas only from the AGPL-licensed side, every mechanism here is ours.

Spec: specs/tier-a-hardening-spec.md.

What changes

Change The failure it closes
S1 A missing ELEVENLABS_API_KEY is an error, not an implicit silent mode A forgotten credential rendered a complete, correctly-timed, captioned video with no voice, invisible to parity because the estimated duration is the clock
S2 Opening navigation and readiness settle hoisted ahead of the recorder A goto-only shot could end capture before first paint, shipping a blank segment, in a real render even when the keyless smoke was clean
S3 maxDurationSec replaces a hardcoded 300, carried across the render manifest Events ship against 2:00 and 3:00 caps; the ceiling was unreachable from config and checked only after the whole render
S4 render-report.json records voice, toolchain, digests, measured timeline A judged 2:57 cut re-rendered at 3:25 with no record of what produced either
S5 Every config schema object rejects unrecognised keys A typo in the remedy for a known defect silently applied the default it was written to override

Review

Three reviewers ran against the diff. Two BLOCKING findings were real defects, not test gaps, and both are fixed:

  • The settle gate was a no-op. Recording began before the actions ran, so it waited on camera and dwell() absorbed the time from the trailing pad: identical content, identical length. An adversarial run sampling frame colour confirmed the hero image absent for the first 1.4s of the shipped segment. Fixed by hoisting the opening navigation ahead of the recorder.
  • A stale dist-remote bundle silently ignored the declared cap. existsSync was the only guard and pnpm demo never rebuilds, so an old renderer enforced 300 while the report recorded the declared limit next to a parity pass that never checked it. Offloading now refuses a bundle older than its sources.

Three changes had no test binding them. Reverting the cap to a literal 300, deleting the report write, and gutting the readiness probe each left the entire suite green. Tests now kill all three mutants, verified by re-running each mutation.

Also fixed from review: default maxSec at the enforcement point so an absent value cannot mean uncapped; consume the probe result rather than treating "evaluate resolved" as "settled"; make a deliberate settleMs: 0 silent; strip control characters from page-controlled error text; validate maxDurationSec at the manifest trust boundary so a non-numeric value cannot make the comparison NaN; digest a config projection excluding machine-resolved paths, which previously gave the same committed config different hashes per operator; record the measured timeline rather than the narration estimate; capture the narration mode once before spend; delete a stale receipt before rendering; drop internal Doppler project names from a public package's error text.

One overclaim was corrected rather than kept: the keyless rehearsal measures a word-count estimate, not real narration, so it surfaces an overage but does not guarantee catching one pre-spend. The spec and the code comment both say so now.

Verification

  • 170 tests, pnpm typecheck, pnpm build all green
  • S1 observed refusing a keyless run; S3 observed rejecting a declared 5s cap on a 26.2s video
  • render-report.json from a real render carries a measured timeline matching the rendered runtime exactly

Breaking

A missing API key now exits non-zero instead of producing a silent video. Every existing test already requested fake mode explicitly, so this is internally non-breaking; it is breaking for npm consumers, hence 0.3.0 and a CHANGELOG.

Known limitations, stated not hidden

The legacy recordvideo engine binds capture at context creation, so the settle shifts rather than removes unsettled frames there. The default screencast engine does not have this limitation. Reviewers also flagged that the DEMO_SCRIPT parser still swallows typos silently (S5 covers the JSON config only) and that a remote render records the local toolchain versions; both are logged as follow-ups rather than scope creep here.

Summary by CodeRabbit

  • New Features
    • Added configurable maxDurationSec render length cap (default 300) and capture.settleMs readiness wait budget.
    • Added render-report.json provenance with voice/TTS selection, tool versions, per-shot timeline, and parity results.
    • Added explicit fake narration mode via FAKE_TTS=1 for deliberate silent placeholder audio.
  • Bug Fixes
    • Narration now errors when credentials are missing (unless fake mode is enabled).
    • Rejects stale remote render bundles to avoid outdated/cap-ignoring renders.
    • Prevents capturing before page readiness; avoids replaying the initial opening navigation; cleans up stray artifacts on live failures.
    • Unknown config keys are rejected with clear error messages.
  • Documentation
    • Updated README/CHANGELOG for the new caps, readiness behavior, and FAKE_TTS=1.
  • Tests
    • Added coverage for readiness probing, provenance/report generation, config validation, and duration-limit behavior.

claude added 2 commits July 25, 2026 18:57
Each item fixes a failure this pipeline has already produced in a real render,
sourced from the 2026-07-25 benchmark against OpenMontage and HyperFrames.
Concepts only from the AGPL side; every mechanism here is ours.

S1 fail-closed narration. resolveTtsMode() replaces an implicit disjunct that
inferred silent mode from an ABSENT api key, so a forgotten `doppler run`
rendered a complete, correctly-timed, captioned video with no voice at all, and
parity verification could not see it because the estimated duration IS the
clock. Fake mode must now be requested explicitly.

S2 readiness settle gate. waitForReady() runs after every goto and before
recording starts: fonts ready plus in-viewport images decoded, bounded by
capture.settleMs (default 500). Fails OPEN, warning and recording anyway, since
aborting would discard an already-paid render. Makes the logged all-white
frozen-segment failure structural instead of relying on authors remembering to
hand-author `wait ms=`.

S3 declarable duration cap. maxDurationSec replaces the hardcoded 300 literal
and is carried across the render manifest so a remote render enforces the same
limit as a local one; pre-cap manifests default to the 300 they were rendered
under. Events ship against 2:00 and 3:00 caps, and a keyless rehearsal now
reaches the check with measured capture wall-clock.

S4 render provenance. render-report.json records the resolved voice, toolchain
versions, config and script digests, the per-shot timeline, and the parity
result. Written after a successful render and never gating. This is the missing
answer to a judged 2:57 cut re-rendering at 3:25: an unpinned voice model
default, not vendor nondeterminism.

S5 strict config schemas. Every schema object rejects unrecognised keys, so a
typo in the remedy for a known defect fails loudly instead of silently applying
the default it was written to override. All four shipped configs validate clean.

Verified: 161 tests green, typecheck clean, and each gate observed firing in a
real keyless render rather than only in unit tests.
…bound tests

Three reviewers (security, correctness, adversarial) ran against the diff. Two
BLOCKING findings were real defects, not test gaps.

The settle gate did nothing. Recording starts at screencast.start() and only
then were the actions run, so waitForReady waited ON CAMERA and dwell() absorbed
the time from the trailing pad: identical content, identical length. An
adversarial run sampling frame colour confirmed the hero image was absent for
the first 1.4s of the shipped segment. Fixed by hoisting the shot's first goto
and its settle ahead of the recorder (openShotPage), so frame one is painted.
The first goto is found anywhere in the sequence, not only at index 0, so a
chapter-first cold open is covered too. The legacy recordvideo engine binds
capture at context creation and cannot be fixed this way; that is documented in
the spec rather than hidden.

A stale dist-remote bundle silently ignored the declared cap. existsSync was the
only guard and `pnpm demo` never rebuilds, so an old renderer enforced the
previous hardcoded 300 while the report recorded the declared limit beside a
parity pass that never checked it. Offloading now refuses a bundle older than
the sources.

Three changes had no test binding them: reverting the cap to a literal 300,
deleting the report write, and gutting the readiness probe each left the whole
suite green. Added tests that kill all three mutants, verified by re-running
each mutation.

Also: default maxSec at the enforcement point so an absent value cannot mean
uncapped; consume the probe result instead of treating "evaluate resolved" as
"settled"; make a deliberate settleMs 0 silent; strip control characters from
page-controlled error text before it reaches the operator's log; validate
maxDurationSec at the manifest trust boundary so a non-numeric value cannot make
the comparison NaN; digest a config projection that excludes machine-resolved
paths; record the MEASURED timeline rather than the narration estimate; capture
the narration mode once before spend rather than re-deriving it after; delete a
stale receipt before rendering; drop internal Doppler project names from a
public package's error text.

Corrected an overclaim rather than keeping it: the keyless rehearsal measures
the word-count estimate, not real narration, so it surfaces an overage but does
not guarantee one is caught pre-spend. Spec and code comment both say so now.

README documents both new knobs, CHANGELOG records the breaking narration
change, version 0.3.0.

Verified: 170 tests, typecheck, build all green; S1 and S3 observed firing in
real renders; report timeline matches the rendered runtime exactly.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@sourcery-ai sourcery-ai 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.

Sorry @OrionArchitekton, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This release adds strict configuration validation, configurable duration and readiness limits, explicit narration-mode resolution, readiness-gated capture, remote bundle freshness checks, and render-report.json provenance output with timelines, digests, tool versions, and parity results.

Changes

Render hardening

Layer / File(s) Summary
Configuration and duration propagation
src/types.ts, src/manifest.ts, src/render.ts, src/config.test.ts, tests/manifest.test.ts, tests/remote-render.parity.test.ts
Adds strict schemas, maxDurationSec, capture.settleMs, manifest compatibility handling, and configurable parity enforcement.
Readiness-gated capture
src/ready.ts, src/capture.ts, src/ready.test.ts, tests/live-capture.smoke.test.ts
Probes fonts and visible images before recording, bounds readiness waits, logs warnings, skips replayed opening navigation, and removes stray live-capture artifacts.
Explicit narration mode
src/tts.ts, src/tts.test.ts
Requires ELEVENLABS_API_KEY unless FAKE_TTS=1, with explicit mode precedence.
Pipeline safeguards and reports
src/pipeline.ts, src/provenance.ts, tests/pipeline.smoke.test.ts, src/provenance.test.ts
Rejects stale remote bundles, removes stale reports, resolves TTS before rendering, and writes render provenance data.
Release and hardening specification
CHANGELOG.md, README.md, package.json, specs/tier-a-hardening-spec.md
Documents version 0.3.0, new configuration and failure behavior, acceptance scenarios, and verification commands.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Pipeline
  participant TTS
  participant Renderer
  participant Report
  Pipeline->>TTS: Resolve narration mode
  Pipeline->>Renderer: Render with maxDurationSec
  Renderer-->>Pipeline: Return timeline and parity
  Pipeline->>Report: Build and write render report
Loading

Possibly related PRs

Poem

I’m a rabbit guarding the render trail,
With tidy reports in a JSON veil.
Caps keep the video from growing too long,
Ready pages make the first frame strong.
Keys guide the voices; stale bundles flee—
Hop, hop, release 0.3.0 with glee!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 68.75% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: Tier A hardening to close five silent-failure paths in demo rendering.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/demo-video-tier-a-20260725

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d048f61924

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/provenance.ts

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 230: Update the capture.settleMs documentation in README.md at lines
230-230 to qualify the pre-recording readiness guarantee as applying only to the
default screencast engine and note that recordvideo starts at context creation,
shifting pre-settle frames later. Add the same qualification to the
corresponding release note in CHANGELOG.md at lines 18-20.

In `@specs/tier-a-hardening-spec.md`:
- Around line 84-92: Update the S4 specification to document render-report
generation as best-effort, matching the failure handling in the pipeline that
logs report construction, tool-version lookup, or write failures while returning
the rendered result. Adjust the unconditional acceptance language so a completed
render may lack render-report.json when report generation fails.
- Around line 66-82: Rewrite the S3 specification and its related acceptance
language to remove any promise of authoritative pre-spend duration enforcement.
Describe keyless or FAKE_TTS rehearsal as a no-spend estimate/preflight, and
state that the cap check becomes authoritative only after rendering, when
narration may already have been purchased; retain the configurable cap and
overage reporting requirements.

In `@src/capture.ts`:
- Around line 511-520: Update the recording failure handling around openShotPage
and the guard so recordvideo artifacts are deleted when opening navigation fails
before runShot starts. Ensure the catch handler closes/finalizes the context,
removes the produced video, and preserves the existing behavior for other
capture engines; also revise the nearby comment so it does not claim recordvideo
fails closed without recording.

In `@src/pipeline.ts`:
- Around line 187-198: Update the renderRemote/RenderResult flow so remote tool
versions are returned with the render result and used when constructing the
report in buildRenderReport. Replace the local toolVersions() probe for remote
renders, while preserving local tool capture for local rendering and clearly
recording the applicable toolchain in render-report.json.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f12267d4-d325-493f-8e8d-3136e5f8e131

📥 Commits

Reviewing files that changed from the base of the PR and between cd76425 and d048f61.

📒 Files selected for processing (20)
  • CHANGELOG.md
  • README.md
  • package.json
  • specs/tier-a-hardening-spec.md
  • src/capture.ts
  • src/config.test.ts
  • src/manifest.ts
  • src/pipeline.ts
  • src/provenance.test.ts
  • src/provenance.ts
  • src/ready.test.ts
  • src/ready.ts
  • src/render.ts
  • src/tts.test.ts
  • src/tts.ts
  • src/types.test.ts
  • src/types.ts
  • tests/manifest.test.ts
  • tests/pipeline.smoke.test.ts
  • tests/remote-render.parity.test.ts

Comment thread README.md Outdated
Comment thread specs/tier-a-hardening-spec.md Outdated
Comment thread specs/tier-a-hardening-spec.md
Comment thread src/capture.ts Outdated
Comment thread src/pipeline.ts
claude added 2 commits July 25, 2026 19:50
A relative dashboardBaseUrl ("./") is rewritten by loadConfig into a file:// URL
of the current checkout, so hashing it verbatim re-introduced exactly the
machine dependence stableConfigJson exists to remove. The same committed config
produced different configHash values per checkout, defeating the cross-operator
comparison the report is for. Verified before fixing: demos/smoke hashed with
the absolute worktree path embedded.

A local fixture base is not part of a config's identity, so it collapses to a
sentinel; an http(s) base IS part of the identity and is already
machine-independent, so it is kept verbatim and two different ports still
digest differently. Three tests cover both directions plus the auth profileDir
case.

Found by the post-push review pipeline (P2 bot thread on PR #11). It is the
residual half of a finding the pre-PR adversarial pass raised: that fix covered
capture.auth.profileDir and out, and missed this one.

Verified: 173 tests, typecheck, build all green.
…stop overclaiming in docs

The security finding was real and is the substantive one. For target: live under
the legacy recordvideo engine, Playwright binds recording at context creation,
so by the time the auth guard trips during the opening navigation the WebM
already exists and context.close() FINALISES it. The code claimed "an expired
session fails closed with nothing recorded" while leaving a recording of a
logged-out page on disk. The catch now reads the video path before closing and
deletes it: fails closed has to mean no artifact, not merely no return value.
A test asserts no .webm survives, and it fails when the deletion is removed.

Docs and spec corrections, all cases of promising more than the code delivers:

- README and CHANGELOG now qualify the readiness guarantee as screencast-only
  and name the recordvideo limitation, instead of implying both engines exclude
  pre-settle frames.
- S3 renamed from "checked before spending" to "declarable and enforced".
  Enforcement is post-render: a real run synthesises all narration before the
  render stage, so an over-cap real run has already spent. The keyless rehearsal
  is the no-spend path and now says exactly that.
- S4 states the report is best-effort. A provenance failure warns and leaves the
  render standing rather than discarding an artifact already paid for, so the
  report is evidence when present, never a guarantee of presence. Also records
  that a parity failure produces no report at all.

Reversed an earlier decline rather than defending it: the remote-toolchain gap
was raised by the pre-PR adversarial pass, declined as a follow-up, then
re-raised independently. The spec says "the versions of the tools that rendered
it", so the spec wins. The report now carries renderedOn: local | remote, so
locally-probed versions can never be silently read as the remote renderer's.
Probing the remote toolchain remains a follow-up, now stated in the spec.

Verified: 175 tests, typecheck, build green; a real render carries
renderedOn: local.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/provenance.ts (1)

98-110: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Normalize local authentication URLs before hashing.

stableConfigJson() hashes dashboardBaseUrl and profileDir after stripping checkout-specific file:// values, but capture.auth.loginUrl is left untouched. Since tests/live-capture.smoke.test.ts resolves loginUrl from resolve("tests/fixtures/saas-app.html"), identical live configs in different checkouts can get different configHash values. Apply the same local-file normalization or preserve the intended stable fixture path while still keeping remote login URLs intact.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/provenance.ts` around lines 98 - 110, Update stableConfigJson() to
normalize local file-based capture.auth.loginUrl values before hashing, using
the same checkout-independent treatment as dashboardBaseUrl and auth.profileDir.
Preserve remote HTTP(S) login URLs unchanged and retain the existing
auth/profileDir sanitization.
🧹 Nitpick comments (1)
src/provenance.test.ts (1)

50-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a schema-valid typed fixture instead of as never.

These tests bypass DemoConfig, so required-field or schema changes can leave them compiling while they exercise malformed objects. Build the fixture with DemoConfigSchema.parse(...) or type it as DemoConfig, then vary only the fields under test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/provenance.test.ts` around lines 50 - 51, Replace the `as never` casts in
the `base` and `mk` fixtures with a schema-valid `DemoConfig` fixture, using
`DemoConfigSchema.parse(...)` or explicit `DemoConfig` typing. Keep the shared
valid fields intact and vary only the properties under test.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/provenance.ts`:
- Around line 15-20: Update the provenance model around renderedOn and tools to
explicitly identify that tools was probed locally, adding a serialized toolHost
or equivalent source field. Populate it consistently in the pipeline and ensure
remote reports distinguish the local tool snapshot from the remote renderer’s
toolchain.

---

Outside diff comments:
In `@src/provenance.ts`:
- Around line 98-110: Update stableConfigJson() to normalize local file-based
capture.auth.loginUrl values before hashing, using the same checkout-independent
treatment as dashboardBaseUrl and auth.profileDir. Preserve remote HTTP(S) login
URLs unchanged and retain the existing auth/profileDir sanitization.

---

Nitpick comments:
In `@src/provenance.test.ts`:
- Around line 50-51: Replace the `as never` casts in the `base` and `mk`
fixtures with a schema-valid `DemoConfig` fixture, using
`DemoConfigSchema.parse(...)` or explicit `DemoConfig` typing. Keep the shared
valid fields intact and vary only the properties under test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4dd77ae8-e524-4a49-b41c-88b8f93e700c

📥 Commits

Reviewing files that changed from the base of the PR and between d048f61 and 5a58644.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • README.md
  • specs/tier-a-hardening-spec.md
  • src/capture.ts
  • src/pipeline.ts
  • src/provenance.test.ts
  • src/provenance.ts
  • tests/live-capture.smoke.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • CHANGELOG.md
  • README.md
  • specs/tier-a-hardening-spec.md
  • src/pipeline.ts
  • src/capture.ts

Comment thread src/provenance.ts
Comment on lines +15 to +20
/** Where the ffmpeg work actually happened. `tools` below is probed LOCALLY, so
* on "remote" it describes the machine that captured and synthesised, NOT the
* one that rendered. Recorded explicitly so a reader is never misled into
* attributing a runtime change to a toolchain that did not produce it. */
renderedOn: "local" | "remote";
tools: ToolVersions;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repository files of interest:\n'
git ls-files | rg '(^|/)provenance\.ts$|(^|/)pipeline\.ts$|package\.json$|schema|report' | sed -n '1,120p'

printf '\n--- provenance outline ---\n'
ast-grep outline src/provenance.ts --view expanded || true

printf '\n--- provenance relevant lines ---\n'
sed -n '1,140p' src/provenance.ts

printf '\n--- pipeline relevant lines ---\n'
sed -n '160,220p' src/pipeline.ts

printf '\n--- toolVersions usages ---\n'
rg -n "toolVersions|tools:|renderedOn|RenderReport|provenance" src -S

Repository: OrionArchitekton/agent-demo-video

Length of output: 8919


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- package scripts/deps ---\n'
cat package.json

printf '\n--- provenance tests ---\n'
sed -n '1,140p' src/provenance.test.ts

Repository: OrionArchitekton/agent-demo-video

Length of output: 262


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- package scripts/deps ---'
cat package.json

printf '%s\n' ''
printf '%s\n' '--- provenance tests ---'
sed -n '1,180p' src/provenance.test.ts

Repository: OrionArchitekton/agent-demo-video

Length of output: 5164


Make the provenance source of tools explicit.

renderedOn can be "remote" while tools is always await toolVersions() locally from the pipeline. The serialized report only contains the local version snapshot, so consumers can mistake the host’s toolchain for the rendered VM’s. Add a serialized field such as toolHost/local-only tools, or separate probe/provided tool versions, and cover the remote report shape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/provenance.ts` around lines 15 - 20, Update the provenance model around
renderedOn and tools to explicitly identify that tools was probed locally,
adding a serialized toolHost or equivalent source field. Populate it
consistently in the pipeline and ensure remote reports distinguish the local
tool snapshot from the remote renderer’s toolchain.

@OrionArchitekton
OrionArchitekton merged commit 0d940d5 into master Jul 26, 2026
3 checks passed
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.

2 participants