Skip to content

feat(web): self-inject web::fetch guidance via pre-generate hook - #385

Merged
andersonleal merged 5 commits into
mainfrom
worktree-web-inject-guidance
Jul 1, 2026
Merged

andersonleal merged 5 commits into
mainfrom
worktree-web-inject-guidance

Conversation

@andersonleal

@andersonleal andersonleal commented Jul 1, 2026 •

Copy link
Copy Markdown
Collaborator

What

Make the web worker own and inject its own web::fetch usage guidance into the
agent system prompt, mirroring how workflow::inject-guidance already works. The
harness prompt stops hardcoding web::*.

Why

Today the harness hardcodes web::fetch guidance across its prompt variants. The
workflow worker already solved this the right way: a harness::hook::pre-generate
hook appends its guidance only while the worker is connected — presence-gated,
single canonical copy, no drift across variants. This brings web to parity.

Changes

web — self-injecting guidance (v1.2.0)

  • New web::inject-guidance pre_generate hook (web/src/functions/inject_guidance.rs)
    with a single canonical WEB_GUIDANCE string.
  • Ported the minimal presence-gated bind machinery into configuration.rs (binds only
    once harness::hook::pre-generate exists; on_error: fail_open so a missing guidance
    line never blocks a turn), wired from main.rs via setup_harness_hooks.
  • Presence-gated: guidance is injected only while web is connected, dropped when it
    disconnects.

harness — stop citing web::*

  • Removed the hardcoded web::fetch HTTP-mandate block from all prompt variants.
  • Reworded the "read the SDK reference before authoring" instruction to drop the
    web::fetch naming (the injected guidance now covers how).
  • Dropped the workflow dependency from iii.worker.yaml (workflow is optional and
    self-attaches via registry-change events; web stays a hard dep so its injected
    guidance is always present).

Follow-up fix — surfaced while investigating a live web::fetch 404

  • The SDK reference docs moved: iii.dev/docs/sdk-reference/<lang>-sdk (now 404, with
    or without .md) → iii.dev/docs/api-reference/sdk-<lang>. Updated the URLs in all
    prompt variants and the sdk_doc_gate test. engine-sdk is unchanged.
  • Relocated the web::fetch mandate test from the harness (web_fetch_localhost_mandate,
    which asserted the now-removed prompt text) to the web worker
    (web_fetch_mandate_present), where the guidance now lives.

Verification

  • web: cargo test → 102 passing (incl. inject_guidance enrich/empty + mandate tests).
  • harness: cargo test --lib → 98 passing; prompt suite 30/30 (previously 30/1 — the
    relocated test was red).
  • Live: new api-reference/sdk-<lang>.md URLs return 200 text/markdown; old
    sdk-reference/<lang>-sdk paths return 404.

Notes

  • web stays a harness dependency by design; only workflow was removed.
  • Behavioral end-to-end (boot harness + web, confirm the injected guidance appears in
    the system prompt and drops when web disconnects) requires a running engine and was
    not exercised in CI.

https://claude.ai/code/session_015P3MFVnbz8DVFSjtfpUosR

Summary by CodeRabbit

  • New Features

    • Added automatic guidance injection for the web worker, so prompt instructions are applied consistently when the worker is connected.
    • Updated SDK documentation references to newer, easier-to-follow API reference pages.
  • Bug Fixes

    • Improved startup behavior so guidance injection can initialize reliably across different load timing scenarios.
    • Removed outdated HTTP-request guidance that could conflict with the latest workflow.

The web worker now contributes its web::fetch usage guidance to the agent
system prompt through a harness::hook::pre-generate hook (web::inject-guidance),
mirroring workflow::inject-guidance. It is presence-gated: injected only while
the web worker is connected, and dropped when it disconnects.

- web: add web::inject-guidance pre_generate hook with a single canonical
  WEB_GUIDANCE string, plus the presence-gated bind machinery ported from the
  workflow worker (bind only once harness::hook::pre-generate exists); bump 1.2.0
- harness: remove all hardcoded web::* citations from the prompt variants — the
  HTTP-mandate block is deleted, and the SDK-reference instruction is reworded to
  drop the web::fetch naming
- harness: drop the workflow dependency from iii.worker.yaml (workflow is optional
  and self-attaches; web stays a hard dep so its injected guidance is present)

Claude-Session: https://claude.ai/code/session_015P3MFVnbz8DVFSjtfpUosR
Both surfaced while investigating a web::fetch 404 on
https://iii.dev/docs/sdk-reference/browser-sdk.md:

