Bump anchore/sbom-action from 0.9.0 to 0.24.0 - #4
Closed
dependabot[bot] wants to merge 1 commit into
Closed
Conversation
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.9.0 to 0.24.0. - [Release notes](https://github.com/anchore/sbom-action/releases) - [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md) - [Commits](anchore/sbom-action@f6c3d0f...e22c389) --- updated-dependencies: - dependency-name: anchore/sbom-action dependency-version: 0.24.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
dependabot
Bot
force-pushed
the
dependabot/github_actions/anchore/sbom-action-0.24.0
branch
from
July 12, 2026 00:28
fcf27e2 to
2e68c3f
Compare
Contributor
Author
|
Looks like anchore/sbom-action is up-to-date now, so this is no longer needed. |
dependabot
Bot
deleted the
dependabot/github_actions/anchore/sbom-action-0.24.0
branch
July 12, 2026 00:37
dovvnloading
added a commit
that referenced
this pull request
Jul 29, 2026
…ings #4, #13) (#178) The audit listed this bug twice - findings #4 and #13 are the same defect (confirmed identical by an independent re-read of the current code). Every popover through the shared .overlay-popover base class (View, Plugins, Pins, Reasoning, Model) is hosted inside .app-canvas-region, which is overflow:hidden. .overlay-popover itself declared no max-height and no overflow-y, so content taller than the available space - most visibly the View popover's FONT section on a short window - was silently clipped away with no scrollbar and no indication anything was missing. Added max-height: calc(100vh - 96px); overflow-y: auto; to the shared base class. Popovers that already set their own max-height (Reasoning, which opens upward from the composer and caps at min(60vh, 320px)) are unaffected - their own rule simply wins the cascade, since this is only a default for consumers that don't set one. Live-verified at the app's documented 960x600 floor: the View popover's FONT section now renders in full with no scrolling needed (max-height 504px vs 485px of real content). At a shorter 960x450 window, where the content genuinely exceeds the available space, the last color swatch is confirmed off-screen before scrolling and fully reachable after - a real scrollbar, not a resize-and-hope fix. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
dovvnloading
added a commit
that referenced
this pull request
Aug 9, 2026
Wraps api_provider.chat()/chat_stream() in a fallback-chain outer layer: when a task in FALLBACK_ENABLED_TASKS (task_title, task_web_validate - "naming/triage" per the ADR's own framing) hits a retryable/unavailable failure after ADR-006's own same-provider transport retry is exhausted, one more attempt fires against a different provider chosen by the same auto-policy catalog stage 18.4 built, excluding the provider that just failed. Correctness-sensitive tasks (task_chat, task_chart, ...) are untouched - no fallback fires for them, matching "off by default for correctness-sensitive tasks" from the ADR's decision #4. The substitution is never silent: on_fallback threads down the same additive kwarg chain as model_ref/settings_manager, and backend/agents.py's dispatch surfaces it as a warning notification naming both the provider that failed and the one substituted in. chat_stream's own fallback is additionally guarded so it can only fire before any real text has reached the caller - mirroring the existing "nothing forwarded yet" invariant the transport-retry layer already established, so a partially-delivered reply is never silently replayed against a different model. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dovvnloading
added a commit
that referenced
this pull request
Aug 9, 2026
…alog (#305) * ADR-018 stage 18.1: ModelRef dispatch + unified catalog ModelRef(provider, model_id) replaces "task" as the addressing scheme for which provider+model a chat call actually hits. graphlink_model_catalog.py gains ModelRef/ResolvedModel, the resolution chain (resolve_model_ref), three auto policies over the catalog (choose_auto_model_ref: cheapest- capable/fastest/best-quality, always capability-filtered), and unified_catalog() - a pure aggregation of Ollama/llama.cpp scan results plus each API provider's cached catalog into one list, annotated with per-mtok cost via a caller-supplied price_lookup (token_counter.py's pricing table, extracted into price_per_mtok so both the cost estimator and the catalog price off the same numbers). api_provider.chat()/chat_stream() accept an optional model_ref kwarg that takes precedence over the existing task-keyed dict lookup; every call site that doesn't pass one is unaffected. A resolved ref naming Ollama or Llama.cpp is always constructible regardless of the session's configured mode (neither needs credentials) - the realistic mixed local+cloud comparison this ADR exists for. A ref naming a cloud provider other than the session's currently configured one raises an actionable error rather than silently falling back or reaching for credentials the request snapshot was never given; genuine simultaneous multi-cloud-credential routing is out of scope for this stage. Test plan: - backend/tests/test_model_routing.py (17 tests): the three auto policies including capability-filtering (never routes a vision requirement to a text-only model) and the ready/available filter; the full resolution chain's precedence order and its "explicit pins are never capability- filtered" posture; unified_catalog's aggregation and price annotation; api_provider.chat()/chat_stream() actually dispatching on a supplied model_ref (bypassing an intentionally-unconfigured task table), routing to Ollama while the session is in API mode, and the cross-cloud-mismatch actionable error. - tests/test_node_state_migration.py: added the one new non-SceneNode "provider" access shape (ModelDescriptor, not SceneNode) the new test file's own iteration introduced. - backend/tests/test_providers.py + test_api_provider_reasoning.py + test_backend_composer.py + test_agents.py: 337 passed, confirming the dispatch rewrite is behavior-preserving for every existing call site. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * ADR-018 stage 18.2: node/branch model-override resolution chain ChatState gains override_provider/override_model_id - an explicit model pin, the input-routing opposite of the existing provider/model provenance fields (which record what generated a completed reply, not what should generate the next one). SceneDocument.set_model_override/ clear_model_override write it; resolve_model_for_node reads it back for a node and, separately, for its branch root - mirroring _resolve_branch_ system_prompt's exact root-walk shape (get_branch_root, then read one field off the root) rather than inventing a new inheritance mechanism. AgentDispatcher._resolve_model_ref_for_dispatch computes node-override -> branch-override (auto/workspace-default stay out of scope for this stage - see the method's own docstring) and threads the result through the same omit-when-None kwarg chain persona overrides already use: _dispatch -> _call_chat_agent(_stream) -> ChatAgent.get_response -> ChatWorker.run -> api_provider.chat/chat_stream(model_ref=...). No pin anywhere means the kwarg is never even passed - every existing call site is unaffected. Test plan: - backend/tests/test_agents.py (7 new): resolve_model_for_node's precedence order (node pin beats branch-root pin) and root-walk correctness at every depth; sendMessage/regenerateResponse actually carrying the resolved ModelRef through the real dispatch pipeline into _call_chat_agent_stream; the negative case (no pin anywhere never adds a model_ref kwarg at all, not even as None). - backend/domain/branches.py sanity-checked directly (set/clear/root-walk precedence) before writing the dispatch-level tests. - Full suite from repo root: 2180 passed, 16 skipped. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * ADR-018 stage 18.3 (backend half): wire schema, persistence, intents for the model-override pin SceneNodeRow gains overrideProvider/overrideModelId (additive, "" default, codegen regenerated), populated in scene_payload() from ChatState's own fields. session_save.py/session_load.py round-trip them the same way provider/model already do. Two new WS intents (setModelOverride/ clearModelOverride, backend/api/intents_model_routing.py) wrap SceneDocument.set_model_override/clear_model_override in record_command - classified "A" (undoable) in the ADR-010 close-out table, same posture as setGroupColor. Test plan: - backend/tests/test_session_save.py + test_session_load.py: the pin round-trips through build_chat_data/restore_chat_payload; absent in a save (every pre-18.3 row) restores to "" / no pin, never a crash. - backend/tests/test_canvas.py: the two intents actually mutate the node and publish through the real WS dispatch path. - tests/test_node_state_migration.py: golden scene_payload() key-set snapshot updated (additive keys only). - tests/test_undo_classification_gate.py + tests/undo_classification.py: both new intents classified and the locked registered-intent population count updated 140 -> 142. - contracts/codegen.py --check: clean, two-field diff only. - Full suite from repo root: 2185 passed, 16 skipped. Frontend (badge + picker UI) is the remaining half of this stage. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * ADR-018 stage 18.3 (frontend half): model-override badge + picker UI A distinct badge (📌, tinted not muted) renders whenever a node carries a model pin - deliberately separate from the existing provenance badge, since they answer different questions (what generated the last reply vs. what pins the next one) and can legitimately co-occur. The node menu gains "Pin to Current Model" (pins to whatever the Composer's live route currently resolves to - reading composerStore.getComposer() at click time, never subscribed, since only the click matters) and, when a pin exists, "Clear Model Pin (<model>)". A full "browse the installed catalog" picker needs a live catalog fetch this stage doesn't wire to the frontend - "pin to current" is the honestly-scoped, fully-functional slice; see ADR-018's own status note. Wiring: sceneStore gains setModelOverride/clearModelOverride (plain fireIntent wrappers, queueable like setGroupColor - both operations are idempotent). SceneCanvas's stable per-node dispatcher gains the two callbacks; getComposerRoute threads through as an optional getter (App.tsx's real render supplies it, every other <SceneCanvas> render - every existing test - keeps its harmless no-op default). Test plan: - ChatNodeView.test.tsx: badge absent/present/tooltip, co-rendering with the provenance badge, both menu items' click behavior including the current-route-unresolved no-op case. - SceneCanvas.test.tsx: dispatcher wiring reads getComposerRoute at click time and calls the right store method; the no-op case when the route has nothing resolved yet. - sceneStore.test.ts: both new methods send the right intent/args. - Fixed 5 pre-existing test fixture builders (sceneStore.test.ts, SceneCanvas.test.tsx, ChatNodeView.test.tsx, renderCountGate.test.tsx, SceneCanvas.pinSearchJump.test.tsx, SceneCanvas.virtualization.test.tsx) that needed the two new SceneNodeRow/ChatNodeData fields to keep satisfying the (now stricter) generated wire schema/types. - Full `npm run check` (schema + typecheck + lint + test + build + bundle-size): clean. 1582 tests passed across 60 files. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * ADR-018 stage 18.4: auto-policy setting, live dispatch wiring, Settings UI Adds SettingsManager.get/set_auto_model_policy (persisted, closed-vocabulary cheapest-capable/fastest/best-quality) and wires it into the auto rung of the resolution chain: api_provider.chat()/chat_stream() now attempt an auto-fallback via unified_catalog + the persisted policy at the exact point they would otherwise raise "no model configured" - filtered to only providers this session can actually dispatch to right now (both local providers always; a cloud provider only when it is the session's live credentialed one), so the auto rung can never hand back a ref _provider_for_model_ref would then reject. settings_manager threads down the same additive, omit-when-None kwarg chain already built for model_ref (agents.py -> graphlink_chat_agent.py -> api_provider.py). Adds the setAutoModelPolicy WS intent and a General-page dropdown in the Settings dialog. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-018 stage 18.5: fallback chains with visible substitution Wraps api_provider.chat()/chat_stream() in a fallback-chain outer layer: when a task in FALLBACK_ENABLED_TASKS (task_title, task_web_validate - "naming/triage" per the ADR's own framing) hits a retryable/unavailable failure after ADR-006's own same-provider transport retry is exhausted, one more attempt fires against a different provider chosen by the same auto-policy catalog stage 18.4 built, excluding the provider that just failed. Correctness-sensitive tasks (task_chat, task_chart, ...) are untouched - no fallback fires for them, matching "off by default for correctness-sensitive tasks" from the ADR's decision #4. The substitution is never silent: on_fallback threads down the same additive kwarg chain as model_ref/settings_manager, and backend/agents.py's dispatch surfaces it as a warning notification naming both the provider that failed and the one substituted in. chat_stream's own fallback is additionally guarded so it can only fire before any real text has reached the caller - mirroring the existing "nothing forwarded yet" invariant the transport-retry layer already established, so a partially-delivered reply is never silently replayed against a different model. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-018 review-fix: llama.cpp basename identity + settings_manager recursion leak Two bugs surfaced by an adversarial review of the full 5-stage branch: - unified_catalog() stored llama.cpp scanned models as their full scanned path, but _provider_for_model_ref's llama.cpp branch only ever accepts a model_id matching the BASENAME of a configured path (the same convention describe_active_model already uses - llama.cpp has no "load any installed model by id" catalog the way Ollama does). Every auto-pick or fallback landing on a llama.cpp candidate was therefore unconditionally rejected. Fixed by reducing to Path(...).name at catalog-build time. - The "no model configured" auto-pick branches inside chat()/chat_stream() (now _chat_dispatch/_chat_stream_dispatch after 18.5's rename) recurse into the module-level chat()/chat_stream() names to dispatch the auto-picked ref - but that name now resolves to 18.5's own fallback wrapper, which had already popped settings_manager into a local before ever calling into the dispatch body, and the recursive call never re-included it. A failure on an auto-picked model (exactly the "nothing was configured" population FALLBACK_ENABLED_TASKS targets) could never trigger a further fallback attempt as a result. Fixed by re-including settings_manager in both recursive calls, in both functions. Adds regression tests for both (pure-function catalog shape, live dispatch through the real basename-matching path, and a live end-to-end trace through the previously-broken recursion). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
dovvnloading
added a commit
that referenced
this pull request
Aug 9, 2026
Recipes are data (the ADR's decision #4): named plans - goal, step titles, default mode - that seed a build. The settings store gains get_recipes/set_recipes (the get_mcp_servers posture exactly: JSON-safe dicts, shared normalization so a round trip is always well-formed, malformed entries dropped, whole-list replace). Two built-ins ship as constants in backend/builder.py, merged read-only at list time so a rename never desyncs a user's file. builder/start gains an optional recipe argument: a recipe-seeded plan lands its checklist immediately at awaiting_start with NO planning model call (proven: the planner is monkeypatched to fail loudly and is never reached). builder/listRecipes (request/reply) and builder/saveRecipe complete the loop - save-your-build captures a terminal plan node's goal + step titles (statuses deliberately dropped: a recipe is the plan, not this run's history), refuses built-in names, and replaces same-named user recipes. Classification gate 151 -> 153. Launcher: a recipe picker (built-ins labeled) that enables launch without a typed goal and relabels the action "Start from recipe"; PlanNodeView offers "Save as recipe" on done builds. The 8.6 exit criterion is covered both ways in test_builder.py: a shipped recipe and a user-saved build each seed a run through the real WS intents. Full backend suite: 2378 passed (the 5 pre-existing test_native_dialogs.py environment failures are untouched by this branch); full frontend check green (1618 tests, bundle gate OK). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dovvnloading
added a commit
that referenced
this pull request
Aug 10, 2026
* ADR-017 stage 17.1: knowledge store schema, chunking, and ingestion pipeline Adds the local SQLite knowledge store (documents/chunks, WAL mode, corrupt-db rescue, backup cadence - mirrors chat_library.py's own connection hygiene), structure-aware token-budgeted chunking with offset-exact citation support, and an extract -> chunk -> store ingestion pipeline that reuses attachments.py's pdf/docx/text extraction plus a new markup-stripping HTML extractor. Ingestion is idempotent by content hash, scoped per collection. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-017 stage 17.2: FTS5 lexical index and knowledge.search tool Adds an FTS5 external-content index over chunks.text (insert/delete triggers keep it in sync, migration backfills pre-existing rows), a bm25-ranked search_chunks() with safe query sanitization against FTS5 operator syntax, and registers knowledge.search on ToolRegistry under a new knowledge.read scope - auto-approval, read-only. Tested via direct registry.invoke() calls: ADR-008's tool-use loop (the piece that offers tools to a live model and processes ToolCallEvents) is not built yet, so this tool is registered and fully working but not yet wired into a live conversation - matching ADR-007's own established precedent for capabilities built ahead of their eventual caller. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-017 stage 17.3: Provider.embed(), embedding cache, and vector search Adds an `embedding` capability to ProviderCapabilities and a concrete .embed() method on OllamaProvider (per-model probe via ollama.show(), mirroring ollama_supports_tools) and OpenAIProvider (client-derived, mirroring image_generation) - the local-first-default-plus-API-option pair ADR-017 names. Anthropic/Gemini/llama.cpp declare embedding=False for this stage. The embeddings table (chunk_id, model_id) migration adds the vector index; knowledge_embeddings.py owns the numpy pack/unpack and provider calls: embed_pending_chunks() only ever embeds chunks with no cached vector for that model (the exit criterion's "cache prevents re-embedding"), and vector_search() is a brute-force cosine-similarity scan (numpy, already a dependency - no sqlite-vec or new pip package) matching the ADR's own "flat index file" alternative. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-017 stage 17.4: hybrid retrieval fusion, budget-aware selection, untrusted context Adds backend/knowledge_retrieval.py: reciprocal_rank_fusion() merges FTS5 and vector search by rank (never by raw score - bm25 and cosine similarity aren't comparable scales), hybrid_search() runs both and fuses when an embedding-capable provider/model is supplied, degrading gracefully to lexical-only otherwise. select_within_budget() greedily trims a ranked result list to a token allowance instead of a fixed k, so retrieval can never overflow a small local model's context window. format_untrusted_ context() builds the labeled, instruction-resistant evidence block for automatic chat-turn augmentation, reusing Web Research's own established spotlighting convention with a distinct [k...] citation marker. knowledge.search (stage 17.2's tool) now runs hybrid_search() when an embedding provider/model is registered, unchanged (lexical-only) otherwise. search_chunks()/vector_search() now also return each chunk's token_count so budget-aware selection needs no second round-trip. Fixture-set test proves the exit criterion directly: a query that only lexical search answers, a paraphrase that only vector search answers, both correctly resolved by hybrid_search() where either index alone misses one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-017 stage 17.5: sources (attachments/web-research/branch indexing) + citations UI Backend: - knowledge_ingest.ingest_text(): a sibling to ingest_file() for already- in-memory text with no file path to extract from - web-research retention and branch indexing both need this, not extract_text()'s file dispatch. - Web Research retention: WebResearchRequest.retain_to_knowledge (opt-in, default False) makes WebResearchService.run() ingest each accepted source document via ingest_text() after synthesis - a retention failure is logged and swallowed, never breaks the actual research result. - Branch indexing: ChatState.index_into_knowledge (per-node opt-in, set on whichever node's branch history should be indexed) + SceneDocument. set_chat_index_into_knowledge() + the new "knowledge" topic's two WS intents (backend/api/intents_knowledge.py): search (hybrid_search(), read-only, the frontend-reachable counterpart to backend/tools_knowledge. py's ADR-008-future tool) and setChatIndexIntoKnowledge (indexes the branch via chat_branch_history()+ingest_text() BEFORE flipping the flag, so a stored true always means the write actually happened). Frontend: a new "Knowledge" search panel (AppBar chip + Dialog, mirroring DiagnosticsDialog's request/reply shape) - search results render as "N sources used", each expandable to the exact cited excerpt (document[offsetStart:offsetEnd], byte-for-byte) with an Open source link for real http(s) sources. No fabricated "jump to this local file at a byte offset" mechanism - none exists anywhere in this codebase, so none is claimed here either; the excerpt itself IS the content at that offset. Contract: ChatState.index_into_knowledge -> indexIntoKnowledge (codegen regenerated). Guard updates: node-state-migration wire-key list, undo- classification intent count (143->145) + two new classifications. Verified live: real WS round-trip through the Knowledge panel against a freshly-started backend renders the correct empty-state UI with no console or server errors. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-017 review-fix: guard embedding batch/dim mismatches, fix search race A 5-dimension adversarial review of the ADR-017 diff surfaced 10 confirmed findings. This fixes the six safely-scoped ones: - embed_pending_chunks() now raises instead of silently mispairing vectors to chunk_ids when a provider returns a mismatched batch length. - vector_search() validates query-embedding count and stored-vector dimension before np.stack(), turning a would-be opaque numpy crash into a clear, diagnosable error. - KnowledgeSearchDialog's search request had no in-flight guard: the Enter-key handler could fire a second request while the first was still pending, and an out-of-order response would silently overwrite fresher results. A sequence token now discards stale responses, and the guard makes a second Enter press during an active search a no-op. - The search input now has an aria-label, matching every other search input in the app. - Both knowledge WS intent handlers (search, setChatIndexIntoKnowledge) now run their blocking SQLite calls via asyncio.to_thread instead of inline on the event loop, matching every other blocking-I/O intent handler in the codebase. The remaining four findings are real but out of scope for a review-fix pass and are documented as known gaps in the (local, gitignored) ADR-017 doc: OpenAIProvider's client-derived (not model-derived) embedding capability check, the Ollama capability cache's pre-existing permanent-negative-caching behavior, the WS search intent being lexical-only in production pending a model-selection surface for embeddings, and format_untrusted_context's lack of escaping (dormant, matches Web Research's own already-shipped precedent). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.1: graph-mutation tools, tool-turn primitive, run_id stamping The graph becomes a tool surface (the ADR's decision #1). Three pieces: - api_provider.chat_turn_with_tools(): one model turn that RETURNS tool calls instead of dropping them - the exact gap ADR-007 left (the streaming dispatch loop never set ChatRequest.tools and silently discarded tool_call events). Mirrors _chat_stream_dispatch's provider construction, model_ref precedence, transport retry, and error translation; gates tools-capability authoritatively at construction; collects tool calls + final text + usage. No 18.5 fallback wrapper - a mid-build silent model swap is what ADR-018 rules out. - backend/tools_graph.py: graph.create_node / graph.connect / graph.set_node_content (scope graph.mutate, approval "once") and graph.read_subgraph (graph.read, auto). Every mutating handler drives the same domain factories the WS intents call, wrapped in the same record_command - an agent-created node is undoable, patch-published, and persisted exactly like a user-created one. Placement is parent-relative and model-free; read results are excerpt-capped so reads don't eat the build's own token budget. - run_id stamping: record_command() and composite() accept a run_id kwarg (Command.run_id existed since ADR-010 stage 10.5 but nothing in production ever assigned it). Handlers read run_id off the RunContext, per-call rather than via a long-open composite - the composite buffer is document-global, so holding one across an approval await would swallow concurrent user commands into the builder's undo entry. Stage exit criterion covered in backend/tests/test_tools_graph.py: a scripted agent turn through the real primitive and real registry creates and connects two nodes, approval-gated (three prompts observed), and the whole turn reverts as one undo_run while the user's own node survives. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.2: run_node - a node's own action as a builder tool run_node(node_id, action?) executes a node's action INLINE under the builder's run - deliberately not re-entering the fire-and-forget AgentDispatcher surfaces (own busy kinds, intent-wired callbacks, no awaitable completion). Actions: - execute (pycoder default): runs the node's current code in the SAME REPL a manual Run uses (dispatcher.get_pycoder_repl), under the same 240 s timeout, landing results through the same complete_pycoder_run / fail_pycoder_run domain methods - the node renders identically to a manual run. No analysis turn: the builder model is the analyst; it reads the output in this same loop. - reply (chat default): generates an assistant reply child from the node's branch history via _call_chat_agent, with branch System-Prompt resolution and provider/model provenance stamped, recorded as a run_id-stamped command. - chart (explicit, on any content node): chart generation is an action ON a source node, not a node kind's own run - dispatching purely on kind would let the chat action shadow it, which the first test run caught. Generates via _call_chart_agent into add_chart_node. Scope enforcement is dynamic per action (execute -> code.execute, reply/chart -> provider.call) inside the handler - the ADR's "run_node additionally carries the scope of what it runs" - since the registry's own scope check is static per-tool. The target node carries the builder's request_id as pending_request_id for the run's duration: per-node conflict guards, the live-run undo refusal, and the spinner UI all come free. web_research runs are a named not-yet error until the network-gating stage. ToolRegistry.invoke now re-raises RequestCancelledError from HANDLERS instead of swallowing it into an error ToolResult - a long-running handler observing the same cancel event must follow the same contract as invoke's own checkpoints (cancellation propagates to the loop, never fed back to the model as a tool "error" to reason about). Stage exit criterion covered in backend/tests/test_run_node_tool.py: the scripted agent turn runs a code node for real (fake REPL) and the tool result it reads back carries the execution output. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.3 (backend): plan node kind + the Builder loop The plan node - the ADR's "planning is explicit and visible" decision - lands end-to-end: PlanState (goal/steps/status machine/budgets/spent counters/approval surface, all plan_-/builder_-prefixed so the bare-attribute ban needs zero exemptions), add_plan_node/set_plan_steps domain mutators (completed steps are immutable history - neither a user edit nor a model replan can rewrite them), 15 wire fields + a typed PlanStepRow (codegen regenerated), session save/load with the one load-time normalization: a non-terminal builder_status restores as "interrupted" - terminal, honest, resumable - since no RunHandle survives a restart. backend/builder.py is the loop itself: planning via respond_json (provider-universal, works where the executor's tools-capable gate would refuse), then per pending step a bounded turn loop alternating chat_turn_with_tools with registry invocations. Loop control is in-band through four auto-approval builder.* tools (complete_step / replan / finish_build / abort) - a per-step turn cap stops a step that never completes. Budgets are hard: tokens/wall-clock checked before every turn and every tool call, the step budget at the outer pre-start point (spent_steps increments at step START, so an in-flight step must not trip its own check - caught by this stage's own test). A breach pauses with all state on the plan node; resume is canvas-sourced. The approval router is mode-aware: copilot parks every non-auto call on the run's approval_future (the pycoder swap-per-round mechanics) behind plan-node awaiting/summary fields; autopilot auto-approves calls whose registered scopes fit the disclosed set and still prompts for net.fetch. ToolRegistry gains scopes_for() so the router keys on registration truth. AgentDispatcher.start_builder_run claims the new "builder" kind (Stop = release-on-cancel + finalize landing "stopped", the 6.2 posture) and lazily builds the session's ToolRegistry - ADR-007's registry finally gets its first production constructor. Six new intents (builder/start| startExecution|cancel|approveTool|denyTool + scene/setPlanSteps), classified, gate 145 -> 151; builder/start is A - it genuinely records the plan-node creation, stamped post-claim with the run id so undo_run reverts the plan node too. Planner/executor prompts join the pinned registry inventory (terse by design - every token recurs per turn; the executor carries the untrusted-content spotlighting language). Stage exit criterion covered in backend/tests/test_builder.py: a scripted co-pilot build lands a 4-node branch with every mutating call individually approved, control tools never prompting, budgets/replan/ abort/deny paths each proven, Stop verified as slot-release-immediate, and the whole build reverting via one undo_run. Mid-step replan keeping the running step live (and the loop re-resolving it from the replaced list) was a real bug this suite caught before it shipped. Frontend (PlanNodeView + launcher) follows in the next commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.3 (frontend): PlanNodeView + Builder launcher PlanNodeView renders the build live off the wire row: goal, the checklist with per-status markers and step summaries, the three budget gauges (spent/max steps, tokens, seconds), status + detail (failed details are role=alert), the autopilot chip, and mode-appropriate controls - Start build / Resume for awaiting_start|paused|interrupted, Stop while running. The tool-approval panel copies CodeExecutionApprovalPanel's architecture: per-node, zero passive dismissal (a dismissal would strand the run's parked approval future), and zero-argument Approve/Deny closed over the current snapshot's pendingRequestId. BuilderLaunchDialog (AppBar, next to Knowledge) collects goal, oversight mode, and the three hard budgets, and starts the build through the value-returning builder/start intent - selecting autopilot surfaces the disclosure sentence inline before launch (per-run, disclosed choice per the ADR). Six new sceneStore methods wire the run controls. Fixture ripple: the 15 new required wire fields land in the five SceneNodeRow fixture builders (the 17.5 indexIntoKnowledge precedent). Styling uses only the design-system variables - the no-raw-colors gate caught the first draft's hex fallbacks. Verified: 10 new component tests; full frontend check green (1612 tests, typecheck, lint, build, bundle gate); full backend suite green (2364 passed; the 5 pre-existing test_native_dialogs.py environment failures are untouched by this branch). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.4: the Undo build affordance "Undo this build" closes the loop ADR-010 stage 10.5 left open: the undo_run machinery and the scene/undoRun intent shipped with zero callers, and stage 8.1 made the builder stamp every command with its run id - this adds the affordance. PlanNodeView offers an "Undo build" button once the run is over (done/failed/stopped/interrupted/paused, with a stamped run id), wired through the existing sceneStore.undoRun. The domain's live-run guard already refuses undo mid-run, so Stop-then-undo remains the enforced sequence with no new code. Live browser verification caught a real bug: the plan node's buttons lacked the `nodrag` class, so React Flow's drag handler swallowed every click (the ChatNodeView-pinned convention). Fixed on all five buttons and pinned by a new test. Verified end-to-end in the running app: a build launched from the AppBar dialog landed a plan node (with the Ollama-unreachable failure surfacing honestly as role=alert), and Undo build reverted the run-stamped creation. The stage's revert-the-whole-build exit criterion is covered by test_builder.py's exit test (undo_run reverts a 4-node scripted build, the user's own node surviving). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.5: research via run_node, autopilot net gate, MCP wiring run_node gains the "research" action (web_research's default): the SAME sync pipeline the dedicated surface runs - WebResearchService with all of ADR-004's SSRF/IP-pinning/robots machinery inside its fetcher - landing through the same complete/fail domain methods, inline under the builder's run. The builder's threading.Event cancel bridges onto the service's own CancellationToken via a watcher task (the pipeline stages checkpoint on the token, not our event) - proven by a test that hits Stop mid-run and watches the token trip. Designing it surfaced a real autopilot hole: the mode router keyed auto-approval on a tool's REGISTERED scope, and run_node registers only graph.read - autopilot would have silently auto-approved a net.fetch research run. run_node_effective_scope() now derives the scope a call actually exercises (target kind + action) and the router unions it in; malformed run_node calls route to the human. Two tests pin the exit criterion's "no network unless approved": a net.fetch tool prompts in autopilot, and run_node(research) prompts via the derived scope while graph mutations still auto-approve. ADR-007's deferred MCP runtime wiring lands in its designated consumer: builder_tool_registry reads the persisted server list, connects each enabled server, and registers its tools (namespaced, per-server scopes, approval="always") with per-server failure tolerance - one broken config never costs the Builder its graph tools. The interrupted-on-load normalization (shipped in 8.3's restorer) gets its round-trip tests: a "running" build restores as interrupted with its mid-flight step failed - never a spinner no run backs - while terminal states and spent budgets round-trip verbatim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 stage 8.6: recipes and save-your-build Recipes are data (the ADR's decision #4): named plans - goal, step titles, default mode - that seed a build. The settings store gains get_recipes/set_recipes (the get_mcp_servers posture exactly: JSON-safe dicts, shared normalization so a round trip is always well-formed, malformed entries dropped, whole-list replace). Two built-ins ship as constants in backend/builder.py, merged read-only at list time so a rename never desyncs a user's file. builder/start gains an optional recipe argument: a recipe-seeded plan lands its checklist immediately at awaiting_start with NO planning model call (proven: the planner is monkeypatched to fail loudly and is never reached). builder/listRecipes (request/reply) and builder/saveRecipe complete the loop - save-your-build captures a terminal plan node's goal + step titles (statuses deliberately dropped: a recipe is the plan, not this run's history), refuses built-in names, and replaces same-named user recipes. Classification gate 151 -> 153. Launcher: a recipe picker (built-ins labeled) that enables launch without a typed goal and relabels the action "Start from recipe"; PlanNodeView offers "Save as recipe" on done builds. The 8.6 exit criterion is covered both ways in test_builder.py: a shipped recipe and a user-saved build each seed a run through the real WS intents. Full backend suite: 2378 passed (the 5 pre-existing test_native_dialogs.py environment failures are untouched by this branch); full frontend check green (1618 tests, bundle gate OK). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ADR-008 review-fix: close autopilot scope gap, fix budget/replan bugs, canonicalize chart data Fixes 13 bugs found by re-reading the branch's own diff after an adversarial review pass: autopilot treated an empty MCP tool scope set as auto-approved (any unscoped server bypassed human approval entirely); Ollama/Anthropic/ Gemini all dropped already-collected token usage on tool-call turns, so the builder's token budget went effectively unenforced; a second plan replan could mint a step id that collided with one an earlier replan already used, killing the build with an unresumable error; a watchdog timeout or any other provider exception left the in-flight step wedged at "running" forever, and "failed" was not a resumable status even though the plan node's state lives entirely on the canvas; a budget breach discovered on a later tool call in a turn could stomp a step an earlier call in that same turn had just completed, or silently drop a declared finish; graph.read_subgraph had no cap on node count, so a hub node's full read could overflow a turn's context window; a transient Ollama capability-probe failure was cached as a permanent negative, silently blocking the builder forever with a false "no tool support" error; the run_node schema still advertised research as unsupported; the web research service's own cancellation exception was swallowed into an ordinary tool error instead of propagating as a real cancellation; chart generation skipped canonicalize_chart_data before storing the model's raw output, violating the chart state's documented invariant; deleting a plan node with a live builder run never cancelled it, permanently locking the builder for the rest of the session; and undo/redo of a plan-node command recorded mid-run could resurrect a stale "running"/"awaiting_approval" status with no live run behind it. Also splits register_node_intents's live-run teardown capture into its own function to stay under the register* 300-line cap after the new plan-cancel branch pushed it over. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps anchore/sbom-action from 0.9.0 to 0.24.0.
Release notes
Sourced from anchore/sbom-action's releases.
... (truncated)
Commits
e22c389chore(deps): update Syft to v1.42.3 (#615)36a5fdechore: update to node 24 + deps (#614)a0a6512chore(deps): bump actions/setup-node from 6.2.0 to 6.3.0 (#608)57aae52chore(deps): update Syft to v1.42.2 (#607)c29e913chore(deps): bump fast-xml-parser and other deps (#604)17ae174chore(deps/test): move to es modules, node:test, single dist file (#595)6d473d3chore(deps): update Syft to v1.42.1 (#599)60619e7fix tests and bump fast-xml-parser (#598)e2bd58achore(deps-dev): bump the dev-dependencies group with 3 updates (#592)d032d7dci(syft auto update): npm ci, not npm install (#597)