Skip to content

Releases: passioncode-ai/fabric-agent-adapter

v0.57.0: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 28 Oct 10:33
d34fd46

The contract pin moves to 3830a33 (v0.1.0+2026-10-27.6) from 00e050ba (FAA-176).

Added

  • comparison as a human step (DEC-0142, contract CT-186). humanStep in an action declaration may be
    comparison: the person compares two codes shown on two screens, or chooses to share without a comparison. Both
    kits' action-declaration checks take it (fabric_actions.py, fabric-actions.mjs, actions-vectors.json
    regenerated: 68 cases, 12 declarations), the probe passes a declaration that uses it, and interop.md, delegation.md
    and working-with-fabric's human gates (OA-5), which its refusal table cites, name it. A reader pinned before (a 0.56.0
    kit, Fabric Dashboards before 0.8.9) refuses such a declaration, which Project Observatory declares on its share
    buttons from OBS-264.
  • The protocol register gains the six peer-share revisions (DEC-0142, fabric-peer-share/1 and its parts) and
    org-adaptation/1 and org-adaptation-receipt/1 (DEC-0138) in both twins (feed-protocols-vectors.json), so a
    service's well-known that names one is read as a known revision.
  • The provider entry's manifest path (DEC-0145, CT-192): fabric_provider.py names the schema's
    MANIFEST_PATTERN, read as a search that ends at the string's end; the reader accepts the manifest's name after a
    backslash, the writer still writes it with / and refuses the other with a sentence naming CT-192, and the CLI's
    stem is read after either separator (CT-193). The contract's ten provider.schema.json fixtures are vendored
    (provider-fixtures.json) and tested in every run.

Changed

  • On Windows, fabric_provider.py's services_dir() (its FAC-SEM-013 check that an id is not a service's) and
    providers_dir() read %LOCALAPPDATA%\passioncode-fabric (provider.md), as the service kit's readers already did.
  • agents-that-answer-people.md (A5) names the contract's support-quality-daily.schema.json, says when a producer may
    carry calibration (CT-188) and that a reader validates against its own pinned copy (DEC-0144).
  • The hosted contract job runs test_provider, and test/validate.py fails a workflow whose contract job leaves out a
    module that holds a test gated on the contract.

Upgrading

  • A bundle pinned to 00e050ba or an earlier supported commit keeps working; adapt_project.py
    accepts it (SUPPORTED_CONTRACT_COMMITS). A new scaffold writes 3830a33.
  • DEC-0139 (the machines' report) and DEC-0138's organization server route reach no kit code: the adapter registers
    their protocol revisions and implements neither side. DEC-0143 (secret.prompt, the local channel) and DEC-0142's
    peer-share profile beyond its register entries reach no kit code either; Project Observatory implements them
    (CT-186).
  • On Windows, a provider entry written by fabric_provider.py now goes to the folder Fabric reads
    (%LOCALAPPDATA%\passioncode-fabric\providers). Fabric v0.3.15 and earlier read a manifest path only under ~/ or
    /; a drive letter (C:/.../fabric-agent.json) is read by the Fabric release after v0.3.15 (CO-479). Until then
    write the manifest path under ~/. An entry an older kit wrote on Windows sits in
    %USERPROFILE%\.local\share\passioncode-fabric\providers, which Fabric never read and remove no longer finds:
    write it again and delete the old file.

v0.56.0: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 28 Oct 09:00
250d5d7

Stability and Windows: the debts of 0.53.0 to 0.55.0 that touch how the hooks, the board responder and the interop
gate behave.

Fixed

  • The board responder's notices reach a service's event feed: they were sent at level warn, which
    JsonlEventLog.append refuses (its levels are info, notice, warning, error), so board.down,
    board.access.needed, board.slot.moved, board.slot.contested, board.request.held, board.request.skipped,
    board.reconcile.needed, board.attempt.lost and board.outcome.invalid were dropped wherever emit=log.append
    (the reference service included, since 0.28.0; board.slot.moved since 0.53.0). They are sent at warning now, in
    both twins, as is the new board.slot.refused (FAA-163). Each notice names its subject ({type, id}: its request,
    else its capability, else its episode, such as a block's cause, else the Project), so a host tells one request's,
    capability's or cause's episode from another's. In Python the subject goes to an emit whose signature names a
    subject parameter with no value bound (JsonlEventLog.append now names one); any other emit (only **kwargs, a
    subject bound with functools.partial, a signature that cannot be read) is called as 0.55.0 called it, once, without
    one. The Node responder always passes it in its options object, which an emit that does not read it ignores.
  • working-with-fabric on Windows (FAA-175, FAA-177). A turn names the repositories it touched on Windows too:
    Git Bash /c/... and /cygdrive/c/..., C:/... and quoted C:\... paths, and git.exe -C (any case); Bash
    text is split with Git Bash's own quoting, so an unquoted backslash is an escape there too. A cd inside ( ), a
    pipeline's stage or a list sent to the background no longer moves the folder a later relative -C is read
    against; a newline ends a command, a here-document's body is text (a # comment no longer hides its lines, and
    <<< opens none), &> only redirects, git -C /a -C b runs in /a/b, and pushd and a cd after { or then
    are read. Cygwin and MSYS Python read paths as POSIX. Before, the Stop hook did not read the
    transcript on Windows at all, and a turn from Windows came without repositories. The hooks run python3, which
    must name Python 3.9 or later in Git Bash there (session-hooks.md; FAA-183 makes the plugin find it itself).
  • A relative git -C after cd (FAA-166) is read against the folder the command last changed into with an
    absolute cd; after a relative or unknown cd it is dropped, never read against the session's folder.
  • The board responder's recovery (FAA-163, FAA-158). A refused enroll of one capability no longer stops the
    others: it is retried on its own, the pause doubling, and said once as board.slot.refused. A slot's move is written
    under the responder's lock and only while its record is unchanged, so an operator's take-back at the same moment
    wins. The slot code moved to its own twin modules, fabric_board_slots.py and fabric-board-slots.mjs.
  • An idle stop leaves the board within 3 s (FAA-173): a responder with no work in hand closes its session with a
    confirmed DELETE inside the hard exit (close(timeout): a timeout not above 0 is the session's own, and a session built
    with one takes 15 s, in both twins),
    instead of letting the slot lapse (a board call already in flight when the
    stop comes runs first, and when the join ends before the DELETE the slot lapses as before). The slot records are forgotten only after
    a 2xx: a 404 (the session already gone) keeps them, since a move made before it ended is read at the next
    com.status. A refusal of the whole board session (not_available included) is the board down, never a refused
    capability; a capability refused, or contested, again after it was held is said again, once per capability. A clean
    leave forgets only the records this session confirmed (a slot it held, paused under the operator's hold included, or
    one com.status showed unmoved) and no fenced call has put in doubt since, so a slot moved while the service was
    down stays moved when the session is dropped at connect or recovery stops early, and is never enrolled again on
    its own. A paused or retrying slot reads com.status before each new ask, so a move during the operator's hold is
    said. Checkpoint.leave(project, held) takes held as a required argument in both twins.
  • action_gate fails closed (FAA-139): a spend that is not a finite number is read as no estimate, which a
    mandate's perCallMaxUsd ceiling refuses (a mandate with no ceiling covers it; the question is with the contract,
    FAA-185), and a project that cannot be read is never covered by a mandate limited to projects. A null mandate in
    _meta reads as an unreadable one, not as none (FAA-178; Python's approval_step, while a Node service passes {}
    to jobStep itself, interop.md). A job's start (job_step) reads spend and project as its answer does, and keeps
    the spend as it read it (a NaN is no estimate, never a bare NaN in the job file).
  • fabric_secrets matches the contract's ECMAScript reading (FAA-136): \s, . and case folding as JavaScript
    reads them, so both ports flag the same values. secret_url also reads a special scheme as new URL does: every
    slash or backslash after https: (or http, ftp, ws, wss) is skipped and a backslash before the query reads
    as a slash, so https:u:p@host and https:\\u:p@host carry a password in Python as in Node. Python splits the URL
    by hand rather than with urlsplit, which refuses a [ or ] outside an IPv6 host (https://u:p[w@h/), and drops
    one leading ? from a parameter's name as URLSearchParams does. Where new URL refuses a host (none, a port over
    65535), Python still reads the password and the parameters, so it can flag more than Node, never less. The
    source.repository check of a descriptor and of a provider entry reads a special scheme's password the same way
    (https:bot:pw@host), up to the user information's last @ (https://me@corp.example:pw@host), and says so
    before it judges the host. The query and the fragment are read percent-encoded, as new URL hands them over.
    fabric_http.redact_url reads a special scheme the same way (below).
  • What the kit sends, refuses and redacts as a URL (FAA-136; the remaining differences are FAA-187):
    • redact_url: the URL an HttpError carries for https:u:pw@host has no password, as in Node; a URL of any
      other scheme (a misspelled htps: included) keeps only its scheme in both twins (htps:<redacted>), since its
      user information may sit anywhere in the rest. It first trims C0 controls and space from the ends and removes
      tabs and line breaks, as new URL does, so https://u:pw@host keeps no password on Python 3.9 either. A
      string with no scheme (ht tps:, 1ttps:, a leading byte order mark or no-break space) and a URL whose host or
      port new URL refuses (a password holding /, a port that is not ASCII digits such as 1_2 or +1, which
      Python 3.9's int() takes, a bracketed host that is no IPv6 address, a ws, wss or ftp URL with no host or
      a port above 65535) read as <unparseable url>; the scheme is read by the WHATWG rule, not by urlsplit, whose
      rule differs between 3.9 patch releases. On Python a host holding % reads as <unparseable url> too, where
      Node writes it decoded. The path is not redacted in either twin (Node writes it as new URL normalises it,
      Python as given), so a key never belongs in it.
    • check_url and request: the same ports and bracketed hosts (an IPv6 zone included) are refused. On Python a
      backslash, %, space or control character in the host (a Unicode space and a C1 control included) is refused
      too, since urllib would decode it or dial another host (h.example%3A8443 reached port 8443), and so is a space
      or ASCII control character before the URL's first #, or a character outside ASCII in its path or query, which
      urllib would send and http.client refuse: such a URL is refused before it is sent (kind refused), where 0.55.0
      retried it and answered kind connection. Python's check_url checks the host's shape, not its name (FAA-187
      (14), (16)). The Node twin reads several of these as new URL does, among them a tab or line break removed, a
      space or a character outside ASCII percent-encoded, a backslash as /, an extra slash before the host skipped
      and a % host decoded (refused when the decoded host is not allowed, as h.example%3A8443).
    • What is sent: the default transport sends a URL up to its first # in both twins (urllib alone kept everything
      before the last one, so /x#a#b asked for /x#a); a transport you pass receives the URL as given. ASCII
      whitespace at the ends, which urllib and new URL both trim, is trimmed, so a URL ending in a line break is still
      sent, as in 0.55.0 (on Python 3.9 a URL with a leading space too, which 0.55.0 refused there). On Python a URL
      whose part before its first # ends in a Unicode space (a no-break or ideographic space) is now refused; 0.55.0
      sent it trimmed when the space ended the URL and failed every call when a fragment followed it. Node keeps it
      percent-encoded.
    • The OpenRouter clients trim a base URL's ends first: ASCII whitespace and trailing slashes in both, and on Node
      every C0 control there and a tab or line break anywhere, as new URL reads them. So .../v1\n, .../v1/ and,
      on Node, .../v1\n/ are sent to .../v1/chat/completions. Both then refuse, when they are built, a base URL
      holding a query or a fragment (kind config, read before check_url; /chat/completions would land in it, so a path-routed endpoint
      such as OpenRouter failed every call in 0.55.0). Python also refuses, through check_url (kind `refu...
Read more

v0.55.0: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 27 Oct 16:19
f3f2d14

Added

  • creating-fabric-agents: agents that answer people (FAA-162, board request 1ad39d4e). A new reference,
    references/agents-that-answer-people.md, lists what an agent that answers people (a support chat, mail, store
    reviews, a group) carries from its first release, each part with the check that proves it: a turn record with a trace
    id and a fixed outcome list, one support.quality_daily per closed UTC day and channel with notMeasured named,
    model lanes whose fallback, checker and judge are other vendors with fallback recoveries counted, a writer change only
    after an offline replay, false-state gates before the model checker, a checker that sees the material before the
    instructions, numbers and account state from tools, the live tail re-read before sending, repair then research then a
    hold that comes back by itself, hand-offs by cause and never as answers, a commitments ledger, a knowledge client that
    reads the service's answer flag, a gap queue, and a feed re-read when a reader starts on a new event kind. Its
    sources are agent-stack's support quality standard and the practices from an audit of five such agents, linked at
    their commits (the practices at agent-stack PR #70 until it merges). Step 0 of the skill gains the row "Does it answer
    people?" and Step 1 links the reference. New scenario eval an-agent-that-answers-people and its prose test
    (test/test_answering_agents_prose.py), which fails when a part or its check is removed. The support-agent recipe now
    says it is the draft-and-check step of such an agent, not the agent: used alone it hands the message to a person at
    the first refusal (the refused draft is not kept), and its Lookup is a relevance rule an agent that answers people
    replaces with the knowledge service's answer flag. It says the calling service routes policy before it, maps its
    hand-offs to causes (a failed check goes to repair and counts as inability only at a hold on the material, a hold
    after an outage or at the research time cap being infrastructure; no-knowledge and model-unsure are inability
    and open a gap; a money reason is never researched; model:* is infrastructure, model:ceiling and model:payment
    also the limit outcome), and tells such an agent to pass an on_handoff that redacts what it stores, in place of
    the outbox, and to keep 30 days or fewer; from_config takes on_handoff=, and a call to answer from inside
    on_handoff is refused at once with ReentryError rather than hanging (copy support_agent.py again to get both);
    building-fabric-services and the README point at it. Backlog FAA-116 records what is left for the recipe.

v0.54.0: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 27 Oct 11:02
5575cc6

Changed

  • Contract pin 00e050ba (v0.1.0+2026-10-27.1, DEC-0141) (FAA-159, CT-149, CT-177). A job's step under the
    operator's mandate is read as its start was: under the job's own capability, its action the step's request key
    (MJ-1). The kits' action_decision / actionDecision now read the reference's way: for an action whose tool is
    fabric.job.get the mandate is read under mandateCapability, and without a usable one (absent, empty, blank, not a
    capability name, or fabric.job.get itself) the answer is the service's fault mandate-capability-missing; any
    other action reads its own tool, whatever mandateCapability says. Before, an absent capability was read as
    fabric.job.get, a non-name string as given, and mandateCapability was read on any action. action_gate /
    actionGate answer that fault to the caller as operator-decision-required (data.detail
    mandate-capability-missing), the fault beside it for the service's log; nothing is applied, so the job stays
    input_required. job_step / jobStep read an unusable job capability alike at the start: the step waits
    input_required, its message naming mandate-capability-missing, and the Python tool server hands that fault (and any
    other job_step answers, such as now-unreadable) to on_fault at the start as at the answer. It is the one service fault a caller reads by name: on_fault's and the
    delegation reference's rule (a caller sees a fault only as unknown-state) now names it. So a job whose tool is not a capability name is no
    longer covered by an actions-only mandate at either end, and a mandate whose capabilities name fabric.job.get
    covers no step of another capability. Any service gating a job's answer itself passes the job's capability
    (actionGate({mandateCapability: private.capability}) in Node, action_gate(..., mandate_capability=) in Python
    outside McpToolServer, which passes it already); without it every answer a mandate used to cover now waits for the
    operator. refusal_from_action / refusalFromAction answer the fault the same way, so action_refusal_tool_result /
    actionRefusalToolResult agree with the gate. The vendored actions-vectors.json gains the contract's jobSteps group (14
    cases) and its two new action-call fixtures (18 in all); both twins run them. Bundles issued under the previous pin
    1197a90d stay valid (adapt_project.py).
  • working-with-fabric: a leading agent covering a job's approval step names the job's capability in
    capabilities without actions (the step's request key is the service's own), and reads data.detail
    mandate-capability-missing as a step no mandate covers: only the operator's decision answers it. New scenario eval
    lead-covers-a-job-step-by-its-capability. building-fabric-services' interop reference drops the sentence that
    read an answer without a capability under fabric.job.get.

v0.53.1: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 27 Oct 09:06
e000c21

0.53.0 was tagged and never released on npm or GitHub (the plugin marketplace, which reads main, offered it until
0.53.1 merged): its release run failed on Windows, where the FAA-140 tests read a Bash
command's POSIX paths through Windows path rules. 0.53.1 is 0.53.0 with this fix.

Fixed

  • No transcript read on Windows (FAA-175): working-with-fabric's Stop hook never reads the session transcript on
    Windows, even once Fabric takes repositories; a Bash command's paths there are not the host's. Windows sessions send
    their turn facts as before 0.53.0, without repositories. BashPaths and the four tests that need the hook itself to
    read (names from Edit and Bash paths, at most ten, one checkout named once, another checkout of the start repository)
    are skipped on Windows; the rest run there, the worker's with the read turned on in the test, and a new test checks that
    the mark turns nothing on there.

v0.52.0: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 26 Oct 22:14
25383f4

Changed

  • Pinned to the contract release v0.1.0+2026-10-26.12 (1197a90d) (FAA-138). It carries DEC-0126 to DEC-0137;
    e6c4fc16, a3a66eb0 and 52c7d798 stay supported. Brief:
    docs/evidence/specs/2026-10-26-faa-138-134-repin-1197a90d-brief.md.
  • DEC-0126, where the operator said the words (source). A mandate and a decision may carry source; both kits
    read it as the contract's schema does, return it in the record (recordAs, ctx.record, input_records), keep it
    on a hand-over, and build it with operator_mandate(source=) / operator_decision(source=) (Node: source).
    request_meta(..., target_protocols=) / requestMeta(traceparent, {targetProtocols}) send it only to a callee whose
    well-known protocols list operator-source/1, and otherwise keep it in the caller's own record (OA-7; never through
    Fabric's agent.call yet, FAA-146). McpToolServer.well_known_protocols(protocols) adds operator-source/1 when
    the server reads source. Nothing writes it to an event, a usage report, a log or a page (a test holds that).
  • A job's approval step reads the operator's mandate (contract interop C3.3, conformance.md; part of FAA-135):
    job_step / jobStep, CallContext.approval_step, request_input(steps=) / requestInput(..., {steps}); with
    input_actions on, an answer's _meta.mandate that covers a kept step is read too, under the job's own capability
    as at the start (action_gate(mandate_capability=) / actionGate({mandateCapability})). Each question replaces the
    kept steps and an answer clears them, so a step outlives neither its question nor its answer.
  • DEC-0136 closes at the pin: MD-2a is the pinned contract's rule, the by-name test override is gone, and both
    twins run the contract's 30 handOn cases; FAC-SEM-144's message ends (DEC-0125 MD-1, MD-2; DEC-0136 MD-2a).
    Vectors at .12: mandate 40 cases and 5 fixtures, actions 67 cases and 16 action calls.
  • working-with-fabric, its board reference, interop.md and the shared operator-channel reference cite DEC-0126 OA-1
    to OA-7 and drop the "ahead of the pin" wording; scenario eval relay-source-goes-only-where-it-is-read.
  • DEC-0128 (DL-14a), a hub key per organization context. hub_key_certified / hubKeyCertified take the
    token's context (context= / {context}), and verify_delegation and delegation_gate (Node: verifyDelegation,
    delegationGate) take estate_context / estateContext. An organization's token verifies only under its context's
    hub key (machines[].contextHubKeys) while the record pins the organization; a context that is neither personal
    nor org:<orgId> fails closed (kid-not-certified). verify_approval takes no context, as the contract declares.
  • Both estate readers check organization pins and context hub keys as the contract's estate-record-rules.ts does at
    .12: FAC-SEM-147 is new; FAC-SEM-073, 076, 114 and 134 read context hub keys.
  • fabric_estate splits its record rules into the new kit module fabric_estate_rules (Node:
    fabric-estate-rules.mjs), listed just before it in kit.json; fabric_estate re-exports every public name, so callers
    keep their imports, and fabric_kit.py install --module fabric_estate copies both.
  • An organization instance whose context the record does not pin still starts (fabric_context); its tokens are
    refused kid-not-certified (brief D5).
  • Vectors regenerated at .12: estate-vectors.json (the organizations positive, seven context and organization
    semantic fixtures, 38 generated context and revision cases), hub-key-vectors.json (contextCases 33,
    contextVerifier 10); the hostile estate inputs cover contextHubKeys, organizations and hub-key contexts.
  • DEC-0135, who a reply reaches (narrowing). A reply reaches the sender of the message it answers; send
    deliverTo: "thread" for every participant, or a list, and on a board pinned before DEC-0135, which refuses the
    member, a new message to the thread instead. The kit's responder posts only fenced replies, which carry none.
    The narrowing: once Fabric adopts DEC-0135 (planned for its 0.3.15; DR-5, for a reader it takes as pinned at or
    after DEC-0135; Fabric to 0.3.14 keeps the old count for every reader), com.list {unread: true} and the unread
    count cover only what was delivered to your Project, so a reply sent only to another Project no longer shows.
    project-board.md now also says a thread com.read_ack with upTo marks what your Project did not send, as the
    board always did.
  • DEC-0130 and DEC-0137, the family and the agent network (wording, no code change): delegation.md names the
    operator's family (T0 and T1) and the agent network, and estate-record.md says a tokenless call runs in the
    instance's context.
  • The session hooks' notes on nudges follow Fabric 0.3.14's final behaviour (board b605a636, Fabric
    release/0.3.14 b97ec351): a turn's answer shows a nudge, at most five, and a repeated turn answers the same; it
    stays for fabric_work_list and fabric_heartbeat, so it may come again there. The nudges of turns spooled before a
    /clear are therefore not lost (0.51.2's notes said they were).

Added

  • Being seen correctly in Fabric (FAA-151, board c42071bc): working-with-fabric Steps 4 and 5 claim the
    person's request as one task titled with it in one line (origin: {kind: "person", ref}), file each split with
    fabric_task_create while it is claimed, and link it with fabric_task_link (rel: "spawned") unless the answer
    says chained: true with chained_to the claimed task: always in a session opened from its own terminal, which
    Fabric to 0.3.14 never links itself. They report the stage with step and ofSteps, and send a heartbeat with
    phase: waiting before a wait (the wait in note, or waitingOn for a question asked with fabric_question_ask).
    Scenario eval seen-correctly-goal-and-step.
  • Fabric's rule work.check-every-three-minutes (FAA-141, Fabric TO-2, ask e2a7bec4): working-with-fabric
    Step 5 and creating-fabric-agents' autonomy reference tell an agent to call fabric_work_list every three minutes
    and before any wait, act first on its nudges and waiting_for_you, read and mark its unread board answers, and
    never leave a held task still. Scenario eval check-every-three-minutes.
  • Nine protocol register entries (DEC-0126, DEC-0127, DEC-0129, DEC-0131, DEC-0132): fabric-machine-report/1,
    machine-report/1, operator-source/1, org-authority/1, org-authority-draft/1, org-key-set/1,
    org-key-set-draft/1, org-membership/1 and org-root-registration/1 in fabric_protocols and
    fabric-protocols.mjs, so the kits' register equals the contract's at the pin.

v0.51.2: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 26 Oct 19:42
113fbf1

Added

  • Reminders Fabric gives on a turn reach the agent (FAA-142, Fabric ask dfb43ffb). From Fabric 0.3.14, the
    answer to a turn's fabric_session_observe may carry nudges: lapsed claims, unread board answers, requests nobody
    moved. The Stop hook's worker keeps their text in the session's spool (nudges.json), and the UserPromptSubmit
    hook prints each one once on the next prompt, after the unread line, as Fabric writes it (each starts Fabric:; any other line gets the tag Fabric reminder: ): one line each, at most five lines of at most
    400 characters. An empty or absent list prints nothing. A turn that watch-mail delivers has its nudges printed by
    watch-mail, once. Not carried across /clear: nudges of turns spooled before it stay in the old id's folder and are
    lost, since Fabric gives each nudge once and the turn's answer took it (carrying them would make the new id's folder before the launched-session check of FAA-68). Claude Code only: the Codex and Kimi
    Code hooks run at session start and send no turns.

Fixed

  • The hooks now name this release to Fabric: 0.51.1 still said 0.51.0, and test/validate.py now checks it.
    Copylot check 4028969a-aa35-48f9-9300-331da036fb1d: no findings.

v0.51.1: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 26 Oct 18:28
37a3dee

The tag v0.51.0 was never published: its release run stopped at the Node 18 floor, so 0.51.1 is the first npm
release carrying everything listed under 0.51.0 below.

Fixed

  • The tests of one instance per context (test/fabric-context.test.mjs, FAA-125) skip on Linux under a Node that
    cannot bind an abstract socket name exactly (Node 18 and 20), as every other lock test does since FAA-72. The kit
    itself already refused there with a sentence; only the tests lacked the guard.
  • references/package.md no longer says the passkey countersignature waits for org-authority/1: DEC-0129 decided
    that protocol only as the organization's member list for relay admission, and the countersignature waits for the
    decision that defines the org-countersign/1 verifier (contract finding on board thread 6c50c84f).

v0.50.0: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 26 Oct 02:57
d813a4e

Changed

  • Pinned to the contract release v0.1.0+2026-10-25 (52c7d798) (FAA-117, contract CT-124). The release carries
    DEC-0112 to DEC-0121; only DEC-0121 changes kit code, the others bind a node, an organization server or Project
    Observatory and only regenerate vendored vectors (connections gains seven cases, the protocol register
    fabric-actions/0.1). 2f020a6 stays supported. The brief is
    docs/evidence/specs/2026-10-26-faa-117-118-repin-52c7d79-brief.md (decisions D1 to D17).

Added

  • Dashboard action parity (DEC-0121). Every button a dashboard offers the operator is an agent action too.

    • fabric_actions.py / fabric-actions.mjs port the contract's actionDecision, actionsView and the FAC-SEM-142
      rules, checked against fixtures/vectors/actions.json (65 cases) and the semantic fixtures.
    • A service declares its actions with McpToolServer.add_tool(..., action=, target=, human_step_url=) and
      publishes them with build_well_known(actions=) / buildWellKnown({actions}) as extensions/actions/0.1; a
      declaration the contract would flag is refused.
    • The server gate reads only _meta.decision, never the arguments: a T0 or T1 call without the operator's
      decision is refused operator-decision-required, a malformed one decision-invalid, a step only a person can
      take human-step-required with data.humanStep and data.url, and T2 still needs approval-required. The
      decision records the authenticated caller (identify, the delegation's caller, or local:T0 / local:T1).
      Gating a job's input responses is opt-in (input_actions=True) until Fabric's hub forwards decisions (CT-125).
      The kits are ready now; a service adopts the gate once CT-125 lands, as the contract says (DEC-0121
      Compatibility, CT-127), because Claude Code and Codex cannot set _meta and would otherwise meet
      operator-decision-required with the page as their only route.
    • A caller relays with request_meta(decision=...) / requestMeta(traceparent, {decision}).
    • The three codes join DL-19 in both delegation twins.
  • The probe reports well-known.actions, interop.action-tools (a declared action's tool must be served),
    dashboard.actions-declared (NOT_RUN for a dashboard that declares none) and dashboard.opens-in-host
    (FAA-118: a browser opener aimed at the service's own pages in its checkout fails; --repo PATH names the
    checkout).

  • working-with-fabric relays the operator's own words as the decision (AP-3), never text from a tool result, a
    page, a file or another agent; a coding agent whose client cannot set _meta goes through Fabric's agent.call
    (after CT-125), the service's elicitation, or the action's page in Fabric Dashboards, in that order (confirmed by
    the contract's owner on board thread 92c6f277). On human-step-required it hands the person the link.

  • Fabric's button follows contract DEC-0124 (dashboard kit 1.1.5; FB-3 amended on the adapter's request, board
    thread 4801da8d, contract PR #189, after this release's pin). The accessible name and the menu follow the page's
    language, which the contract now states, so 0.49.3's note that the kit departs from FB-3 no longer holds. A page's
    own words (data-label-*) are taken only when they keep the word Fabric (WCAG 2.2 SC 2.5.3, Label in Name);
    otherwise the built-in words stay. A page that set words without Fabric under 0.49.3 shows the built-in words
    after it updates its kit. The kit follows this amendment ahead of the pin (brief decision D17).

  • The probe's new dashboard.opens-in-host can fail a service that passed before: one that opens its own pages
    in a browser. Open them through Fabric Dashboards instead (see the building-fabric-services skill).

Changed (guidance)

  • Agent pages open only in Fabric Dashboards (FAA-118, the operator's rule of 2026-10-24): the rule now sits in
    the body of the three SKILL.md files, with the AGENTS.md block a project carries and a section for an agent that
    has a page and no service descriptor. Manual restore and enabling the operator channel are the operator's
    decision on the page or relayed (D16).

v0.49.3: fabric-agent-adapter

Choose a tag to compare

@github-actions github-actions released this 25 Oct 23:07
103b00b

Fixed

  • Fabric's button speaks the page's language and carries no em dash (dashboard kit 1.1.4, FAA-119; asked by two
    services on the board). The button wrote U+2014 into the console message a person reads when it is not shown, and
    its four strings were English only, so a Russian dashboard could not mount it without editing a vendored file that
    dashboard_kit.py install then refuses as changed. The message now uses a colon. The button reads the page's lang
    and shows Russian on a Russian page, English otherwise; data-label-chat, data-label-session (with {name}),
    data-label-open and data-label-absent set a page's own words. The strings were checked with Copylot in the
    PassionCode.ai site voice (en-US report 239ff62c-e0af-4b8b-96e1-0c45c5eca02a, ru-RU report
    be37143c-aff1-4502-b9d0-f8b1be56bbf3, no findings). A test fails on U+2014 in any kit asset, and the WebKit test
    opens a Russian page and a page with its own words. The button's accessible name follows the page too (Открыть Fabric, or
    data-label-open), which departs from the pinned contract's FB-3 ("Open Fabric" in every case) the way Fabric
    Dashboards' own button already does; the amendment to allow a localized name is proposed to the contract (board
    thread 4801da8d).
  • A remote service registers where its code lives (FAA-120, a finding from a service that patched its descriptor
    after the kit wrote it). registerRemote and register_remote take source ({repository}), which the contract's
    service-descriptor.schema.json describes and Fabric Dashboards reads. The descriptor check now validates source
    in every descriptor: an object with repository only, a URI of RFC 3986 characters (the same answer as the
    contract's ajv-formats uri on 112 cases, brackets only around an IP-literal host), a host and a port up to 65535
    when it names an authority (Fabric reads it with new URL and drops a descriptor it cannot read), no
    user:password@, and no value shaped like a credential; None and null mean no source in
    both twins. A provider entry's source.repository (fabric_provider.py) refuses a password or a credential the same
    way. The probe's data rule and the SessionStart notice no longer raise on a descriptor whose source is not an
    object.