Skip to content

fix: stale sign-off pins block first publication, and calculator entries survive a resize - #3575

Merged
gitar-bot[bot] merged 7 commits into
mainfrom
claude/pr-3574-resolve-0lrep3
Oct 16, 2026
Merged

gitar-bot[bot] merged 7 commits into
mainfrom
claude/pr-3574-resolve-0lrep3

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Oct 16, 2026 •

Copy link
Copy Markdown
Owner

User description

Summary

These are the two follow-ups the owner approved from PR #3574.

  • Sign-off content check. Before, the first-publication plan checked only that reviewedContentSha256 looked like a SHA-256, so a record edited after its sign-off could still be planned for publication. After, the plan works out each pin again through the clinical:review contract and refuses any record whose content changed since sign-off. Forms are checked against data/forms-catalog.json and services against the curated records. A service whose curated records cannot be loaded is also refused. All 54 form pins and all 21 reviewed service pins in the repository still match.
  • Calculator keeps entries on resize. Before, the bedside CrCl, QTc and lithium panel lost everything entered when the window crossed 1280 px, because the sidebar copy and the mobile copy each held their own state. After, the calculator page holds one in-memory state and passes it to whichever panel is showing. Nothing is stored on the device.

Areas touched: App experience, Clinical reference content, Answer engine

Verification

  • Checks run:
    • npx vitest run on 7 suites (calculators, clinical math, first-publication CLI): Test Files 7 passed (7) Tests 119 passed (119)
    • New breakpoint test fails without the fix (Tests 1 failed (1)) and passes with it.
    • npm run typecheck: [gate-receipts] recorded a pass for "typecheck:internal" (10176 input files).
    • npx eslint --max-warnings=0 on the changed files: clean
    • npm run check:diff-integrity -- --base origin/main: PASS — 2 changed test file(s), 10 -> 13 test case(s)
    • npm run check:calculator-content: CALCULATOR_CONTENT_PASS sources=ok golden-vectors=ok rights=ok
    • First-publication dry run (--kind form): First-publication plan ready: 54 record(s) across 1 batch(es)
    • Browser suite left to CI.

Risk and rollout

  • Risk: Low. The publish change can only refuse more. It is an offline planning script and nothing calls it automatically. The calculator change moves where the same state lives.
  • Rollback: Revert the commit.
  • Provider or production effects: None. No database, ranking or clinical text changes.

Notes

  • RAG impact: no retrieval behaviour change. No ranking or retrieval files are touched.

🤖 Generated with Claude Code

https://claude.ai/code/session_016imb8DCuk85z3FWRDDyZx5


Generated by Claude Code


Summary by cubic

Fixes two follow-ups from PR #3574: stale sign-off pins now block first publication, and bedside calculator entries survive window resizes.

Changes

  • The first-publication plan recomputes each content pin via the clinical:review contract — forms against data/forms-catalog.json, services against curated records loaded from the repository root — and refuses any record whose content changed since sign-off, any service pin whose content cannot be loaded, and any service record carrying legacy cost fields not covered by the sign-off.
  • The plan also refuses a sign-off that names a different record than the one being published, so a review matched only through a slug alias no longer counts.
  • The calculator page holds one in-memory state for the bedside CrCl, QTc, and lithium panels and passes it to whichever panel is mounted, so crossing the 1280px breakpoint no longer wipes entries.
  • Reverted unreviewed bot commits that had reintroduced separate per-layout calculator state and changed sign-off refusal behavior.

Written for commit cfcffe1. Summary will update on new commits.

View guided diff Turn on auto-fix


CodeAnt-AI Description

Prevent outdated clinical approvals from publishing changed content and preserve calculator entries during resizing

What Changed

  • Publication plans now reject clinical records if their content has changed since sign-off or cannot be checked.
  • Calculator entries remain filled in when resizing between the desktop sidebar and mobile layout.

Impact

✅ Changed clinical content cannot rely on an outdated approval
✅ Calculator entries survive desktop and mobile resizing

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features
    • Calculator panel entries now remain available when switching between desktop and mobile layouts.
  • Bug Fixes
    • First-publication plans now require service and form sign-off pins to match the reviewed content. Plans are rejected when a pin is stale or cannot be verified, including when required content is unavailable.

…in is stale

The first-publication plan checked only that reviewedContentSha256 looked
like a SHA-256. It now recomputes the pin through the clinical:review
contract (forms against data/forms-catalog.json, services against the
curated records) and refuses any record edited since its sign-off.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016imb8DCuk85z3FWRDDyZx5
…breakpoint

The calculator page mounts ClinicalMathPanel in the sidebar at 1280px and
wider, and in the mobile column below that. Each mount had its own state,
so resizing across the breakpoint wiped everything entered. The page now
holds one in-memory state and passes it to whichever panel is mounted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016imb8DCuk85z3FWRDDyZx5
@supabase