1. The SDK reference docs moved. The language SDK pages are now at
   iii.dev/docs/api-reference/sdk-<lang> (node/python/rust/browser); the old
   sdk-reference/<lang>-sdk paths 404 with or without .md — that was the reported
   error, not the .md suffix. Update the URLs in all prompt variants and the
   sdk_doc_gate test. The engine-protocol doc (sdk-reference/engine-sdk) is
   unchanged. Verified the new .md URLs return 200 text/markdown.

2. The web::fetch mandate was removed from the prompts (it is now injected by
   web::inject-guidance) but its test (web_fetch_localhost_mandate) still asserted
   the old prompt text and was failing. Relocate the assertion to the web worker
   (web_fetch_mandate_present) where the guidance now lives.

Claude-Session: https://claude.ai/code/session_015P3MFVnbz8DVFSjtfpUosR
CI runs `cargo fmt --all -- --check`; wrap the multi-arg assertion to satisfy it.

Claude-Session: https://claude.ai/code/session_015P3MFVnbz8DVFSjtfpUosR
@vercel

vercel Bot commented Jul 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview, Comment Jul 1, 2026 6:25pm
workers-tech-spec Ready Ready Preview, Comment Jul 1, 2026 6:25pm

Request Review

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 30 skipped (no docs/).

Layer Result
structure ✓
vale ✓
ai ✓
render ✓

Four for four. Nicely done.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@andersonleal, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3c8eafb7-04ba-47f9-9d8a-f2144976d7a6

📥 Commits

Reviewing files that changed from the base of the PR and between 751a30e and 192d353.

📒 Files selected for processing (1)
  • web/src/functions/inject_guidance.rs
📝 Walkthrough

Walkthrough

Prompt files across the harness update SDK documentation URLs to new api-reference paths and remove hardcoded web::fetch HTTP-request instructions. A new web::inject-guidance pre-generate hook is added to the web worker, injecting fetch guidance into the system prompt, with new harness hook binding logic, registration wiring, and a version bump.

Changes

Prompt SDK doc URL and web::fetch guidance removal

