Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/strict-scalar-tool-envelope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ignite-element": patch
---

Tighten igniteTools scalar provider envelopes by publishing `additionalProperties: false` on scalar wrappers and rejecting malformed `{ value, ...extra }` provider inputs as `InvalidInput`.
20 changes: 13 additions & 7 deletions .fas/TASKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1562,7 +1562,7 @@ No active tasks.

- Title: collapse ignite ActorWebAddress tolerant union to pure string once @actor-web/runtime publishes the opaque branded addre
- Mode: single-agent
- Status: queued
- Status: deferred
- Owner: runtime
- Brief: .fas/tasks/collapse-ignite-actorwebaddress-tolerant-union-to-pure-strin.md
- Automation mode: advisory
Expand All @@ -1571,9 +1571,12 @@ No active tasks.

- Title: update ActorWebAdapter dev-warning wording that still references the removed commandSource config concept after the beta
- Mode: single-agent
- Status: queued
- Owner: runtime
- Status: done
- Owner: implementer
- Brief: .fas/tasks/update-actorwebadapter-dev-warning-wording-that-still-refere.md
- Verification lane: fast
- Policy sensitivity: standard
- Blast radius: cross-cutting

### Task: add an observe() observation channel to the neutral igniteTools core (events + view stream) for the agent act-observe lo

Expand Down Expand Up @@ -1638,19 +1641,22 @@ No active tasks.

- Title: Split the agent-runtime host type (EventTarget) from the render-host Host generic so the headless runtime needs no HTMLE
- Mode: single-agent
- Status: queued
- Owner: runtime
- Status: done
- Owner: implementer
- Brief: .fas/tasks/split-the-agent-runtime-host-type-eventtarget-from-the-rende.md
- Automation mode: advisory

### Task: igniteTools PR2 CodeRabbit follow-ups — bind runtime.execute, strict scalar value envelope, fix canExecute doc wording

- Title: igniteTools PR2 CodeRabbit follow-ups — bind runtime.execute, strict scalar value envelope, fix canExecute doc wording
- Mode: single-agent
- Status: queued
- Owner: runtime
- Status: done
- Owner: implementer
- Brief: .fas/tasks/ignitetools-pr2-coderabbit-follow-ups-bind-runtime-execute-s.md
- Automation mode: advisory
- Verification lane: fast
- Policy sensitivity: standard
- Blast radius: cross-cutting

### Task: Fix example runtime test lanes before next igniteTools task