supabase Bot commented Oct 16, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BigSimmo has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@codeant-ai

codeant-ai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR fe0f259 Oct 16, 2026 · 10:56 11:03

@codeant-ai

codeant-ai Bot commented Oct 16, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T11:02:16.686775Z fe0f259 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2s —— View job


I'll analyze this and get back to you.

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Oct 16, 2026
@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Reject stale publication sign-offs and preserve calculator entries on resize

🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Refuse first-publication plans when clinical sign-off pins no longer match their content.
• Keep bedside calculator entries and panel state when switching between mobile and desktop layouts.
• Add regression tests for stale pins, unavailable service records, and breakpoint changes.
Diagram

graph TD
  CLI["First-publication CLI"] --> Pin{"Current pin?"} --> Outcome["Plan or refusal"]
  Content["Signed content"] --> Pin
  Page["Calculator page"] --> State["Shared memory"] --> Desktop["Desktop panel"]
  State --> Mobile["Mobile panel"]
Loading
High-Level Assessment

Reuse of the clinical review pin contract avoids a second hashing rule, while lifting calculator state to the page preserves entries without device storage. Reworking the responsive layout to keep one panel mounted would be broader than the state-ownership fix.

Files changed (5) +267 / -12

Bug fix (3) +145 / -9
publish-site-content-first-catalogue.tsRequire current content pins in first-publication plans +59/-4

Require current content pins in first-publication plans

• Checks form and service sign-offs against the content covered by their pins using the clinical review contract. Refuses stale pins or unavailable service context, and loads curated service records for CLI planning.

scripts/publish-site-content-first-catalogue.ts

clinical-math-panel.tsxExtract reusable in-memory clinical math state +82/-2

Extract reusable in-memory clinical math state

• Moves entries, active tab, and open state into a hook that a parent can own. The panel accepts that state while retaining its standalone default behavior.

src/components/calculators/clinical-math-panel.tsx

search-page.tsxShare calculator state across responsive panel mounts +4/-3

Share calculator state across responsive panel mounts

• Owns clinical math state at page level and passes it to either the desktop sidebar or mobile panel, preserving entries when the mounted panel changes.

src/components/calculators/search-page.tsx

Tests (2) +122 / -3
clinical-math-panel-breakpoint.dom.test.tsxTest calculator entries across the desktop breakpoint +64/-0

Test calculator entries across the desktop breakpoint

• Simulates changes to the 1280-pixel media query and verifies that entered age and weight remain available after the panel moves between layouts.

tests/clinical-math-panel-breakpoint.dom.test.tsx

site-content-first-publication-cli.test.tsTest current, stale, and unverifiable publication pins +58/-3

Test current, stale, and unverifiable publication pins

• Adds coverage for a valid repository form pin, a stale form pin, and a service whose curated records were not loaded. Updates synthetic planning fixtures to supply record-specific pin checks.

tests/site-content-first-publication-cli.test.ts

@codeant-ai

codeant-ai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: cfcffe1a
Scan Time: 2026-10-16 11:38:21 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED No IAC issues

View Full Results

@coderabbitai

coderabbitai Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Warning

Review limit reached

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

Next included review available in 41 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 99 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: BigSimmo/PsychSift/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 226d0e88-1df9-4ddf-adad-4da36fc69126
📥 Commits

Reviewing files that changed from the base of the PR and between fe0f259 and cfcffe1.

📒 Files selected for processing: 2
  • scripts/publish-site-content-first-catalogue.ts
  • tests/site-content-first-publication-cli.test.ts

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: BigSimmo/PsychSift/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 5d0bd311-9932-46e4-b854-be1658cac246
📥 Commits

Reviewing files that changed from the base of the PR and between 0f441dc and fe0f259.

📒 Files selected for processing: 5
  • scripts/publish-site-content-first-catalogue.ts
  • src/components/calculators/clinical-math-panel.tsx
  • src/components/calculators/search-page.tsx
  • tests/clinical-math-panel-breakpoint.dom.test.tsx
  • tests/site-content-first-publication-cli.test.ts

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

📝 Walkthrough

First-publication plans now validate service and form sign-off content pins. The calculator search page shares clinical math panel state across responsive sidebar renderings.

Changes: First-publication sign-off pins

Layer / File(s) Summary
Pin-check contract and checker
scripts/publish-site-content-first-catalogue.ts
Adds pin states and a checker callback. The default checker checks service pins against supplied context and form pins against a lazily loaded catalogue.
Plan validation and CLI coverage
scripts/publish-site-content-first-catalogue.ts, tests/site-content-first-publication-cli.test.ts
Plan creation rejects unverifiable or non-current pins. The CLI loads service context for service and all-kind plans. Tests cover current pins, different digests, and missing service context.

Clinical math panel state