Layer / File(s) Summary
Update SDK reference URLs
harness/prompts/anthropic.txt, harness/prompts/cli.txt, harness/prompts/default.txt, harness/prompts/gpt.txt, harness/prompts/kimi.txt
SDK documentation links switched from sdk-reference/-sdk paths to docs/api-reference/sdk- paths, some with "fetch as Markdown" wording.
Remove hardcoded web::fetch guidance and reword curl reminders
harness/prompts/*.txt
Deletes the block mandating web::fetch for all HTTP(S) requests, localhost verification, and markdown formatting; shortens curl-prohibition checklist bullets.
Update harness tests and worker dependencies
harness/src/prompt/tests.rs, harness/iii.worker.yaml
Updates sdk_doc_gate assertions to new URLs, replaces the removed web_fetch_localhost_mandate test with an explanatory comment, and removes the workflow dependency.

Web worker inject-guidance hook and harness binding

Layer / File(s) Summary
Implement inject_guidance hook
web/src/functions/inject_guidance.rs
Adds hook constants, PreGenerateEvent/GenerateContext types, enrich() logic appending WEB_GUIDANCE to the system prompt, async fail-open handle(), and unit tests.
Register hook in module setup
web/src/functions/mod.rs
Declares the inject_guidance submodule and registers it via register_all, wiring PreGenerateEvent to handle().
Add harness hook binding logic
web/src/configuration.rs
Adds concurrency-safe try_bind_harness_hooks and readiness checks, setup_harness_hooks with event-driven retries and warm-start probe, plus unit tests.
Wire startup and bump version
web/src/main.rs, web/Cargo.toml
Calls setup_harness_hooks during boot, updates the ready log message, and bumps crate version from 1.1.4 to 1.2.0.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Main as web/main.rs
  participant Config as configuration::setup_harness_hooks
  participant Engine
  participant Hook as inject_guidance::handle

  Main->>Config: setup_harness_hooks(iii)
  Config->>Engine: subscribe to engine::workers-available / functions-available
  Config->>Engine: probe engine::triggers::list (warm-start)
  Engine-->>Config: harness::hook::pre-generate present?
  alt hook trigger ready
    Config->>Engine: register_trigger web::on-config-change (fail_open)
  else not ready
    Engine-->>Config: engine::*-available event fires later
    Config->>Engine: retry register_trigger
  end
  Engine->>Hook: PreGenerateEvent (system_prompt)
  Hook->>Hook: enrich(base) appends WEB_GUIDANCE
  Hook-->>Engine: mutations.system_prompt
Loading

Possibly related PRs

  • iii-hq/workers#245: Both PRs modify identity/system-prompt guidance around fetching iii.dev SDK docs and enforcing web::fetch, with the main PR moving that mandate into the new inject-guidance hook.
  • iii-hq/workers#288: Both PRs modify harness/iii.worker.yaml dependency entries.
  • iii-hq/workers#299: Both PRs adjust the dependencies section of harness/iii.worker.yaml.

Suggested reviewers: sergiofilhowz

Poem

A rabbit hopped through docs anew,
Swapped old links for api-reference too,
No more curl to sneak and prowl,
web::fetch now whispered by a hook's soft howl,
Guidance injected, prompt-side and neat—
Hop hop hooray, the code's a treat! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 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: the web worker now self-injects web::fetch guidance through a pre-generate hook.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-web-inject-guidance

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.

Version bumps are handled separately from feature PRs; revert web to 1.1.4.

Claude-Session: https://claude.ai/code/session_015P3MFVnbz8DVFSjtfpUosR

@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: 2

🤖 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 `@web/src/configuration.rs`:
- Around line 96-127: The binding state in try_bind_harness_hooks is marked too
early, before the hook is actually observable in the engine. Move the bound=true
claim to after bind() succeeds and the hook is confirmed active, using the
existing try_bind_harness_hooks and bind flow so a dropped asynchronous
registration does not leave the AtomicBool stuck true. If the bind is accepted
but not visible, keep the retry path reachable by only setting bound once the
hook is truly in place.

In `@web/src/functions/inject_guidance.rs`:
- Around line 26-36: The hook event deserialization in
PreGenerateEvent/GenerateContext is too permissive because serde defaults turn a
missing or renamed generate.system_prompt into an empty string, which later
causes inject_guidance to overwrite the prompt with WEB_GUIDANCE alone. Remove
the defaulting behavior on the nested generate/system_prompt fields and update
inject_guidance to preserve the existing system prompt when the event payload is
missing or malformed, or fail the hook explicitly instead of replacing the
prompt.
🪄 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

Run ID: 67e134f3-06b0-4982-b64f-2b675bd24fa9

📥 Commits

Reviewing files that changed from the base of the PR and between dbf1125 and 751a30e.

⛔ Files ignored due to path filters (1)
  • web/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • harness/iii.worker.yaml
  • harness/prompts/anthropic.txt
  • harness/prompts/cli.txt
  • harness/prompts/default.txt
  • harness/prompts/gpt.txt
  • harness/prompts/kimi.txt
  • harness/src/prompt/tests.rs
  • web/Cargo.toml
  • web/src/configuration.rs
  • web/src/functions/inject_guidance.rs
  • web/src/functions/mod.rs
  • web/src/main.rs

Comment thread web/src/configuration.rs
Comment thread web/src/functions/inject_guidance.rs
web::inject-guidance defaulted a missing/renamed generate.system_prompt to "" and
returned it as the mutation, replacing the whole agent system prompt with the
guidance alone. Now emit no system_prompt mutation when the base is empty, so the
harness preserves its assembled prompt (per HookRunner::run_pre_generate, it
overwrites only when the mutation carries system_prompt). Addresses CodeRabbit
review on #385.

Claude-Session: https://claude.ai/code/session_015P3MFVnbz8DVFSjtfpUosR
@andersonleal
andersonleal merged commit d949441 into main Jul 1, 2026
37 checks passed
@andersonleal
andersonleal deleted the worktree-web-inject-guidance branch July 1, 2026 18:31
rohitg00 added a commit that referenced this pull request Jul 27, 2026
Resolves against the prompt-evaluation work that landed in #595, which
edited the same sections this branch moves out of the identity prompt.

- `default.txt` keeps this branch's trimmed identity. The `curl`
  prohibition is dropped with it: the web worker has injected that rule
  through its own pre-generate hook since #385, so the line was a stale
  duplicate that also fired on rigs without the web worker installed.
- #595's dispatch doctrine (audit every resolved resource selector before
  dispatching; derive a per-run namespace suffix and confirm the namespace
  is absent) moves into `harness/skills/orchestration.md`, which now owns
  spawn and reaction mechanics.
- #595 also corrected the reaction session semantics: an ordinary event
  reaction MUST omit `metadata.session_id`, and every event then creates a
  fresh distinct child under the resolved console root. The playbook still
  carried the older rule, that omitting it delivers back into the
  registering chat, so it was describing behaviour the runtime no longer
  has. Same for `once`, which is a top-level registration field and is
  standing by default on join predecessor edges.
- The three tests #595 added assert that doctrine against the identity
  prompt. They now assert it against the orchestration playbook, which is
  where the text lives after this branch.

This branch was successfully deployed

2 active deployments
Preview – workers-tech-spec — 192d3530 Deployed Jul 1, 2026 by vercel[bot]
Preview – workers — 192d3530 Deployed Jul 1, 2026 by vercel[bot]
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