Expand Down
150 changes: 73 additions & 77 deletions .fas/queue/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
"taskClassification": "self-improvement",
"selfImprovementCategory": "developer-experience",
"signalFingerprint": null,
"status": "deferred",
"status": "queued",
"owner": "runtime",
"mode": "single-agent",
"dependsOn": [
Expand All @@ -202,7 +202,7 @@
"prDependencies": [],
"createdAt": "2026-06-18T17:54:24.107Z",
"updatedAt": "2026-06-20T07:07:22.721Z",
"deferredReason": "dependency_reopened: task-1782269414711",
"deferredReason": null,
"invalidationReason": null
},
{
Expand Down Expand Up @@ -403,81 +403,8 @@
"branchBase": null,
"prDependencies": [],
"createdAt": "2026-06-24T02:49:56.312Z",
"updatedAt": "2026-06-24T02:49:56.312Z",
"deferredReason": "dependency_reopened: task-1782499305182",
"invalidationReason": null
},
{
"id": "task-1782269414711",
"task": "update ActorWebAdapter dev-warning wording that still references the removed commandSource config concept after the beta",
"priority": "low",
"source": "manual",
"details": "After commandSource was removed (PR #67), these messages still say 'commandSource' which no longer exists in the public API: failInvariant 'Actor-Web commandSource is required.' at packages/ignite-adapters/src/adapters/ActorWebAdapter.ts ~289 and ~327 (resolveCommandActor), and the send() console.warn 'Cannot send events without an Actor-Web commandSource.' ~468. Reword to reference 'a command-capable source (one that exposes send())'. Internal dev warnings only; behavior unchanged. Nit deferred from PR #67 babysit to avoid churning a green PR.\nSee .fas/tasks/update-actorwebadapter-dev-warning-wording-that-still-refere.md",
"taskClassification": "standard",
"selfImprovementCategory": null,
"signalFingerprint": null,
"status": "deferred",
"owner": "runtime",
"mode": "single-agent",
"dependsOn": [
"task-1782269396312"
],
"blocks": [
"task-1781805264107"
],
"branchBase": null,
"prDependencies": [],
"createdAt": "2026-06-24T02:50:14.711Z",
"updatedAt": "2026-06-24T02:50:14.711Z",
"deferredReason": "dependency_reopened: task-1782269396312",
"invalidationReason": null
},
{
"id": "task-1782499303572",
"task": "Split the agent-runtime host type (EventTarget) from the render-host Host generic so the headless runtime needs no HTMLE",
"priority": "medium",
"source": "manual",
"details": "Phase A made the headless runtime DOM-free via createRuntimeHost returning a bare EventTarget cast to HTMLElement (IgniteElementFactory.ts). The cast is forced because the runtime host shares the render path's Host generic (typed HTMLElement for the JSX renderer host.appendChild). The agent runtime only uses host as an EventTarget (on() add/removeEventListener; effect emits via dispatchEvent) — verified no element-only API usage on the runtime host. Properly split the runtime-host type (EventTarget) from the render-host Host generic (HTMLElement) across createComponentFactory/createProjectionFactory/agent.ts so createRuntimeHost returns EventTarget honestly and the cast disappears. Found by CodeRabbit on the Phase A PR (major, accepted-with-justification + this follow-up).\nSee .fas/tasks/split-the-agent-runtime-host-type-eventtarget-from-the-rende.md",
"taskClassification": "self-improvement",
"selfImprovementCategory": "runtime-reliability",
"signalFingerprint": null,
"status": "queued",
"owner": "runtime",
"mode": "single-agent",
"dependsOn": [
"task-1782494866385"
],
"blocks": [
"task-1782499305182"
],
"branchBase": null,
"prDependencies": [],
"createdAt": "2026-06-26T18:41:43.572Z",
"updatedAt": "2026-06-26T18:41:43.572Z"
},
{
"id": "task-1782499305182",
"task": "igniteTools PR2 CodeRabbit follow-ups — bind runtime.execute, strict scalar value envelope, fix canExecute doc wording",
"priority": "medium",
"source": "manual",
"details": "Three CodeRabbit findings on shipped PR2 code, out of the Phase A (DOM-free) scope. (1) igniteTools.ts: const execute = runtime.execute is unbound — bind it via runtime.execute.bind(runtime) like canExecute already is, else an execute that relies on this breaks when run() calls it; the current fake runtime uses an arrow so the gap is uncovered — add a class/this-based fake runtime regression test. (2) tools/scalar.ts: the scalar value envelope is not strict — { value: 7, extra: true } unwraps to 7, bypassing resolveCall validation; add additionalProperties:false on encode (toProviderInputSchema) and reject extra keys on decode (fromProviderInput) so a malformed provider envelope surfaces InvalidInput; add tests. (3) docs/ignite-tools.md: the observation note overpromises that canExecute re-gates the tool list as state changes, but igniteTools snapshots the manifest once — reword to say rebuild igniteTools() (or re-derive tools) to publish a fresh canExecute-gated manifest.\nSee .fas/tasks/ignitetools-pr2-coderabbit-follow-ups-bind-runtime-execute-s.md",
"taskClassification": "self-improvement",
"selfImprovementCategory": "runtime-reliability",
"signalFingerprint": null,
"status": "deferred",
"owner": "runtime",
"mode": "single-agent",
"dependsOn": [
"task-1782499303572"
],
"blocks": [
"task-1782269396312"
],
"branchBase": null,
"prDependencies": [],
"createdAt": "2026-06-26T18:41:45.182Z",
"updatedAt": "2026-06-26T18:41:45.182Z",
"deferredReason": "dependency_reopened: task-1782499303572",
"updatedAt": "2026-07-03T17:13:42.000Z",
"deferredReason": "blocked-until-actor-web-runtime-branded-address: current @actor-web/runtime resolves to 0.1.0, which still uses the legacy object address",
"invalidationReason": null
}
],
Expand Down Expand Up @@ -2784,6 +2711,75 @@
"workflowId": "direct-1783093106382",
"branchName": "fas/ignite-ecosystem-bridge",
"prStatus": "draft-only"
},
{
"id": "task-1782499303572",
"task": "Split the agent-runtime host type (EventTarget) from the render-host Host generic so the headless runtime needs no HTMLE",
"priority": "medium",
"source": "manual",
"taskClassification": "self-improvement",
"selfImprovementCategory": "runtime-reliability",
"signalFingerprint": null,
"dependsOn": [
"task-1782494866385"
],
"blocks": [
"task-1782499305182"
],
"branchBase": null,
"prDependencies": [],
"prRef": null,
"completedAt": "2026-07-03T17:03:43.953Z",
"terminalOutcome": null,
"workflowId": "direct-1783097767418",
"branchName": "fas/ignite-ecosystem-followups",
"prStatus": "draft-only"
},
{
"id": "task-1782499305182",
"task": "igniteTools PR2 CodeRabbit follow-ups — bind runtime.execute, strict scalar value envelope, fix canExecute doc wording",
"priority": "medium",
"source": "manual",
"taskClassification": "self-improvement",
"selfImprovementCategory": "runtime-reliability",
"signalFingerprint": null,
"dependsOn": [
"task-1782499303572"
],
"blocks": [
"task-1782269396312"
],
"branchBase": null,
"prDependencies": [],
"prRef": null,
"completedAt": "2026-07-03T17:25:38.445Z",
"terminalOutcome": null,
"workflowId": "direct-1783098275694",
"branchName": "fas/ignite-ecosystem-followups",
"prStatus": "draft-only"
},
{
"id": "task-1782269414711",
"task": "update ActorWebAdapter dev-warning wording that still references the removed commandSource config concept after the beta",
"priority": "low",
"source": "manual",
"taskClassification": "standard",
"selfImprovementCategory": null,
"signalFingerprint": null,
"dependsOn": [
"task-1782269396312"
],
"blocks": [
"task-1781805264107"
],
"branchBase": null,
"prDependencies": [],
"prRef": null,
"completedAt": "2026-07-03T17:18:57.748Z",
"terminalOutcome": null,
"workflowId": "direct-1783098943999",
"branchName": "fas/ignite-ecosystem-followups",
"prStatus": "draft-only"
}
],
"pullRequests": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ Drop the object branch + the TODO(actor-web > 0.1.0) comment in packages/ignite-
- Validate generated scope, acceptance criteria, and verification evidence before closeout to avoid workflow drift.