Layer / File(s) Summary
Shared state across responsive sidebars
src/components/calculators/clinical-math-panel.tsx, src/components/calculators/search-page.tsx, tests/clinical-math-panel-breakpoint.dom.test.tsx
Adds an exported state hook and optional panel state. The search page passes shared state to both sidebar renderings. A breakpoint test checks that entered values remain after switching layouts.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant CalculatorsSearchPage
  participant useClinicalMathPanelState
  participant ClinicalMathPanel
  participant Viewport
  CalculatorsSearchPage->>useClinicalMathPanelState: initialize shared panel state
  CalculatorsSearchPage->>ClinicalMathPanel: pass shared state to visible sidebar
  Viewport->>CalculatorsSearchPage: cross the 1280px breakpoint
  CalculatorsSearchPage->>ClinicalMathPanel: render alternate sidebar with shared state
Loading
Merge Risk: ⚪ Minimal · up to fe0f2

First publication now refuses records whose content changed after sign-off. Calculator entries now persist when the window crosses the desktop breakpoint. The supported publication command validates and publishes the same content, so no merge-blocking risk remains.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 26.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly summarizes both primary changes: stale sign-off pins now block first publication, and calculator entries survive resizing.
Description check Passed The description includes the required Summary, Verification, Risk and rollout, and Notes sections. It explains the changes, lists verification results, and documents risk, rollback, and production eff…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Description check

Explanation

The description includes the required Summary, Verification, Risk and rollout, and Notes sections. It explains the changes, lists verification results, and documents risk, rollback, and production effects.

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@gitar-bot
gitar-bot Bot enabled auto-merge (squash) October 16, 2026 10:58
gitar-bot[bot]
gitar-bot Bot previously approved these changes Oct 16, 2026

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR (configure)

@qodo-code-review

qodo-code-review Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

No findings for this group


Remediation recommended

No findings for this group


Informational

No findings for this group

Grey Divider


Resolved findings

1. Service details bypass clinical sign-off ✗ Dismissed
Description
createSignOffPinCheck validates the review and its curated or catalogue context, but does not
verify the ServiceRecord or FormRecord selected for publication; defaultServiceRecords() can
also retain legacy fields outside the curated service pin. If a caller edits a selected record
without changing its valid review, or a snapshot entry comes to match a signed standalone service,
the pin still passes while the edited fields or legacy cost reach the publication plan.
Code

scripts/publish-site-content-first-catalogue.ts[R145-147]

