Skip to content

feat(Guardrails): add guardrails feature to Bosun#457

Open
jaeko44 wants to merge 16 commits intomainfrom
guardrails
Open

feat(Guardrails): add guardrails feature to Bosun#457
jaeko44 wants to merge 16 commits intomainfrom
guardrails

Conversation

@jaeko44
Copy link
Copy Markdown
Member

@jaeko44 jaeko44 commented Mar 26, 2026

No description provided.

Copilot AI review requested due to automatic review settings March 26, 2026 16:15
@github-actions github-actions bot added bosun-pr-public PR observed by Bosun but not trusted for high-risk automation bosun-attached Bosun PR attachment marker labels Mar 26, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 26, 2026

Bosun PR classification: public.
This PR is tracked by Bosun attachment automation.

  • PR class label: bosun-pr-public
  • Attach label: bosun-attached (yes, because attachMode=all)
  • Attach mode policy: all
  • Trusted author: no
  • Bosun-created label present: no
  • Automation scope: Public PR. Bosun observes it only and will not auto-repair or auto-merge it.
  • CI failure signal label: bosun-needs-fix
  • CI failure marker:
  • Trigger: pull_request_target / synchronize

@jaeko44 jaeko44 changed the title Guardrails feat(Guardrails): add guardrails feature to Bosun Mar 26, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new “Guardrails” policy surface across the runtime (push/hook enforcement + input-quality gating), workflows (PR quality templates + managed pre-push enforcement), and UI (new Guardrails tab + desktop layout improvements), plus supporting tooling and tests.

Changes:

  • Introduces guardrails policy storage/assessment (infra/guardrails.mjs) and wires it into server APIs, task creation, and manual flows.
  • Enforces managed-worktree push safety (pre-push bootstrap + skipHooks guardrails) and expands code-quality workflow templates for PR review/Sonar remediation.
  • Adds Guardrails UI tab + state plumbing, improves demo boot reliability + desktop layout, and adds site serving/dev tooling.

Reviewed changes