## Dependencies
- None known at task creation.
- Blocked until `@actor-web/runtime` publishes the branded string `ActorAddress`
and this repo bumps the installed/devDependency version. Current verification
on 2026-07-03 shows `@ignite-element/adapters` still resolves
`@actor-web/runtime@0.1.0`, which uses the legacy object address.

## Open questions
- None captured at task creation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,37 @@ Three CodeRabbit findings on shipped PR2 code, out of the Phase A (DOM-free) sco
- packages/ignite-element/src/tests/tools.test.ts
- packages/ignite-element/src/tests/tools.scalar.test.ts
- docs/ignite-tools.md
- .changeset/strict-scalar-tool-envelope.md
- packages/ignite-element/src/tests/tools.anthropic.test.ts

## Scope Amendments
- None.
- Type: implementation-scope
- Added at: 2026-07-03
- Trigger: strict scalar envelope requires package changeset and Anthropic golden fixture update
- Reason: Acceptance criteria require a changeset, and adding additionalProperties:false changes the provider-facing Anthropic schema fixture.
- Evidence source: closeout-readiness
- Evidence: closeout-readiness | .fas/state/closeout-readiness/latest.json
- Accuracy signal: live ChangeSet after focused tests
- Follow-up needed: none

- Type: implementation-scope
- Added at: 2026-07-03
- Trigger: strict scalar wrapper changed provider schema
- Reason: The package patch changeset is required by acceptance criteria, and the Anthropic golden test must reflect additionalProperties:false emitted by the shared scalar helper.
- Added paths: .changeset/strict-scalar-tool-envelope.md, packages/ignite-element/src/tests/tools.anthropic.test.ts
- Evidence source: focused-verification
- Evidence: focused-verification | .fas/state/verification/validate-task-1783098491.log
- Accuracy signal: focused tests and typecheck passed before scope refresh
- Follow-up needed: none

- Type: implementation-scope
- Added at: 2026-07-03
- Trigger: explicit affected-file amendment recorded
- Reason: Refresh generated planning and task packet after adding changeset and Anthropic fixture to the task scope.
- Evidence source: task-brief
- Evidence: task-brief | .fas/tasks/ignitetools-pr2-coderabbit-follow-ups-bind-runtime-execute-s.md
- Accuracy signal: affected files now match live ChangeSet
- Follow-up needed: none

## Implementation plan
- Convert the supplied context into a scoped implementation plan before editing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,27 @@ After commandSource was removed (PR #67), these messages still say 'commandSourc

## Affected files
- packages/ignite-adapters/src/adapters/ActorWebAdapter.ts
- packages/ignite-element/src/tests/adapters/ActorWebAdapter.test.ts

## Scope Amendments
- None.
- Type: test-scope
- Added at: 2026-07-03
- Trigger: warning wording needs runtime-facing regression coverage
- Reason: The adapter warning/error strings are exercised through the existing ignite-element ActorWebAdapter vitest suite.
- Added paths: packages/ignite-element/src/tests/adapters/ActorWebAdapter.test.ts
- Evidence source: focused-test
- Evidence: focused-test | packages/ignite-element/src/tests/adapters/ActorWebAdapter.test.ts
- Accuracy signal: focused test failed before implementation and passed after wording update
- Follow-up needed: none

- Type: test-scope
- Added at: 2026-07-03
- Trigger: explicit affected test path recorded
- Reason: Refresh generated planning and task packet after adding ActorWebAdapter.test.ts to task scope.
- Evidence source: task-brief
- Evidence: task-brief | .fas/tasks/update-actorwebadapter-dev-warning-wording-that-still-refere.md
- Accuracy signal: affected files now match live ChangeSet
- Follow-up needed: none

## Implementation plan
- Convert the supplied context into a scoped implementation plan before editing.
Expand Down
23 changes: 14 additions & 9 deletions docs/ignite-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,16 @@ because that is the command's true contract (`getSchema()` must not lie). So the
wrap/unwrap lives only at the provider boundary, in shared pure helpers
(`tools/scalar.ts`):

- `toProviderInputSchema(schema)` — wraps a scalar under a clean `value` key
(`{ type: "object", properties: { value: schema }, required: ["value"] }`);
object/no-arg schemas pass through unchanged. Adapters call it in `tools()`.
- `fromProviderInput(input, schema)` — unwraps the model's `{ value: x }` back to
`x`, **gated on the manifest schema being scalar** (collision-free: an object
command that legitimately has its own `value` field is never unwrapped).
Adapters call it in `toolCalls()`, which is why the port hands `toolCalls` the
manifest.
- `toProviderInputSchema(schema)` — wraps a scalar under a clean, strict `value`
key (`{ type: "object", properties: { value: schema }, required: ["value"],
additionalProperties: false }`); object/no-arg schemas pass through unchanged.
Adapters call it in `tools()`.
- `fromProviderInput(input, schema)` — unwraps the model's exact `{ value: x }`
back to `x`, **gated on the manifest schema being scalar** (collision-free: an
object command that legitimately has its own `value` field is never unwrapped).
Extra keys keep the provider object intact so `resolveCall` reports
`InvalidInput`. Adapters call it in `toolCalls()`, which is why the port hands
`toolCalls` the manifest.

The constraint is universal across providers, so it is fixed once in the port +
two helpers; the OpenAI/Ollama dialect reuses them verbatim.
Expand Down Expand Up @@ -216,7 +218,10 @@ to the provider's `tool_result` (`is_error: true`) so the model can recover.

- **typed-view** ✓ + **`getSchema().view`** ✓ (done) — typed manifest inputs + view grounding.
- **`canExecute`** (`docs/can-execute.md`) — composes for availability-gated tools
by omitting unavailable commands from the manifest. Older runtimes without the
by omitting unavailable commands when `igniteTools(runtime)` builds the manifest
and by re-checking availability when `run()` routes a call. To publish a fresh
provider tool list after state changes, rebuild `igniteTools(runtime)` or
re-derive provider tools from a fresh manifest. Older runtimes without the
optional method still offer all commands for compatibility.

## Alternatives considered
Expand Down
10 changes: 7 additions & 3 deletions packages/ignite-adapters/src/adapters/ActorWebAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,9 @@ function createSharedFactory<
factory.resolveStateSnapshot = () => entry.snapshot();
factory.resolveCommandActor = () =>
entry.actor ??
failInvariant("[ActorWebAdapter] Actor-Web commandSource is required.");
failInvariant(
"[ActorWebAdapter] Actor-Web command-capable source (one that exposes send()) is required.",
);
return factory;
}

Expand Down Expand Up @@ -324,7 +326,9 @@ function createIsolatedFactory<
adapter,
"[ActorWebAdapter] Unable to resolve actor for facade callbacks.",
).actor ??
failInvariant("[ActorWebAdapter] Actor-Web commandSource is required.")
failInvariant(
"[ActorWebAdapter] Actor-Web command-capable source (one that exposes send()) is required.",
)
);
};

Expand Down Expand Up @@ -465,7 +469,7 @@ function createAdapterEntry<

if (!commandSource) {
console.warn(
"[ActorWebAdapter] Cannot send events without an Actor-Web commandSource.",
"[ActorWebAdapter] Cannot send events without an Actor-Web command-capable source (one that exposes send()).",
);
return;
}
Expand Down
Loading
Loading