From b97354353b346c26b034cc319629d1284fc61dfa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 20:59:59 +0000 Subject: [PATCH 1/3] Initial plan From 8ad69f74c6d73890794b74026a2359dfcedc50d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 21:11:51 +0000 Subject: [PATCH 2/3] ci: add workflow and issue data to create GitHub issues from PR #361 review comments Co-authored-by: JustAGhosT <5531814+JustAGhosT@users.noreply.github.com> Agent-Logs-Url: https://github.com/phoenixvc/cognitive-mesh/sessions/b551d67f-8284-421d-b411-3850be2a0401 --- .github/pr-361-review-issues.json | 112 ++++++++++++++++++ .github/workflows/create-pr-review-issues.yml | 79 ++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 .github/pr-361-review-issues.json create mode 100644 .github/workflows/create-pr-review-issues.yml diff --git a/.github/pr-361-review-issues.json b/.github/pr-361-review-issues.json new file mode 100644 index 00000000..6e2406de --- /dev/null +++ b/.github/pr-361-review-issues.json @@ -0,0 +1,112 @@ +[ + { + "title": "fix(ci): Pin all checkouts to triggering workflow_run commit in deploy-frontend.yml", + "body": "## Summary\n\nOn `workflow_run`-triggered jobs, `github.sha` points to the default branch HEAD — not the commit that passed the upstream workflow. This causes `actions/checkout` to check out a different revision than what was tested, allowing a build-one-commit/deploy-another-manifests scenario.\n\n## Affected file\n`.github/workflows/deploy-frontend.yml` — lines 64-67, 105-106, 121-123, 185-187\n\n## Required fix\nUse `github.event.workflow_run.head_sha` as the `ref` input on every `actions/checkout` step and for the `org.opencontainers.image.revision` OCI label:\n\n```yaml\n- uses: actions/checkout@v6\n with:\n fetch-depth: 0\n ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }}\n```\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918141425\n- Severity: 🔴 Critical", + "labels": ["bug", "ci/cd"] + }, + { + "title": "fix(ci): Staging calls production API — NEXT_PUBLIC_API_BASE_URL baked in at build time", + "body": "## Summary\n\nThe workflow bakes `NEXT_PUBLIC_API_BASE_URL=https://api.cognitivemesh.io` into the client bundle via Docker build-args, then promotes the **same image** to both staging and production. Because Next.js inlines `NEXT_PUBLIC_*` variables at build time, staging can never override this value at runtime and will always call the production API endpoint.\n\n## Affected file\n`.github/workflows/deploy-frontend.yml` — lines 97-99\n\n## Required fix\nEither:\n1. Create separate build jobs per environment, each passing environment-specific `NEXT_PUBLIC_API_BASE_URL`; or\n2. Move API configuration to runtime (e.g., server-side config endpoint, SSR context, or non-`NEXT_PUBLIC_` env var read server-side and exposed to the client).\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918141434\n- Severity: 🔴 Critical", + "labels": ["bug", "ci/cd"] + }, + { + "title": "fix(k8s): Global rewrite-target \"/\" collapses all requests in frontend-ingress.yaml", + "body": "## Summary\n\nThe annotation `nginx.ingress.kubernetes.io/rewrite-target: /` is applied globally. This means every request — including `/api/foo`, `/healthz`, and frontend deep links like `/widgets/marketplace` — arrives at the upstream service as `/`, breaking API routing and App Router direct loads.\n\n## Affected file\n`k8s/base/frontend-ingress.yaml` — lines 11-15, 24-25, 47-48\n\n## Required fix\nRemove the global rewrite annotation. If path stripping is needed for a specific route, apply a targeted annotation on that rule only. Switch `/api(/|$)(.*)` regex rules to simple `Prefix` path type rules:\n\n```yaml\n- path: /api\n pathType: Prefix\n backend:\n service:\n name: cognitive-mesh-api\n```\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918141438\n- Severity: 🔴 Critical", + "labels": ["bug", "infrastructure"] + }, + { + "title": "fix(auth): RevokeAuthorityOverrideAsync ignores action parameter and may revoke wrong override", + "body": "## Summary\n\n`IAuthorityPort.RevokeAuthorityOverrideAsync` in `AuthorityService` queries `AuthorityOverrides` by `AgentId`/`TenantId`/`IsActive` but **ignores the `action` parameter** and calls `FirstOrDefaultAsync()`. When multiple active override rows exist for the same agent/tenant, this can revoke an unrelated or already-expired override, leaving the requested elevated permission in place.\n\n## Affected file\n`src/BusinessApplications/AgentRegistry/Services/AuthorityService.cs` — lines 745-760\n\n## Required fix\nAdd `action` to the LINQ filter and choose deterministically:\n\n```csharp\nvar activeOverride = (await _dbContext.AuthorityOverrides\n .Where(o => o.AgentId == agentId\n && o.TenantId == tenantId\n && o.IsActive\n && o.ExpiresAt > DateTimeOffset.UtcNow)\n .OrderByDescending(o => o.CreatedAt)\n .ToListAsync())\n .FirstOrDefault(o => o.OverrideScope?.AllowedApiEndpoints?.Contains(action) == true);\n```\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918141445\n- Severity: 🔴 Critical", + "labels": ["bug", "security"] + }, + { + "title": "fix(compliance): ConcurrentDictionary.AddOrUpdate unsafe for in-place EvidenceRecord mutation in NISTComplianceService", + "body": "## Summary\n\n`ConcurrentDictionary.AddOrUpdate` executes its `updateValueFactory` delegate **outside the dictionary's internal locks** and may invoke it **multiple times** under contention. Concurrent calls to `SubmitReviewAsync` with the same evidence ID therefore mutate an `EvidenceRecord` field-by-field without synchronization, resulting in a record with a mixed review state.\n\n## Affected file\n`src/BusinessApplications/NISTCompliance/Services/NISTComplianceService.cs` — line 233\n\n## Required fix\nReplace the unsafe in-place mutation with an immutable update (create a new record value) or use a proper `lock`/`Interlocked` mechanism:\n\n```csharp\n_evidenceRecords.AddOrUpdate(\n evidenceId,\n _ => CreateNewRecord(review),\n (_, existing) => existing with { ReviewedBy = review.ReviewedBy, Status = review.Status, ReviewedAt = review.ReviewedAt }\n);\n```\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918141448\n- Severity: 🔴 Critical", + "labels": ["bug", "concurrency"] + }, + { + "title": "fix(state): Phase 16 history entry missing from orchestrator.json before advancing last_phase_completed", + "body": "## Summary\n\n`last_phase_completed` in `.claude/state/orchestrator.json` has been advanced to `16`, but `phase_history` still ends at `\"15a\"`. Any consumer that derives release notes, rollback context, or next work from the history log will see Phase 16 as if it never happened.\n\n## Affected file\n`.claude/state/orchestrator.json` — line 4\n\n## Required fix\nAdd a Phase 16 history entry to `phase_history` before (or alongside) updating `last_phase_completed`. The entry should include the phase name, completion date, and key deliverables.\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918362689\n- Severity: 🟠 Major", + "labels": ["bug", "documentation"] + }, + { + "title": "fix(state): FETEST-001 marked DONE in backlog while component_test_coverage_pct is 25% in orchestrator.json", + "body": "## Summary\n\n`.claude/state/orchestrator.json` shows `component_test_coverage_pct: 25`, but the backlog simultaneously marks `FETEST-001 Unit tests 80% [DONE]`. This internal inconsistency risks treating incomplete test coverage as complete, allowing work items that depend on 80% coverage to proceed prematurely.\n\n## Affected file\n`.claude/state/orchestrator.json` — line 173\n\n## Required fix\nEither:\n1. Update `component_test_coverage_pct` to accurately reflect the achieved coverage; or\n2. Reopen `FETEST-001` in the backlog until coverage actually reaches 80%.\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2918362694\n- Severity: 🟠 Major", + "labels": ["bug", "testing"] + }, + { + "title": "fix(tests): E2E auth-flow test helper uses stale auth contract (auth_token vs accessToken/refreshToken)", + "body": "## Summary\n\nThe in-test auth store helper in `auth-flow.test.tsx` writes `auth_token` and accepts an injected `user` object. The actual shipped auth flow uses `accessToken`/`refreshToken`, derives the user from the JWT, and sets the `cm_access_token` cookie. This mismatch means the tests pass even when the real auth contract is broken.\n\n## Affected file\n`src/UILayer/web/src/__tests__/e2e/auth-flow.test.tsx` — line 39\n\n## Required fix\nUpdate the test helper to use the same field names and structure as the real `useAuthStore` (`accessToken`, `refreshToken`, cookie logic) so the tests fail when the production auth contract changes.\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2919366126\n- Severity: 🟠 Major", + "labels": ["bug", "testing"] + }, + { + "title": "fix(tests): E2E login tests exercise fictional API and component flow, not the real implementation", + "body": "## Summary\n\nThe login tests in `auth-flow.test.tsx` (lines 76, 105) post to `/api/auth/login` and consume `{ token, user }`, while the actual implementation uses a different endpoint and response shape. The form, submit handler, fetch URL, response parsing, and redirect are all defined inline within the test — the real component is never imported or rendered.\n\n## Affected file\n`src/UILayer/web/src/__tests__/e2e/auth-flow.test.tsx` — line 123\n\n## Required fix\nImport and render the actual login page/component. Mock only external boundaries (fetch, router) with responses that match the real API shape. Assertions should verify the real component's behavior after login.\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2919366167\n- Severity: 🟠 Major", + "labels": ["bug", "testing"] + }, + { + "title": "fix(tests): Dashboard e2e tests use inline stub components — real implementation never exercised", + "body": "## Summary\n\nAll \"dashboard\" behavior in `dashboard-flow.test.tsx` comes from inline stub components defined in the test file. The suite will not fail if the actual route, widgets, fetch logic, or `useSignalR` integration breaks, because the real implementation is never imported or rendered.\n\n## Affected file\n`src/UILayer/web/src/__tests__/e2e/dashboard-flow.test.tsx` — line 105\n\n## Required fix\nImport and render the real dashboard route/page. Mock only external boundaries (API calls, WebSocket) and assert on rendered output from the real implementation.\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2919366173\n- Severity: 🟠 Major", + "labels": ["bug", "testing"] + }, + { + "title": "fix(tests): Settings e2e test suite tests the Zustand store directly, not the settings UI flow", + "body": "## Summary\n\nEvery assertion in `settings-flow.test.tsx` goes through `usePreferencesStore.getState()` directly. The test suite will pass even if the real settings page stops rendering the correct controls, miswires event handlers, or fails to hydrate from the store — because the real component is never involved.\n\n## Affected file\n`src/UILayer/web/src/__tests__/e2e/settings-flow.test.tsx` — line 54\n\n## Required fix\nRender the real settings page component and interact with it via user events (`userEvent.click`, `userEvent.type`). Assert on what the user sees (rendered output) rather than internal store state.\n\n## References\n- PR #361 review: https://github.com/phoenixvc/cognitive-mesh/pull/361#discussion_r2919366181\n- Severity: 🟠 Major", + "labels": ["bug", "testing"] + }, + { + "title": "fix(ui): CommandPalette Ctrl/Cmd+K shortcut fires when focus is on text-entry controls", + "body": "## Summary\n\nThe document-level `keydown` handler in `CommandPalette.tsx` fires on all events regardless of which element is focused. If a user is typing in an ``, `