Copilot reviewed 56 out of 59 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
workspace/worktree-setup.mjs Exports ensureGitHooksPath for use by preflight/repairs.
workflow/workflow-templates.mjs Registers/exports new code-quality templates.
workflow/workflow-nodes/actions.mjs Adds cwd template fallback + managed pre-push bootstrap in push action.
workflow/workflow-nodes.mjs Guardrails enforcement for action.push_branch (skipHooks restrictions + bootstrap).
workflow-templates/github.mjs Adds GitHub PR quality signal collection snippet used by templates.
workflow-templates/code-quality.mjs Adds PR Review Quality Striker + SonarQube PR Striker templates.
ui/tabs/guardrails.js New Guardrails admin tab UI (runtime/policy/hooks/assessment).
ui/styles/layout.css Adds desktop-specific layout grid styling.
ui/modules/state.js Adds guardrails caching, loader, and WS channels.
ui/modules/router.js Adds Guardrails route/tab registration.
ui/demo.html Adds forced layout boot param + demo GitHub commit endpoints + boot failure detection changes.
ui/app.js Adds Guardrails lazy tab + emits bosun:app-mounted signal after render.
tools/vitest-runner.mjs Adjusts reporter arg filtering logic.
tools/site-serve.mjs Adds simple static server for site/.
tests/workflow-templates.test.mjs Adds/updates template expectations for new PR-quality templates and other template behavior.
tests/workflow-templates-e2e.test.mjs Adds “doesn’t crash” E2E runs for new templates.
tests/workflow-task-lifecycle.test.mjs Updates skipHooks default + adds managed-worktree skipHooks block test.
tests/workflow-guaranteed.test.mjs Adds guaranteed runs for new templates.
tests/workflow-engine.test.mjs Adds test for unresolved cwd fallback in action.run_agent.
tests/ui-server.test.mjs Adds API coverage for guardrails endpoints (policy/runtime/assess).
tests/sandbox/fixtures.mjs Adds fixtures for new templates.
tests/repo-config.test.mjs Adds tests for Claude settings normalization/repair.
tests/preflight.test.mjs Adds coverage for hooksPath auto-repair in preflight.
tests/portal-ui-smoke.node.test.mjs Smoke coverage for Guardrails route/tab registration.
tests/hook-profiles.test.mjs Updates expectations for portable bridge paths + adds gemini/opencode coverage.
tests/hook-library.test.mjs Adds coverage for the new “block agent direct push” safety hook.
tests/guardrails.test.mjs Adds unit tests for guardrails policy persistence, assessment, and repo guardrail detection.
tests/github-pr-trust-regression.test.mjs Updates regressions for Bosun-created provenance detection and branch sync workflow.
tests/demo-api-sync.test.mjs Marks guardrails endpoints as intentionally server-only in demo sync test.
tests/codex-shell.test.mjs Updates Codex runtime/profile tests (home resolution, provider selection, sandbox injection).
tests/agent-supervisor.test.mjs Updates supervisor behavior for workflow-owned push lifecycle.
tests/agent-pool.test.mjs Adds Windows Codex runtime prereq checks + deterministic failure handling tests.
site/ui/styles/layout.css Mirrors desktop layout styling into site UI copy.
site/ui/modules/state.js Mirrors guardrails state plumbing into site UI copy.
site/ui/modules/router.js Mirrors Guardrails route/tab registration into site UI copy.
site/ui/demo.html Mirrors demo boot/layout + GitHub commit simulation logic into site UI copy.
site/ui/app.js Mirrors Guardrails lazy tab + mount event signaling into site UI copy.
site/README.md Updates local dev instructions to use npm run site:serve.
shell/opencode-providers.mjs Replaces promisify wrappers with explicit Promise wrappers capturing stdout/stderr.
shell/codex-model-profiles.mjs Adds env-driven home directory resolution for reading Codex config.
server/ui-server.mjs Adds guardrails endpoints + enforces INPUT guardrails on task/manual-flow requests + broadcasts invalidations.
package.json Adds site:serve script + ships infra/guardrails.mjs in package files allowlist.
package-lock.json Updates lockfile dependency specifiers/peer flags (aligned with package.json deps).
infra/preflight.mjs Auto-repairs git core.hooksPath drift to .githooks during preflight.
infra/maintenance.mjs Tweaks git branch listing and adds encoding to spawnSync calls.
infra/guardrails.mjs New guardrails policy + repo script detection + input-quality assessment implementation.
config/repo-config.mjs Normalizes Claude permissions and uses portable bridge paths.
agent/hook-profiles.mjs Uses portable agent/agent-hook-bridge.mjs path and updates generated hook configs.
agent/hook-library.mjs Adds new blocking hook preventing direct git push when guardrails require workflow-owned pushes.
agent/agent-supervisor.mjs Adjusts “commits not pushed” guidance for workflow-owned push lifecycle.
agent/agent-prompt-catalog.mjs Updates managed-task agent instructions to avoid direct pushing and require local validation before handoff.
agent/agent-pool.mjs Adds Windows Codex runtime prereq detection + deterministic failure suppression + env cleanup for Azure keys.
_docs/AZURE_AGENTIC_INFRAOPS_BACKPORT_ANALYSIS.md Adds analysis doc (reference/background).
.vscode/tasks.json Adds “Serve Bosun Site” task.
.vscode/launch.json Adds “Serve Bosun Site” debug configuration.
.gitignore Fixes tmp/* ignore entry formatting.
.githooks/pre-push Extends adjacency patterns to include guardrails-related files.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +6638 to +6642
globalThis.addEventListener('bosun:app-mounted', function handleMounted() {
bootReady = true;
clearTimeout(bootTimeoutId);
globalThis.removeEventListener('bosun:app-mounted', handleMounted);
});
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

Same boot sequencing problem as ui/demo.html: the bosun:app-mounted listener is registered after the app.js module script, so the event can be emitted before the listener exists, triggering false boot-failure UI. Move the listener setup before the app.js script tag (or add a persistent mounted flag that the boot script can read).

Copilot uses AI. Check for mistakes.
Comment on lines 333 to 338
`Agent cwd resolved from unresolved template (${resolvedCwd}) to ${cwd}`,
"warn",
);
}
const toolContract = buildWorkflowAgentToolContract(cwd, agentProfileId);
const trackedTaskId = String(
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

There is a stray early toolContract assignment here that references agentProfileId before it is declared, and it also duplicates the later toolContract definition. As written this will throw at runtime due to TDZ/ReferenceError and prevents action.run_agent from executing. Remove the premature toolContract line and keep only the later assignment after agentProfileId is computed.

Copilot uses AI. Check for mistakes.
Comment on lines 434 to +439
cwd,
repoRoot: ctx.data?.repoRoot || cwd,
repoRoot:
String(ctx.data?.repoRoot || "").trim() && !isUnresolvedTemplateToken(ctx.data?.repoRoot)
? ctx.data.repoRoot
: cwd,
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

repoRoot is defined twice in the object passed into buildArchitectEditorFrame. The first value is silently overwritten by the second, which is confusing and can mask bugs when refactoring. Remove the duplicate key and keep a single repoRoot assignment (preferably the unresolved-template-safe one).

Copilot uses AI. Check for mistakes.
Comment on lines +6638 to +6642
globalThis.addEventListener('bosun:app-mounted', function handleMounted() {
bootReady = true;
clearTimeout(bootTimeoutId);
globalThis.removeEventListener('bosun:app-mounted', handleMounted);
});
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The boot-loader listens for bosun:app-mounted, but this listener is registered in a module script that runs after the external app.js module has already executed (module scripts run in document order). That means the event will likely be missed and the timeout will incorrectly show a boot failure even when the app mounted successfully. Register the bosun:app-mounted listener before loading app.js (or persist mount state on globalThis and check it immediately).

Copilot uses AI. Check for mistakes.
const normalized = [];
const seen = new Set();

for (const rawValue of values || []) {
@jaeko44 jaeko44 added the bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair label Mar 26, 2026
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 26, 2026
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 27, 2026
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 added the bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair label Mar 27, 2026
jaeko44 and others added 3 commits March 27, 2026 21:02
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 removed the bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair label Mar 27, 2026
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 27, 2026
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 27, 2026
Co-authored-by: bosun-ve[bot] <262908237+bosun-ve[bot]@users.noreply.github.com>
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 28, 2026
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 28, 2026
@jaeko44 jaeko44 enabled auto-merge March 28, 2026 13:31
@jaeko44 jaeko44 added bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair and removed bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair labels Mar 28, 2026
@jaeko44 jaeko44 changed the base branch from main to repair/pr457-cwd-fallback March 28, 2026 17:07
@jaeko44 jaeko44 changed the base branch from repair/pr457-cwd-fallback to main March 29, 2026 13:46
@jaeko44
Copy link
Copy Markdown
Member Author

jaeko44 commented Mar 29, 2026

@copilot This branch has conflicts that must be resolved
Use the web editor or the command line to resolve conflicts before continuing.

Fix all conflicts (git merge origin main, fix conflicts, and push back to this branch)

Copilot AI and others added 2 commits March 29, 2026 13:54
- Resolve merge conflicts in 13 files with origin/main
- Fix boot sequencing race condition in ui/demo.html and site/ui/demo.html
  (set globalThis.__bosunAppMounted flag before dispatching event, check
  flag after listener registration to handle already-fired events)
- Remove stray toolContract TDZ reference in workflow-nodes/actions.mjs
- Fix duplicate repoRoot key in buildArchitectEditorFrame call in actions.mjs

Co-authored-by: jaeko44 <9289791+jaeko44@users.noreply.github.com>
…ated templates

- Resolve 13 merge conflicts with origin/main
- Fix boot sequencing race in demo.html (persist __bosunAppMounted flag)
- Remove stray toolContract TDZ in actions.mjs (PR review fix)
- Remove duplicate repoRoot key in buildArchitectEditorFrame (PR review fix)
- Use getProviderEndpointEnvKeys to remove non-selected Azure provider vars
- Fix agent-supervisor assess() null -> HEALTHY for workflow-owned push
- Fix ui-server guardrails test env isolation
- Align test assertions with updated workflow templates
- Regenerate demo-defaults after template changes"

Agent-Logs-Url: https://github.com/virtengine/bosun/sessions/490bc647-e5a4-416f-9bac-31ec9ebfd9d5

Co-authored-by: jaeko44 <9289791+jaeko44@users.noreply.github.com>
auto-merge was automatically disabled March 29, 2026 14:23

Head branch was pushed to by a user without write access

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 29, 2026

@copilot This branch has conflicts that must be resolved
Use the web editor or the command line to resolve conflicts before continuing.

...

Resolved. Merged origin/main into the branch and fixed all 13 conflict files. Also addressed the PR review bugs identified in the earlier review:

  • Boot sequencing race in ui/demo.html and site/ui/demo.html: now sets globalThis.__bosunAppMounted = true before dispatching the event, and the boot loader checks this flag immediately after registering the listener to handle already-fired events.
  • Stray toolContract TDZ reference in workflow/workflow-nodes/actions.mjs: removed the pre-agentProfileId assignment.
  • Duplicate repoRoot key in buildArchitectEditorFrame call: removed the duplicate, kept the safer template-check version.

All 238 test files (4536 tests) pass. Committed as 894148b7.

function buildCodexSdkRuntime(streamProviderOverrides, envInput = process.env, workingDirectory = DEFAULT_WORKING_DIRECTORY) {
const resolved = resolveCodexProfileRuntime(envInput);
const { env: resolvedEnv, configProvider } = resolved;
const runtimeDefaults = readCodexConfigRuntimeDefaults(envInput) || {};
function buildCodexSdkRuntime(streamProviderOverrides, envInput = process.env, workingDirectory = DEFAULT_WORKING_DIRECTORY) {
const resolved = resolveCodexProfileRuntime(envInput);
const { env: resolvedEnv, configProvider } = resolved;
const runtimeDefaults = readCodexConfigRuntimeDefaults(envInput) || {};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bosun-attached Bosun PR attachment marker bosun-needs-fix Attached PR with failing CI that Bosun should pick up for repair bosun-pr-public PR observed by Bosun but not trusted for high-risk automation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants