A0) Global Policy (applies to A1–A3)
A0.1 Gemini Usage Reduction Mandate
Use Gemini only in tightly controlled cases:
At PR open (single pass)
One initial review pass only if deterministic gates are green.
At PR merge queue (optional)
Only for high-risk label + changed files hitlist.
No per-commit auto-invocation
Remove “review-on-every-update” behavior unless explicitly labeled.
Hard Constraints
Max Gemini invocations per PR: 1 default, 2 with ai:required label.
If lint/type/knip fails → Gemini must not run.
If only docs/comments changed → Gemini must not run.
If only formatting changes → Gemini must not run.
A0.2 Orchestration Principles
Deterministic checks are the gatekeeper.
AI is an escalation path, not the default path.
All AI runs must include a reason code (e.g., risk_file_touched, security_sensitive_change).
Add telemetry per PR: deterministic_fail, ai_skipped, ai_invoked, tokens_used.
A1) Deterministic Gate Before AI Reasoning
A1.1 Workflow order (strict)
eslint
tsc --noEmit
knip
optional: unit-smoke (fast suite)
Only then: Gemini conditional step
A1.2 Fail-fast behavior
First failing deterministic step stops pipeline branch.
Post a diagnostic PR comment with:
failed command
top 20 errors (truncated)
remediation hints
Mark check as failed; do not invoke Gemini.
A1.3 High-risk trigger list for Gemini
Run Gemini only if changed files match any of:
server.ts
middleware.ts
context/WebSocketContext.tsx (until deprecated)
context/webSocketReducer.ts (until migrated)
hooks/useBluetoothHRM.ts
auth, security, workflow configs (.github/workflows/**)
dependency manifests (package.json, lockfile) if major versions changed
Also run if PR has labels:
ai:required
risk:high
security:review
A1.4 Event reduction strategy
Trigger on:
pull_request opened/reopened/ready_for_review
Do not trigger on:
synchronize (by default)
draft updates
label changes (unless ai:required applied)
Optional manual override:
workflow_dispatch with force_ai=true.
A1.5 Acceptance criteria (expanded)
Lint/type/knip failure blocks AI 100% of the time.
Gemini skipped for low-risk PRs with green deterministic checks.
Gemini runs only when risk trigger or explicit label applies.
Invocation count + reason recorded in summary artifact.
A2) Jules Direct-Action Mode
A2.1 CLI contract for jules_ops.py
Add explicit modes:
--mode audit (default, current behavior)
--mode direct (new tactical mode)
Backward compatibility: --direct maps to --mode direct
direct mode behavior
Skip debt-issue generation workflow entirely.
Create branch + patch + PR draft directly.
Attach deterministic checks output in PR body.
audit mode behavior
Preserve issue-first flow and artifact generation.
A2.2 Safety gates for direct mode
Direct mode allowed only when:
deterministic checks pass, and
PR scope is low/medium risk, and
no restricted paths unless --allow-risk-paths flag is set.
A2.3 Observability
Emit structured run summary:
mode used
issue created? (bool)
PR created? (bool)
skipped reason(s)
A2.4 Acceptance criteria (expanded)
--direct creates PR draft with no debt issue.
--mode audit unchanged.
Mode selection visible in logs + CI summary.
A3) Architectural Boundary Lint Rules
A3.1 Rules to add
no-restricted-imports
block transport libs (ws, socket libs) in component tree.
path boundaries
block utils/logger.server imports from client/components.
optional strict rule
block direct WebSocket construction in component files.
A3.2 Error message standard
Each lint violation must say:
why forbidden
where to move logic (services/, hooks/, context adapter)
link to architecture doc section
A3.3 Acceptance criteria (expanded)
Import boundary violations fail CI.
Developer gets actionable remediation message.
Rule exceptions require inline justification + approval label.
A4) Workflow Cleanup: Remove or Fix Broken Pipelines
A4.1 Inventory and classify all workflows
Create a matrix:
Keep (works + valuable)
Fix (valuable but broken/flaky)
Deprecate (unused or superseded)
Delete (non-functional with no owner/use)
A4.2 Mandatory actions
Remove duplicate AI workflows.
Consolidate to one orchestration entrypoint.
Fix Jules workflows to support direct mode path.
Remove dead jobs and unreachable workflow branches.
Enforce owner tags for each workflow file.
A4.3 “No orphan workflow” policy
A workflow must have:
owner
trigger rationale
success metrics
runbook link
Otherwise: mark deprecated and remove in next sprint.
A4.4 Acceptance criteria
Every workflow has owner + purpose.
Broken workflows either fixed or removed within sprint.
CI runtime reduced (target: 20–40% faster for standard PRs).
AI-triggered runs reduced significantly (target: 60–90% fewer).
A5) Suggested GitHub Actions design (reference)
Stage 1 — pr-quality-fast
lint/type/knip
upload diagnostics
fail fast
Stage 2 — ai-gate-decision
evaluate changed files + labels + deterministic results
output run_ai=true/false, reason
Stage 3 — gemini-review (conditional)
only if run_ai=true
single invocation unless ai:required
Stage 4 — workflow-health
verifies no deprecated/broken workflow references
A6) Rollout plan (1 sprint)
Days 1–2
Implement deterministic gate + fail-fast diagnostics.
Add changed-file/label risk gate.
Days 3–4
Implement Jules --mode direct.
Add compatibility + logs.
Day 5
Add boundary lint rules + clear messages.
Fix/remove obsolete workflows and publish workflow ownership matrix.
A7) Definition of Done for Epic A
Epic A is done when:
Deterministic checks always precede any AI.
Gemini invocations are rare, justified, and capped.
Jules direct mode works and audit mode remains intact.
Boundary lint rules block forbidden imports.
Broken/unused workflows are removed or repaired.
CI is faster, cleaner, and cheaper in token/runtime usage.
- GitHub Actions: ai-gate-decision (exact pattern)
Use this as a reusable job inside your PR workflow (or as its own workflow).
name: pr-quality
on:
pull_request:
types: [opened, reopened, ready_for_review, synchronize, labeled]
workflow_dispatch:
inputs:
force_ai:
description: "Force Gemini review"
required: false
default: "false"
permissions:
contents: read
pull-requests: write
jobs:
deterministic:
name: Deterministic checks
runs-on: ubuntu-latest
outputs:
passed: ${{ steps.set_result.outputs.passed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- name: ESLint
id: eslint
run: pnpm lint
- name: Typecheck
id: tsc
run: pnpm tsc --noEmit
- name: Knip
id: knip
run: pnpm knip
- name: Set deterministic result
id: set_result
if: ${{ success() }}
run: echo "passed=true" >> "$GITHUB_OUTPUT"
- name: Set deterministic result (failure)
if: ${{ failure() }}
run: echo "passed=false" >> "$GITHUB_OUTPUT"
ai_gate_decision:
name: AI gate decision
runs-on: ubuntu-latest
needs: deterministic
outputs:
run_ai: ${{ steps.decide.outputs.run_ai }}
reason: ${{ steps.decide.outputs.reason }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Gather changed files
id: changed
uses: tj-actions/changed-files@v45
with:
files_yaml: |
risk:
- server.ts
- middleware.ts
- context/WebSocketContext.tsx
- context/webSocketReducer.ts
- hooks/useBluetoothHRM.ts
- .github/workflows/**
- package.json
- pnpm-lock.yaml
docs_only:
- "**/*.md"
- "**/*.mdx"
- "docs/**"
- name: Decide whether to run AI
id: decide
env:
DETERMINISTIC_PASSED: ${{ needs.deterministic.outputs.passed }}
FORCE_AI: ${{ inputs.force_ai || 'false' }}
PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
ANY_CHANGED: ${{ steps.changed.outputs.any_changed }}
RISK_CHANGED: ${{ steps.changed.outputs.risk_any_changed }}
DOCS_ONLY: ${{ steps.changed.outputs.only_changed == 'true' && steps.changed.outputs.docs_only_any_changed == 'true' }}
EVENT_NAME: ${{ github.event_name }}
EVENT_ACTION: ${{ github.event.action }}
shell: bash
run: |
run_ai=false
reason=""
# Hard stop: deterministic fail
if [[ "$DETERMINISTIC_PASSED" != "true" ]]; then
echo "run_ai=false" >> "$GITHUB_OUTPUT"
echo "reason=deterministic_failed" >> "$GITHUB_OUTPUT"
exit 0
fi
# Force override
if [[ "$FORCE_AI" == "true" ]]; then
echo "run_ai=true" >> "$GITHUB_OUTPUT"
echo "reason=manual_force" >> "$GITHUB_OUTPUT"
exit 0
fi
# Docs-only skip
if [[ "$DOCS_ONLY" == "true" ]]; then
echo "run_ai=false" >> "$GITHUB_OUTPUT"
echo "reason=docs_only" >> "$GITHUB_OUTPUT"
exit 0
fi
# Label-driven allowlist
if echo "$PR_LABELS" | grep -Eiq '"ai:required"|"risk:high"|"security:review"'; then
echo "run_ai=true" >> "$GITHUB_OUTPUT"
echo "reason=label_trigger" >> "$GITHUB_OUTPUT"
exit 0
fi
# Risk file trigger
if [[ "$RISK_CHANGED" == "true" ]]; then
echo "run_ai=true" >> "$GITHUB_OUTPUT"
echo "reason=risk_file_changed" >> "$GITHUB_OUTPUT"
exit 0
fi
# Aggressive reduction default
echo "run_ai=false" >> "$GITHUB_OUTPUT"
echo "reason=low_risk_skip" >> "$GITHUB_OUTPUT"
- name: Post gate summary
uses: actions/github-script@v7
with:
script: |
const runAi = "${{ steps.decide.outputs.run_ai }}";
const reason = "${{ steps.decide.outputs.reason }}";
const body = `### AI Gate Decision\n- run_ai: **${runAi}**\n- reason: \`${reason}\``;
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body
});
gemini_review:
name: Gemini review (conditional)
needs: [deterministic, ai_gate_decision]
if: ${{ needs.ai_gate_decision.outputs.run_ai == 'true' }}
runs-on: ubuntu-latest
steps:
- run: echo "Invoke Gemini once here. reason=${{ needs.ai_gate_decision.outputs.reason }}"
# add your actual Gemini invocation action/script
2) PR Template Checklist (drop-in)
Create/update .github/pull_request_template.md:
Summary
Risk & Scope
Architecture Compliance
Service/Store Impact
Auth/Security
Testing
Accessibility
- Workflow Ownership Metadata Checklist (for each workflow file)
Add as front-matter comment at top of each workflow (or maintain in a separate docs/workflow-owners.md table):
owner: @team-devex
purpose: Deterministic PR quality gate and conditional AI review
triggers: pull_request(opened,reopened,ready_for_review,synchronize,labeled)
sla: P1 failures acknowledged within 1 business day
deprecation_date: n/a
runbook: docs/runbooks/pr-quality.md
metrics:
- median_duration
- failure_rate
- ai_invocation_rate
- deterministic_fail_rate
Review checklist for cleanup
Has owner
Has purpose
Trigger still needed
Not duplicated by another workflow
Has runbook
Has success metrics
Passes dry-run test
If not, mark deprecated and remove this sprint
- Jules CLI mode contract (quick spec)
jules_ops.py --mode audit # default, create debt issue + follow audit flow
jules_ops.py --mode direct # skip issue creation, open tactical PR draft
jules_ops.py --direct # alias for --mode direct
Guardrails:
Direct mode blocked on deterministic failure.
Direct mode blocked for high-risk files unless --allow-risk-paths.
If you want, next I can provide:
a minimal jules_ops.py argparse patch, and
a single consolidated pr-quality.yml that wires deterministic → decision → conditional Gemini end-to-end.
A0) Global Policy (applies to A1–A3)
A0.1 Gemini Usage Reduction Mandate
Use Gemini only in tightly controlled cases:
At PR open (single pass)
One initial review pass only if deterministic gates are green.
At PR merge queue (optional)
Only for high-risk label + changed files hitlist.
No per-commit auto-invocation
Remove “review-on-every-update” behavior unless explicitly labeled.
Hard Constraints
Max Gemini invocations per PR: 1 default, 2 with ai:required label.
If lint/type/knip fails → Gemini must not run.
If only docs/comments changed → Gemini must not run.
If only formatting changes → Gemini must not run.
A0.2 Orchestration Principles
Deterministic checks are the gatekeeper.
AI is an escalation path, not the default path.
All AI runs must include a reason code (e.g., risk_file_touched, security_sensitive_change).
Add telemetry per PR: deterministic_fail, ai_skipped, ai_invoked, tokens_used.
A1) Deterministic Gate Before AI Reasoning
A1.1 Workflow order (strict)
eslint
tsc --noEmit
knip
optional: unit-smoke (fast suite)
Only then: Gemini conditional step
A1.2 Fail-fast behavior
First failing deterministic step stops pipeline branch.
Post a diagnostic PR comment with:
failed command
top 20 errors (truncated)
remediation hints
Mark check as failed; do not invoke Gemini.
A1.3 High-risk trigger list for Gemini
Run Gemini only if changed files match any of:
server.ts
middleware.ts
context/WebSocketContext.tsx (until deprecated)
context/webSocketReducer.ts (until migrated)
hooks/useBluetoothHRM.ts
auth, security, workflow configs (.github/workflows/**)
dependency manifests (package.json, lockfile) if major versions changed
Also run if PR has labels:
ai:required
risk:high
security:review
A1.4 Event reduction strategy
Trigger on:
pull_request opened/reopened/ready_for_review
Do not trigger on:
synchronize (by default)
draft updates
label changes (unless ai:required applied)
Optional manual override:
workflow_dispatch with force_ai=true.
A1.5 Acceptance criteria (expanded)
Lint/type/knip failure blocks AI 100% of the time.
Gemini skipped for low-risk PRs with green deterministic checks.
Gemini runs only when risk trigger or explicit label applies.
Invocation count + reason recorded in summary artifact.
A2) Jules Direct-Action Mode
A2.1 CLI contract for jules_ops.py
Add explicit modes:
--mode audit (default, current behavior)
--mode direct (new tactical mode)
Backward compatibility: --direct maps to --mode direct
direct mode behavior
Skip debt-issue generation workflow entirely.
Create branch + patch + PR draft directly.
Attach deterministic checks output in PR body.
audit mode behavior
Preserve issue-first flow and artifact generation.
A2.2 Safety gates for direct mode
Direct mode allowed only when:
deterministic checks pass, and
PR scope is low/medium risk, and
no restricted paths unless --allow-risk-paths flag is set.
A2.3 Observability
Emit structured run summary:
mode used
issue created? (bool)
PR created? (bool)
skipped reason(s)
A2.4 Acceptance criteria (expanded)
--direct creates PR draft with no debt issue.
--mode audit unchanged.
Mode selection visible in logs + CI summary.
A3) Architectural Boundary Lint Rules
A3.1 Rules to add
no-restricted-imports
block transport libs (ws, socket libs) in component tree.
path boundaries
block utils/logger.server imports from client/components.
optional strict rule
block direct WebSocket construction in component files.
A3.2 Error message standard
Each lint violation must say:
why forbidden
where to move logic (services/, hooks/, context adapter)
link to architecture doc section
A3.3 Acceptance criteria (expanded)
Import boundary violations fail CI.
Developer gets actionable remediation message.
Rule exceptions require inline justification + approval label.
A4) Workflow Cleanup: Remove or Fix Broken Pipelines
A4.1 Inventory and classify all workflows
Create a matrix:
Keep (works + valuable)
Fix (valuable but broken/flaky)
Deprecate (unused or superseded)
Delete (non-functional with no owner/use)
A4.2 Mandatory actions
Remove duplicate AI workflows.
Consolidate to one orchestration entrypoint.
Fix Jules workflows to support direct mode path.
Remove dead jobs and unreachable workflow branches.
Enforce owner tags for each workflow file.
A4.3 “No orphan workflow” policy
A workflow must have:
owner
trigger rationale
success metrics
runbook link
Otherwise: mark deprecated and remove in next sprint.
A4.4 Acceptance criteria
Every workflow has owner + purpose.
Broken workflows either fixed or removed within sprint.
CI runtime reduced (target: 20–40% faster for standard PRs).
AI-triggered runs reduced significantly (target: 60–90% fewer).
A5) Suggested GitHub Actions design (reference)
Stage 1 — pr-quality-fast
lint/type/knip
upload diagnostics
fail fast
Stage 2 — ai-gate-decision
evaluate changed files + labels + deterministic results
output run_ai=true/false, reason
Stage 3 — gemini-review (conditional)
only if run_ai=true
single invocation unless ai:required
Stage 4 — workflow-health
verifies no deprecated/broken workflow references
A6) Rollout plan (1 sprint)
Days 1–2
Implement deterministic gate + fail-fast diagnostics.
Add changed-file/label risk gate.
Days 3–4
Implement Jules --mode direct.
Add compatibility + logs.
Day 5
Add boundary lint rules + clear messages.
Fix/remove obsolete workflows and publish workflow ownership matrix.
A7) Definition of Done for Epic A
Epic A is done when:
Deterministic checks always precede any AI.
Gemini invocations are rare, justified, and capped.
Jules direct mode works and audit mode remains intact.
Boundary lint rules block forbidden imports.
Broken/unused workflows are removed or repaired.
CI is faster, cleaner, and cheaper in token/runtime usage.
Use this as a reusable job inside your PR workflow (or as its own workflow).
name: pr-quality
on:
pull_request:
types: [opened, reopened, ready_for_review, synchronize, labeled]
workflow_dispatch:
inputs:
force_ai:
description: "Force Gemini review"
required: false
default: "false"
permissions:
contents: read
pull-requests: write
jobs:
deterministic:
name: Deterministic checks
runs-on: ubuntu-latest
outputs:
passed: ${{ steps.set_result.outputs.passed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ai_gate_decision:
name: AI gate decision
runs-on: ubuntu-latest
needs: deterministic
outputs:
run_ai: ${{ steps.decide.outputs.run_ai }}
reason: ${{ steps.decide.outputs.reason }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
gemini_review:
name: Gemini review (conditional)
needs: [deterministic, ai_gate_decision]
if: ${{ needs.ai_gate_decision.outputs.run_ai == 'true' }}
runs-on: ubuntu-latest
steps:
- run: echo "Invoke Gemini once here. reason=${{ needs.ai_gate_decision.outputs.reason }}"
# add your actual Gemini invocation action/script
2) PR Template Checklist (drop-in)
Create/update .github/pull_request_template.md:
Summary
Risk & Scope
Architecture Compliance
Service/Store Impact
Auth/Security
Testing
Accessibility
Add as front-matter comment at top of each workflow (or maintain in a separate docs/workflow-owners.md table):
owner: @team-devex
purpose: Deterministic PR quality gate and conditional AI review
triggers: pull_request(opened,reopened,ready_for_review,synchronize,labeled)
sla: P1 failures acknowledged within 1 business day
deprecation_date: n/a
runbook: docs/runbooks/pr-quality.md
metrics:
- median_duration
- failure_rate
- ai_invocation_rate
- deterministic_fail_rate
Review checklist for cleanup
Has owner
Has purpose
Trigger still needed
Not duplicated by another workflow
Has runbook
Has success metrics
Passes dry-run test
If not, mark deprecated and remove this sprint
jules_ops.py --mode audit # default, create debt issue + follow audit flow
jules_ops.py --mode direct # skip issue creation, open tactical PR draft
jules_ops.py --direct # alias for --mode direct
Guardrails:
Direct mode blocked on deterministic failure.
Direct mode blocked for high-risk files unless --allow-risk-paths.
If you want, next I can provide:
a minimal jules_ops.py argparse patch, and
a single consolidated pr-quality.yml that wires deterministic → decision → conditional Gemini end-to-end.