+    if (kind === "service") {
+      if (!options.serviceContext) return "unverifiable";
+      return recordPinState(review, "service", options.serviceContext);
Relevance

●●● Strong

Signed hashes must cover every published field; prior governance precedents accept omitted-input
integrity fixes.

PR-#2580
PR-#2878

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The check receives and hashes the review and its context, while the builder independently converts
the selected record into a publication row. Consequently, changing a selected record’s title changes
the row without changing the checked digest; the default service-record merge likewise preserves
legacy cost information and maps it into the published service record despite the check hashing the
curated record.

scripts/publish-site-content-first-catalogue.ts[140-150]
scripts/publish-site-content-first-catalogue.ts[249-264]
src/lib/service-governance.ts[339-355]
src/lib/service-catalog-mapper.ts[455-472]
scripts/publish-site-content-first-catalogue.ts[139-151]
scripts/publish-site-content-first-catalogue.ts[264-275]
scripts/publish-site-content-first-catalogue.ts[287-324]
scripts/publish-site-content-first-catalogue.ts[222-237]
src/lib/registry-records.ts[57-86]
src/lib/service-governance.ts[339-352]
Skill: source-governance

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A current review pin can pass even when the selected publication record contains edited content or legacy service fields not covered by that pin.

## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[139-151]
- scripts/publish-site-content-first-catalogue.ts[222-237]
- scripts/publish-site-content-first-catalogue.ts[285-324]
- src/lib/service-governance.ts[339-355]
- tests/site-content-first-publication-cli.test.ts[136-161]

## Recommended Fix
Before accepting a selected service or form record, verify that its publishable content matches or is derived solely from the content covered by its review pin. Refuse a merged legacy service record when that relationship cannot be established. Add tests for edited caller-supplied records and for a signed standalone service that gains a matching snapshot entry with different legacy cost information.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. One review can approve another record ✗ Dismissed
Description
validateSignOffEntry checks the pin on the review returned by an alias lookup without requiring
that review's id or code to identify the selected record. When a signed review's slug matches
another service or form, its pin is checked against its own content and can authorize publication of
that other record.
Code

scripts/publish-site-content-first-catalogue.ts[294]

+    const problem = validateSignOffEntry("service", stableId, service.slug, review, pinState);
Relevance

●●● Strong

Alias-based approval without selected-record identity is an authorization mismatch, consistent with
accepted canonical-selection fixes.

PR-#2878
PR-#3114

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The lookup indexes reviews by multiple keys, including slug, but the attestation resolves content by
the review's own ID or code. The new pin check consequently cannot establish which selected record
that review authorizes.

scripts/publish-site-content-first-catalogue.ts[267-274]
scripts/publish-site-content-first-catalogue.ts[287-294]
scripts/publish-site-content-first-catalogue.ts[296-319]
scripts/lib/signoff-kinds/services.mjs[47-56]
scripts/lib/clinical-record-review-contract.mjs[704-721]
scripts/lib/clinical-record-review-contract.mjs[856-874]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Alias lookup can select a valid pin for a different publication target.
## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[287-294]
- scripts/publish-site-content-first-catalogue.ts[310-319]
- scripts/publish-site-content-first-catalogue.ts[154-201]
## Recommended Fix
Before accepting a current pin, require the review's canonical service ID or form code to match the selected target's canonical identity. Reject conflicting aliases and test a current review whose slug points to another record.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Service plans fail outside the project root ✓ Resolved
Description
runFirstPublicationCli passes process.cwd() to the new curated-service loader rather than
locating the service data relative to the script or an explicit root. Even when callers provide
absolute review-file paths through the CLI flags, invoking a service plan from another working
directory makes the loader look for canonical part files there and fail before planning.
Code

scripts/publish-site-content-first-catalogue.ts[R496-497]

+    serviceSignOffContext:
+      options.kind === "form" ? undefined : await loadServiceSignOffContext("service", process.cwd()),
Relevance

●●● Strong

CLI loaders should resolve repository data independently of working directory; path portability
fixes are routinely accepted.

PR-#2486
PR-#2557

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The CLI accepts review paths, but the newly added context load has an independent working-directory
dependency: the loader appends the canonical-data directory to the supplied root.

scripts/publish-site-content-first-catalogue.ts[450-465]
scripts/publish-site-content-first-catalogue.ts[490-498]
scripts/lib/signoff-kinds/services.mjs[263-269]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new service loader assumes the process working directory is the repository root, even when review paths are explicitly supplied.
## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[493-498]
- scripts/lib/signoff-kinds/services.mjs[263-269]
## Recommended Fix
Resolve the canonical service directory from a stable project location or accept an explicit project root, and test a service-plan invocation from a different working directory with absolute review paths.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View resolved (3)
4. Missing record reported as edited content ✓ Resolved
Description
recordPinState catches every error thrown by the kind's attested function and returns "stale",
and validateSignOffEntry turns any non-current state into "content changed since sign-off …
re-review it with npm run clinical:review". When a form code is missing from
data/forms-catalog.json, or a service review row has no curated record, the operator is told to
re-review, but re-reviewing can't fix a record that isn't there, so the real cause stays hidden.
Code

scripts/publish-site-content-first-catalogue.ts[R210-217]

+  if (pin !== "current") {
+    return {
+      kind,
+      recordId,
+      slug,
+      reason:
+        "content changed since sign-off (reviewedContentSha256 no longer matches); re-review it with npm run clinical:review",
+    };
Relevance

●●● Strong

Missing review data should be classified distinctly; repository precedents require unavailable
inputs to fail explicitly.

PR-#2173
PR-#2733

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The form attested function throws when the catalog has no entry, and the service curatedService
throws when the id is missing. recordPinState turns both errors into stale, and the new branch
gives every stale case the same "content changed" reason.

scripts/lib/clinical-record-review-contract.mjs[867-874]
scripts/lib/clinical-record-review-contract.mjs[713-717]
scripts/lib/signoff-kinds/services.mjs[52-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A missing catalog entry or curated record is reported as "content changed since sign-off", which sends the operator the wrong way.

## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[140-152]
- scripts/publish-site-content-first-catalogue.ts[201-218]

## Recommended Fix
In `createSignOffPinCheck`, wrap the call in try/catch and call `recordContentSha256` directly. Return `unverifiable` when it throws (and put the error message in the rejection reason), and return `stale` only when the digests differ. Also catch failures reading or parsing the forms catalog and return `unverifiable`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Panel ignores its default props when given shared state ✓ Resolved
Description
When state is passed, ClinicalMathPanel still calls `useClinicalMathPanelState({ defaultOpen,
defaultTab }) and then throws that copy away, so defaultOpen and defaultTab` quietly do nothing.
A later caller who writes <ClinicalMathPanel state={s} defaultOpen /> gets no effect and no
warning, and every mount keeps 16 unused state slots.
Code

src/components/calculators/clinical-math-panel.tsx[R97-103]

+export function ClinicalMathPanel({
+  defaultOpen = false,
+  defaultTab = "renal",
+  state,
+}: ClinicalMathPanelProps & { state?: ClinicalMathPanelState }) {
+  const panelId = useId();
+  const ownState = useClinicalMathPanelState({ defaultOpen, defaultTab });
Relevance

●●● Strong

Passed shared state makes the hook-created defaults ineffective; this is a deterministic local
component bug.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Line 103 always creates its own state, and line 135 picks state ?? ownState, so the defaults only
reach the copy that gets discarded.

src/components/calculators/clinical-math-panel.tsx[97-135]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`defaultOpen` and `defaultTab` are quietly ignored when `state` is supplied.

## Fix Focus Areas
- src/components/calculators/clinical-math-panel.tsx[97-135]

## Recommended Fix
Use a discriminated-union props type so callers pass either `state` or `defaultOpen`/`defaultTab`, never both. Or split it into a controlled inner panel that takes `state`, plus a thin uncontrolled wrapper that calls the hook.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Typing in a calculator re-renders the whole page ✓ Resolved
Description
useClinicalMathPanelState() now runs in CalculatorsSearchPage, so every keystroke in a CrCl, QTc
or lithium field updates state there and re-renders the whole calculators search page, including its
result lists, sidebar panels and layout. Before this change only ClinicalMathPanel re-rendered, so
typing on a large calculator catalogue on lower-end devices now does much more work per key.
Code

src/components/calculators/search-page.tsx[348]

+  const clinicalMath = useClinicalMathPanelState();
Relevance

●● Moderate

The re-render cost is plausible, but state lifting is intentional and performance evidence is
subjective.

PR-#3152

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Every setter returned by the hook is a useState setter owned by CalculatorsSearchPage, and that
component has no memo boundaries (grep for memo( finds nothing), so a state change re-renders
its whole subtree.

src/components/calculators/clinical-math-panel.tsx[38-59]
src/components/calculators/search-page.tsx[345-351]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The calculator state now lives in the page component, so every keystroke re-renders the whole calculators page.

## Fix Focus Areas
- src/components/calculators/search-page.tsx[348-348]
- src/components/calculators/search-page.tsx[606-618]

## Recommended Fix
Move the shared state into a small client component that owns `useClinicalMathPanelState`, for example a context provider placed around the layout that renders only the panel consumers. Alternatively, wrap the heavy sibling subtrees in `React.memo` so a calculator keystroke doesn't re-render search results.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 9 rules
✅ Cross-repo context — repo relationships
Review mode: Auto: 🚀 Fast: Localized offline validation changes with limited, self-contained behavioral impact.
✅ Fix-loop round: fix loop

Grey Divider

Tip of the day
💡 Did you know, you can pick a display mode instead of tweaking every Display option by hand

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit cfcffe1

Results up to commit fe0f259 🧠 Deep


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required

No findings for this group


Remediation recommended

No findings for this group


Informational

No findings for this group


Resolved findings

1. Service details bypass clinical sign-off ✗ Dismissed
Description
createSignOffPinCheck validates the review and its curated or catalogue context, but does not
verify the ServiceRecord or FormRecord selected for publication; defaultServiceRecords() can
also retain legacy fields outside the curated service pin. If a caller edits a selected record
without changing its valid review, or a snapshot entry comes to match a signed standalone service,
the pin still passes while the edited fields or legacy cost reach the publication plan.
Code

scripts/publish-site-content-first-catalogue.ts[R145-147]

+    if (kind === "service") {
+      if (!options.serviceContext) return "unverifiable";
+      return recordPinState(review, "service", options.serviceContext);
Relevance

●●● Strong

Signed hashes must cover every published field; prior governance precedents accept omitted-input
integrity fixes.

PR-#2580
PR-#2878

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The check receives and hashes the review and its context, while the builder independently converts
the selected record into a publication row. Consequently, changing a selected record’s title changes
the row without changing the checked digest; the default service-record merge likewise preserves
legacy cost information and maps it into the published service record despite the check hashing the
curated record.

scripts/publish-site-content-first-catalogue.ts[140-150]
scripts/publish-site-content-first-catalogue.ts[249-264]
src/lib/service-governance.ts[339-355]
src/lib/service-catalog-mapper.ts[455-472]
scripts/publish-site-content-first-catalogue.ts[139-151]
scripts/publish-site-content-first-catalogue.ts[264-275]
scripts/publish-site-content-first-catalogue.ts[287-324]
scripts/publish-site-content-first-catalogue.ts[222-237]
src/lib/registry-records.ts[57-86]
src/lib/service-governance.ts[339-352]
Skill: source-governance

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A current review pin can pass even when the selected publication record contains edited content or legacy service fields not covered by that pin.

## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[139-151]
- scripts/publish-site-content-first-catalogue.ts[222-237]
- scripts/publish-site-content-first-catalogue.ts[285-324]
- src/lib/service-governance.ts[339-355]
- tests/site-content-first-publication-cli.test.ts[136-161]

## Recommended Fix
Before accepting a selected service or form record, verify that its publishable content matches or is derived solely from the content covered by its review pin. Refuse a merged legacy service record when that relationship cannot be established. Add tests for edited caller-supplied records and for a signed standalone service that gains a matching snapshot entry with different legacy cost information.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. One review can approve another record ✗ Dismissed
Description
validateSignOffEntry checks the pin on the review returned by an alias lookup without requiring
that review's id or code to identify the selected record. When a signed review's slug matches
another service or form, its pin is checked against its own content and can authorize publication of
that other record.
Code

scripts/publish-site-content-first-catalogue.ts[294]

+    const problem = validateSignOffEntry("service", stableId, service.slug, review, pinState);
Relevance

●●● Strong

Alias-based approval without selected-record identity is an authorization mismatch, consistent with
accepted canonical-selection fixes.

PR-#2878
PR-#3114

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The lookup indexes reviews by multiple keys, including slug, but the attestation resolves content by
the review's own ID or code. The new pin check consequently cannot establish which selected record
that review authorizes.

scripts/publish-site-content-first-catalogue.ts[267-274]
scripts/publish-site-content-first-catalogue.ts[287-294]
scripts/publish-site-content-first-catalogue.ts[296-319]
scripts/lib/signoff-kinds/services.mjs[47-56]
scripts/lib/clinical-record-review-contract.mjs[704-721]
scripts/lib/clinical-record-review-contract.mjs[856-874]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Alias lookup can select a valid pin for a different publication target.
## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[287-294]
- scripts/publish-site-content-first-catalogue.ts[310-319]
- scripts/publish-site-content-first-catalogue.ts[154-201]
## Recommended Fix
Before accepting a current pin, require the review's canonical service ID or form code to match the selected target's canonical identity. Reject conflicting aliases and test a current review whose slug points to another record.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Service plans fail outside the project root ✓ Resolved
Description
runFirstPublicationCli passes process.cwd() to the new curated-service loader rather than
locating the service data relative to the script or an explicit root. Even when callers provide
absolute review-file paths through the CLI flags, invoking a service plan from another working
directory makes the loader look for canonical part files there and fail before planning.
Code

scripts/publish-site-content-first-catalogue.ts[R496-497]

+    serviceSignOffContext:
+      options.kind === "form" ? undefined : await loadServiceSignOffContext("service", process.cwd()),
Relevance

●●● Strong

CLI loaders should resolve repository data independently of working directory; path portability
fixes are routinely accepted.

PR-#2486
PR-#2557

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The CLI accepts review paths, but the newly added context load has an independent working-directory
dependency: the loader appends the canonical-data directory to the supplied root.

scripts/publish-site-content-first-catalogue.ts[450-465]
scripts/publish-site-content-first-catalogue.ts[490-498]
scripts/lib/signoff-kinds/services.mjs[263-269]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new service loader assumes the process working directory is the repository root, even when review paths are explicitly supplied.
## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[493-498]
- scripts/lib/signoff-kinds/services.mjs[263-269]
## Recommended Fix
Resolve the canonical service directory from a stable project location or accept an explicit project root, and test a service-plan invocation from a different working directory with absolute review paths.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View resolved (3)
4. Panel ignores its default props when given shared state ✓ Resolved
Description
When state is passed, ClinicalMathPanel still calls `useClinicalMathPanelState({ defaultOpen,
defaultTab }) and then throws that copy away, so defaultOpen and defaultTab` quietly do nothing.
A later caller who writes <ClinicalMathPanel state={s} defaultOpen /> gets no effect and no
warning, and every mount keeps 16 unused state slots.
Code

src/components/calculators/clinical-math-panel.tsx[R97-103]

+export function ClinicalMathPanel({
+  defaultOpen = false,
+  defaultTab = "renal",
+  state,
+}: ClinicalMathPanelProps & { state?: ClinicalMathPanelState }) {
+  const panelId = useId();
+  const ownState = useClinicalMathPanelState({ defaultOpen, defaultTab });
Relevance

●●● Strong

Passed shared state makes the hook-created defaults ineffective; this is a deterministic local
component bug.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Line 103 always creates its own state, and line 135 picks state ?? ownState, so the defaults only
reach the copy that gets discarded.

src/components/calculators/clinical-math-panel.tsx[97-135]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`defaultOpen` and `defaultTab` are quietly ignored when `state` is supplied.

## Fix Focus Areas
- src/components/calculators/clinical-math-panel.tsx[97-135]

## Recommended Fix
Use a discriminated-union props type so callers pass either `state` or `defaultOpen`/`defaultTab`, never both. Or split it into a controlled inner panel that takes `state`, plus a thin uncontrolled wrapper that calls the hook.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Missing record reported as edited content ✓ Resolved
Description
recordPinState catches every error thrown by the kind's attested function and returns "stale",
and validateSignOffEntry turns any non-current state into "content changed since sign-off …
re-review it with npm run clinical:review". When a form code is missing from
data/forms-catalog.json, or a service review row has no curated record, the operator is told to
re-review, but re-reviewing can't fix a record that isn't there, so the real cause stays hidden.
Code

scripts/publish-site-content-first-catalogue.ts[R210-217]

+  if (pin !== "current") {
+    return {
+      kind,
+      recordId,
+      slug,
+      reason:
+        "content changed since sign-off (reviewedContentSha256 no longer matches); re-review it with npm run clinical:review",
+    };
Relevance

●●● Strong

Missing review data should be classified distinctly; repository precedents require unavailable
inputs to fail explicitly.

PR-#2173
PR-#2733

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The form attested function throws when the catalog has no entry, and the service curatedService
throws when the id is missing. recordPinState turns both errors into stale, and the new branch
gives every stale case the same "content changed" reason.

scripts/lib/clinical-record-review-contract.mjs[867-874]
scripts/lib/clinical-record-review-contract.mjs[713-717]
scripts/lib/signoff-kinds/services.mjs[52-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A missing catalog entry or curated record is reported as "content changed since sign-off", which sends the operator the wrong way.

## Fix Focus Areas
- scripts/publish-site-content-first-catalogue.ts[140-152]
- scripts/publish-site-content-first-catalogue.ts[201-218]

## Recommended Fix
In `createSignOffPinCheck`, wrap the call in try/catch and call `recordContentSha256` directly. Return `unverifiable` when it throws (and put the error message in the rejection reason), and return `stale` only when the digests differ. Also catch failures reading or parsing the forms catalog and return `unverifiable`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Typing in a calculator re-renders the whole page ✓ Resolved
Description
useClinicalMathPanelState() now runs in CalculatorsSearchPage, so every keystroke in a CrCl, QTc
or lithium field updates state there and re-renders the whole calculators search page, including its
result lists, sidebar panels and layout. Before this change only ClinicalMathPanel re-rendered, so
typing on a large calculator catalogue on lower-end devices now does much more work per key.
Code

src/components/calculators/search-page.tsx[348]

+  const clinicalMath = useClinicalMathPanelState();
Relevance

●● Moderate

The re-render cost is plausible, but state lifting is intentional and performance evidence is
subjective.

PR-#3152

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Every setter returned by the hook is a useState setter owned by CalculatorsSearchPage, and that
component has no memo boundaries (grep for memo( finds nothing), so a state change re-renders
its whole subtree.

src/components/calculators/clinical-math-panel.tsx[38-59]
src/components/calculators/search-page.tsx[345-351]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The calculator state now lives in the page component, so every keystroke re-renders the whole calculators page.

## Fix Focus Areas
- src/components/calculators/search-page.tsx[348-348]
- src/components/calculators/search-page.tsx[606-618]

## Recommended Fix
Move the shared state into a small client component that owns `useClinicalMathPanelState`, for example a context provider placed around the layout that renders only the panel consumers. Alternatively, wrap the heavy sibling subtrees in `React.memo` so a calculator keystroke doesn't re-render search results.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

You’re at about 91% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

@cubic-dev-ai

cubic-dev-ai Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Auto-fix isn't included in your plan ↗

Upgrade to Team

A review matched by slug alias could carry a current pin for a different
record. The plan now requires the review's own id (service) or code (form)
to be the record being published. The curated service records are loaded
from the repository root rather than the working directory.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016imb8DCuk85z3FWRDDyZx5
@codeant-ai

codeant-ai Bot commented Oct 16, 2026

Copy link
Copy Markdown

CodeAnt PR Risk: Low Risk

  • The PR appears safe to merge; no concrete blocking issue is evident in the changed code.
  • Publication now refuses sign-offs with stale or unverifiable content pins, and the CLI loads the service sign-off context before checking them.
  • The calculator page keeps entered values in parent state so they persist when the panel moves across the desktop breakpoint; a regression test covers this.

Assessed commit: fe0f2591ff5a

gitar-bot[bot]
gitar-bot Bot previously approved these changes Oct 16, 2026

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR (configure)

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit a7e6bc1

- Reject unsigned merged service details
- Require matching reviewed record identities
- Resolve curated data from project root
- Separate missing-content errors from real drift
@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo Fixer

✅ Committed (6) · ☑ Fixed (6)

Grey Divider

Commits pushed directly to this PR — no separate fix PR opened.

Process — 6 fixed
  • ☑ Fixed: Service details bypass clinical sign-off
  • ☑ Fixed: One review can approve another record
  • ☑ Fixed: a66a52a5-0b25-4b6d-a936-fe0f2591ff5
  • ☑ Fixed: Missing record reported as edited content
  • ☑ Fixed: Panel ignores its default props when given shared state
  • ☑ Fixed: Typing in a calculator re-renders the whole page

@gitar-bot
gitar-bot Bot disabled auto-merge October 16, 2026 11:13
…ollow-ups

The bot's search-page change gave each layout its own calculator state again,
so entries were lost across the 1280px resize (the fix this PR exists for), and
its publish-script rewrite changed refusal behaviour (a new legacy-cost refusal)
without review. Restores the reviewed a7e6bc1 code. Reverts 5ebcb55,
11f5961 and 11d42e2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016imb8DCuk85z3FWRDDyZx5

Copy link
Copy Markdown
Owner Author

Reverted the three Qodo Fixer commits (5ebcb55, 11f5961, 11d42e2) in cfcffe1, which restores the reviewed a7e6bc1 tree exactly.

  • The new ClinicalMathPanels wrapper mounts a separate instance in the sidebar and in the mobile column, so each has its own useClinicalMathPanelState. Calculator entries were lost across the 1280px resize again, and tests/clinical-math-panel-breakpoint.dom.test.tsx went red. Keeping that state through the resize is the whole point of this PR.
  • The publish-script rewrite added a refusal for any service carrying legacy cost text, which is unreviewed policy. It also replaced the specific refusal reasons that the tests pin, so two tests failed.
  • The earlier threads on these findings were already answered and resolved. The "missing record reported as edited content" finding was optional and stays as is.

With the revert, the two regression suites pass 14 of 14 locally.


Generated by Claude Code

@qodo-code-review

qodo-code-review Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

No code changes since the last review — review skipped

Qodo Logo

@gitar-bot
gitar-bot Bot enabled auto-merge (squash) October 16, 2026 11:14

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR (configure)

@gitar-bot

gitar-bot Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor
Code Review ✅ Approved 2 closed / 2 findings

🔴 High risk · Recomputing sign-off pins changes the clinical-content publication gate; incorrect checks could block approved guidance or allow stale clinical content to publish.

Sign-off checks now recompute each first-publication content pin, refusing stale or unverifiable records, and the calculator page keeps a single state across the 1280 px breakpoint. Two issues from this session were resolved: calculator state is reset at the breakpoint again, and the form identity check falls back to review.id when the code is missing. No open findings remain.

✅ 2 closed
✅ Bug: Calculator state is reset at the breakpoint again

📄 src/components/calculators/search-page.tsx:332-340 📄 src/components/calculators/search-page.tsx:618 📄 src/components/calculators/search-page.tsx:625
useClinicalMathPanelState() now runs inside ClinicalMathPanels, and the page creates one ClinicalMathPanels in sidebar and a separate one in sidebarMobile. Each is rendered only when its isDesktopSidebar condition holds. When the window crosses 1280 px, one instance unmounts with its state and the other mounts with empty state. That brings back the bug this PR set out to fix: CrCl, QTc and lithium entries are lost on resize. The inner ternaries in ClinicalMathPanels also do nothing, because the caller has already gated on the same flag. The fix is to put the hook back in CalculatorsSearchPage (a component that does not unmount) and pass the same state to both mount points.

✅ Security: Form identity check falls back to review.id when code is missing

📄 scripts/publish-site-content-first-catalogue.ts:229-232
In the previous commit, a form sign-off had to name the form by its own code. The new check uses review.code ?? review.id, so a form review with no code now passes on id alone. The pin is then recomputed with recordContentSha256(review, "form", ...), which looks up the form by the review's code. If that lookup does not resolve through id in the same way, a review missing code can pass the identity check while its pin is computed against different content, or none. This weakens the rule that "a sign-off must name the record it publishes". The fix is to require review.code for forms, as before, or to confirm that the contract keys forms by id when code is missing.

Verification

Rules No rules evaluated

Functional validation Not enabled

Set up

Auto-approval Approved

For more verification details, comment gitar display:verbose.

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing compact verification results.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Important

Your trial ends in 5 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more.

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Owner Author

Production UI (3) failed one test on cfcffe1: tests/ui-tools.spec.ts:1548 "services query param fallback ignores whitespace-only q values". It timed out in expectHydrated while loading the legacy tools launcher, and the other 261 tests in the shard passed.

I don't think this PR caused it. The PR only changes the first-publication script, the bedside calculator panel and the calculators search page. Nothing here touches the tools launcher or services routing, and the failure is a hydration timeout, not an assertion about content. I'll re-run the failed job once to confirm.


Generated by Claude Code

@gitar-bot
gitar-bot Bot merged commit 37217d7 into main Oct 16, 2026
69 of 71 checks passed
@gitar-bot
gitar-bot Bot deleted the claude/pr-3574-resolve-0lrep3 branch October 16, 2026 11:37
BigSimmo pushed a commit that referenced this pull request Oct 16, 2026
Main carries #3574 (squash of this branch's earlier commits) and #3575, which
already ships a stricter sign-off pin check. This merge keeps main's pin check,
adds this branch's --execute credential guard, drops a broken bot commit
(b0adab7), and repairs two others (stray JSX after the handover page's last
line, and a setState-in-effect lint error in the note editor).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016imb8DCuk85z3FWRDDyZx5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔴 Large blast radius size:L This PR changes 100-499 lines, ignoring generated files 🕐 40+ Minutes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants