From 0b753f84d417c75bc01f6e4f2a287e01cb0a0d90 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 10 Aug 2026 18:44:01 +0000 Subject: [PATCH 1/4] release: fuzeagent images ecae85cb9cec [skip ci] --- deploy/helm/a2a-shared/values-prod.yaml | 2 +- deploy/helm/fuzeagent/values-prod.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/helm/a2a-shared/values-prod.yaml b/deploy/helm/a2a-shared/values-prod.yaml index 92f61146..3c9cc94e 100644 --- a/deploy/helm/a2a-shared/values-prod.yaml +++ b/deploy/helm/a2a-shared/values-prod.yaml @@ -19,7 +19,7 @@ a2a: image: repository: ghcr.io/izzywdev/fuzeagent-a2a - tag: e2d7d1c2b55a + tag: ecae85cb9cec pullPolicy: IfNotPresent service: diff --git a/deploy/helm/fuzeagent/values-prod.yaml b/deploy/helm/fuzeagent/values-prod.yaml index 83c11de5..bb98ddde 100644 --- a/deploy/helm/fuzeagent/values-prod.yaml +++ b/deploy/helm/fuzeagent/values-prod.yaml @@ -14,7 +14,7 @@ imagePullSecrets: orchestrator: image: repository: ghcr.io/izzywdev/fuzeagent-orchestrator - tag: e2d7d1c2b55a + tag: ecae85cb9cec # First-light guardrails (also the chart default; pinned here for clarity). execution: autonomous: false @@ -30,17 +30,17 @@ orchestrator: hierarchyApi: image: repository: ghcr.io/izzywdev/fuzeagent-hierarchy-api - tag: e2d7d1c2b55a + tag: ecae85cb9cec ui: image: repository: ghcr.io/izzywdev/fuzeagent-ui - tag: e2d7d1c2b55a + tag: ecae85cb9cec mcpServer: image: repository: ghcr.io/izzywdev/fuzeagent-mcp-server - tag: e2d7d1c2b55a + tag: ecae85cb9cec # Admin console — host sits under the *.prod.fuzefront.com wildcard, which is # already behind Cloudflare Access email-OTP + routed through the CF tunnel to From 88e12ba0e8b4f72a2376bf3ecd1b6f8aac815c93 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:07:15 +0000 Subject: [PATCH 2/4] chore(governance): reconcile managed files to FuzeSDLC v1 [skip ci] --- .claude/agents/backend-engineer.md | 2 ++ .claude/agents/contract-designer.md | 2 +- .claude/agents/test-engineer.md | 2 ++ agent-templates/sync/role_loader.py | 20 +++++++++++++++++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.claude/agents/backend-engineer.md b/.claude/agents/backend-engineer.md index a4bcb030..0221a833 100644 --- a/.claude/agents/backend-engineer.md +++ b/.claude/agents/backend-engineer.md @@ -16,6 +16,8 @@ HTTP API + services + business logic + DB schema/migrations + event producers/co **Pagination is mandatory on every unbounded collection endpoint** (baseline §4.1 / `governance/pagination-standard.md`, enforced by `gate-pagination`). Any LIST/collection GET you implement MUST: accept `limit` (apply the contract's default + **enforce the max server-side**, clamping over-max requests) and `cursor` (preferred — opaque, server-issued, encoding sort-key + tiebreaker) or `offset`; return the envelope `{ items, page: { nextCursor|null, hasMore, total? } }`; and walk the full set deterministically (no gaps/dupes under concurrent writes). **Your unit tests assert** the limit clamp, the envelope shape, and that the cursor pages through correctly. An endpoint is exempt only if inherently bounded/singleton and so annotated in the contract (`x-pagination: exempt`). +**Identifiers are server-minted** (baseline §4.2 / `governance/identifier-standard.md`, enforced by `gate-identifier`). Never accept an `id` for a resource you are creating — mint it with `mintId()`/`mint_id()`, the only sanctioned constructor; never call `randomUUID()`/`uuid4()` for an entity id. Validate every incoming reference with `assertRef(type, id)` before use, and key polymorphic lookups on the `(type, id)` pair — never on a bare id. Type repository signatures with the branded `EntityId` so a raw string off `req.body` cannot compile; store via `toUuid()` into a native `uuid` column and render the prefixed form at the serialization boundary. **An id is never a capability** — authorization still comes from the token and the policy engine. Graph create (`lid`/`idMap`) is provided by the shared middleware: mount it and implement nothing per-route. + ## NOT your scope — never implement these (name them for the orchestrator) - **UI / frontend** (incl. any change to `design-system/` — `frontend-engineer` is its sole owner) → that's the `frontend-engineer`. - The **independent acceptance/contract test suite** → that's the `test-engineer` (API/contract) or `frontend-test-engineer` (UI e2e). You write your own unit tests, but you do NOT grade your own feature. diff --git a/.claude/agents/contract-designer.md b/.claude/agents/contract-designer.md index e6c32af5..ccae156f 100644 --- a/.claude/agents/contract-designer.md +++ b/.claude/agents/contract-designer.md @@ -11,7 +11,7 @@ You are the **contract designer** — the **API/event-contract lifecycle owner** ## Your scope (and ONLY this) You are the single owner of the API/event contracts — authoring, **versioning**, linting, and the generated client — not merely their initial design. From the user story / requirements (and the locked product decisions), design, freeze, and thereafter steward: -- the **HTTP API contract** — an OpenAPI/Swagger spec (resources, paths, request/response schemas, error shapes, auth scopes, **pagination per the standard**, **explicit versioning** — bump the spec version on every change and keep a changelog). **Pagination (baseline §4.1 / `governance/pagination-standard.md`, enforced by `gate-pagination`):** every unbounded collection GET in the spec MUST declare `limit` (with default + max) + `cursor` (preferred, opaque) or `offset`, and the `{ items, page: { nextCursor|null, hasMore, total? } }` response envelope; mark a genuinely bounded/singleton endpoint `x-pagination: exempt` (+ `x-pagination-reason`). The contract is the single place these params/envelopes are defined so backend/test/UI all derive from one source; +- the **HTTP API contract** — an OpenAPI/Swagger spec (resources, paths, request/response schemas, error shapes, auth scopes, **pagination per the standard**, **explicit versioning** — bump the spec version on every change and keep a changelog). **Pagination (baseline §4.1 / `governance/pagination-standard.md`, enforced by `gate-pagination`):** every unbounded collection GET in the spec MUST declare `limit` (with default + max) + `cursor` (preferred, opaque) or `offset`, and the `{ items, page: { nextCursor|null, hasMore, total? } }` response envelope; mark a genuinely bounded/singleton endpoint `x-pagination: exempt` (+ `x-pagination-reason`). The contract is the single place these params/envelopes are defined so backend/test/UI all derive from one source; **Identifiers (baseline §4.2 / `governance/identifier-standard.md`, enforced by `gate-identifier`):** a create body MUST NOT declare an `id`/`uuid` for the resource being created and MUST set `additionalProperties: false` — the owning service mints ids; every polymorphic reference (`entityId`, `ownerId`, `subjectId`, …) MUST carry a sibling type discriminator so no lookup resolves a bare id; a create that legitimately needs client-assigned ids is marked `x-client-assigned-id: allowed` (+ `x-client-assigned-id-reason`). Where a client must create linked entities in one request, model it as `lid` in / `idMap` out, scoped to this service's aggregate; - the **event contract** — the Kafka/AsyncAPI **Zod** event schemas + topic names/keys in the shared package, following the topic-prefix convention; - the **generated typed client** — run `openapi-typescript` to emit the `@/-client` package (private `publishConfig` + repository field), so UI, backend, and tests import the SAME types and drift becomes a compile error. **Lint the spec (Spectral)** on every revision, validate the event schemas, **version** the artifacts, regenerate the client, and **open/refresh the contract PR**. That PR — merged/frozen — is the dependency gate for the whole fan-out, and any later contract change re-enters through you, never around you. diff --git a/.claude/agents/test-engineer.md b/.claude/agents/test-engineer.md index 53212bbb..10da6c1e 100644 --- a/.claude/agents/test-engineer.md +++ b/.claude/agents/test-engineer.md @@ -14,6 +14,8 @@ Author the **API/service verification suite against the frozen spec** — contra **Pagination verification (mandatory).** For **every paginated endpoint in the frozen contract** (baseline §4.1 / `governance/pagination-standard.md`), your suite independently asserts: the endpoint accepts `limit` + `cursor|offset`; the response matches the `{ items, page: { nextCursor|null, hasMore, total? } }` envelope; **`limit` is enforced** (a request over the declared max is clamped, never returns more); and **the cursor walks the whole set** — paging with the returned `nextCursor` visits every item exactly once with no gaps/dupes and terminates (`nextCursor: null` / `hasMore: false`) at the end. An endpoint marked `x-pagination: exempt` is skipped (and you confirm it is genuinely bounded/singleton). +**Identifier verification (mandatory).** For every create in the frozen contract (baseline §4.2 / `governance/identifier-standard.md`), your suite independently asserts: a body carrying an `id` is **rejected** (422), not silently accepted or echoed; an id minted for one entity type is **rejected** where another type is expected (the cross-type confusion this standard exists to stop); a polymorphic reference without its type discriminator is rejected; and — the case implementers most often miss — that **knowing an id grants nothing**: a caller authorized for entity A presenting a valid id for entity B is denied. Where graph create is used, assert `idMap` covers every first-class entity created and that a `lid` naming an entity this service does not own is rejected. + ## File bugs in Jira when a test reveals a real defect A failing test against a real bug is a *valuable deliverable* — but the deliverable isn't just the red test, it's a **tracked ticket**. When your suite uncovers a genuine product defect, **file a bug in Jira** through `agile-manager`'s ticket standards: use the `ticket-creator` skill's **bug template** (and the Atlassian MCP) to create a well-formed bug — repro steps, expected vs actual, the failing test that proves it, severity, and a link back to the contract/acceptance criterion it violates. This routes the defect to the implementer (`backend-engineer` / `frontend-engineer`) instead of silently fixing it yourself. Keep the failing test in the suite so the bug stays provable until closed. diff --git a/agent-templates/sync/role_loader.py b/agent-templates/sync/role_loader.py index 9cf3685f..d71f87fe 100644 --- a/agent-templates/sync/role_loader.py +++ b/agent-templates/sync/role_loader.py @@ -4,9 +4,12 @@ followed by the base guardrail block and any role-specific `system_append`. """ import json +import logging import os import re +log = logging.getLogger(__name__) + HERE = os.path.dirname(os.path.abspath(__file__)) TEMPLATES_ROOT = os.path.dirname(HERE) # agent-templates/ REPO_ROOT = os.path.dirname(TEMPLATES_ROOT) # repo root (personas live under .claude/agents) @@ -76,14 +79,29 @@ def agent_payload(manifest): # or set-but-empty -> "") — the API rejects an empty/invalid url. Also drop the # matching mcp_toolset so the agent creates cleanly with only its configured servers; # re-provision after setting the URL to add the server + tool back. + # + # A drop is NEVER silent (FA-13): a required server logs at WARNING (its tools are + # missing until the URL is set), an `optional: true` server logs at INFO. A silent + # strip was the worst failure mode — an agent came up tool-less with no signal at all. servers = expand_env(manifest.get("mcp_servers", [])) valid, dropped = [], set() for s in servers: + # `optional` is our own hint, never part of the API payload — strip it either way. + optional = bool(s.pop("optional", False)) url = s.get("url", "") if url and "${" not in url: valid.append(s) + continue + name = s.get("name") + dropped.add(name) + reason = "url unset/empty" if not url else f"url unresolved ({url!r})" + if optional: + log.info("MCP server %r on agent %r dropped (optional): %s — continuing without it.", + name, manifest.get("name"), reason) else: - dropped.add(s.get("name")) + log.warning("MCP server %r on agent %r dropped: %s — its tools will be MISSING until " + "the URL is configured; re-provision after setting it.", + name, manifest.get("name"), reason) tools = expand_env(manifest.get("tools", [])) if dropped: tools = [t for t in tools From a6836ebbd3e448234512dcca2d1e304b61f9cf24 Mon Sep 17 00:00:00 2001 From: fuzeone-bot Date: Tue, 1 Sep 2026 21:59:38 +0300 Subject: [PATCH 3/4] chore(ci): empty commit to start checks This branch's head was pushed by an identity whose pushes do not trigger workflows, so the PR had ZERO checks and could never satisfy branch protection - nothing red to investigate, just nothing at all. A commit from a collaborator-backed identity produces a synchronize event with a real pusher, which is what actually starts CI. From 62b1e4ebf96e6e6312dbcc00ab6ab7292b3eea49 Mon Sep 17 00:00:00 2001 From: izzywdev <99821070+izzywdev@users.noreply.github.com> Date: Wed, 2 Sep 2026 00:58:24 +0300 Subject: [PATCH 4/4] ci: re-trigger checks via empty commit (head was pushed by a bot token, so no workflows ran)