Skip to content

feat: standardize CI workflows and branch protection [OMN-7648] - #7

Merged
jonahgabriel merged 4 commits into
mainfrom
jonah/omn-7648-ci-standardization
Apr 7, 2026
Merged

jonahgabriel merged 4 commits into
mainfrom
jonah/omn-7648-ci-standardization

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Apr 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add 8 standard CI workflows matching org-wide CI/CD standards (auto-merge, pr-title-check, contract-validation, omni-standards-compliance, onex-schema-compat, linear-close-on-merge, stale-todo-gate, todo-audit-on-merge)
  • Update ci.yml with merge_group trigger and CI Summary aggregator job for branch protection gating
  • Language-agnostic workflows copied directly from omniclaude reference; repo-specific workflows adapted for omnimarket's Python/uv structure

Test plan

  • Verify all 9 workflows appear in GitHub Actions tab
  • Confirm CI Summary job passes on this PR
  • Configure branch protection to require CI Summary status check after merge
  • Enable merge queue via GitHub repo settings/rulesets after merge

Summary by CodeRabbit

  • Chores
    • Enhanced pull request validation with automated quality and standards compliance checks
    • Integrated automated ticket lifecycle management for merged pull requests
    • Added merge queue support and schema compatibility validation

Add 8 standard workflows matching org-wide CI/CD standards:
- auto-merge.yml: auto-enqueue PRs for merge queue
- pr-title-check.yml: reusable PR title convention check
- contract-validation.yml: ONEX ticket contract validation
- omni-standards-compliance.yml: repo structure and ecosystem checks
- onex-schema-compat.yml: schema version compatibility gate
- linear-close-on-merge.yml: auto-close Linear tickets on merge
- stale-todo-gate.yml: block PRs with stale TODO references
- todo-audit-on-merge.yml: create follow-up tickets for residual TODOs

Update ci.yml with merge_group trigger and CI Summary aggregator job
for branch protection gating.
@linear

linear Bot commented Apr 6, 2026

Copy link
Copy Markdown

OMN-7648

@coderabbitai

coderabbitai Bot commented Apr 6, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@jonahgabriel has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 12 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 6 minutes and 12 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e94a0c1-1d4d-4951-8305-6b0db7df1bad

📥 Commits

Reviewing files that changed from the base of the PR and between 92c23c1 and 9f30922.

📒 Files selected for processing (1)
  • .github/workflows/onex-schema-compat.yml
📝 Walkthrough

Walkthrough

The pull request adds nine new GitHub Actions workflows automating repository operations: auto-merging PRs, running CI with merge queue support, validating ONEX contracts and schemas, integrating with Linear for ticket lifecycle management (closing merged tickets and auditing TODOs), enforcing repository standards compliance, and checking PR titles.

Changes

Cohort / File(s) Summary
Auto-Merge & PR Workflows
.github/workflows/auto-merge.yml, .github/workflows/pr-title-check.yml
Auto-merge configuration for specific author with squash strategy; PR title validation via external reusable workflow.
CI & Testing
.github/workflows/ci.yml
Adds merge_group trigger and new ci-summary job that consolidates lint, typecheck, and test results, reporting overall workflow status.
Contract & Schema Validation
.github/workflows/contract-validation.yml, .github/workflows/onex-schema-compat.yml
Contract validation gating for main branch using external change-control action; schema compatibility checking against ONEX upstream via Python TOML parsing and cross-version validation.
Linear Integration
.github/workflows/linear-close-on-merge.yml, .github/workflows/stale-todo-gate.yml, .github/workflows/todo-audit-on-merge.yml
Close merged PRs' Linear tickets by extracting ticket IDs from branch names and updating issue states; gate PRs with stale (completed/cancelled) tickets found in TODO comments; auto-create follow-up Linear issues for unresolved TODOs on merge.
Repository Standards
.github/workflows/omni-standards-compliance.yml
Multi-check workflow enforcing required directories, manifest files, naming conventions, and legacy compatibility rules across ecosystem repositories.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Workflows spring to life, automation's delight,
Auto-merging, validating through the day and night,
Linear tickets dance as Linear APIs play,
TODOs audited, standards guarded, all the way,
GitHub's gears turn smooth—a rabbit's grand ballet!
twitch whiskers proudly ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding standardized CI workflows and branch protection configuration for the omnimarket repository.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jonah/omn-7648-ci-standardization

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

jonahgabriel added a commit that referenced this pull request Apr 6, 2026
Follow-up to PR #7 — adds 3 remaining standard workflows not covered:
- check-handshake.yml: architecture handshake validation via omnibase_core
- release-dry-run.yml: manual workflow to simulate a release build
- security-scan.yml: dependency, secret, and CodeQL security scanning
The schema compat workflow fails because omnimarket depends on
omnibase_core via [tool.uv.sources] local path override. Add a
checkout step for omnibase_core at ../omnibase_core so uv sync
can resolve the editable dependency in CI.
actions/checkout@v6 rejects paths outside the workspace directory
(../omnibase_core). Switch to git clone --depth=1 to match the pattern
used in ci.yml, which is not subject to the same path restriction.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (8)
.github/workflows/omni-standards-compliance.yml (1)

121-125: Name extraction may not handle quoted values.

The current extraction grep -m1 "^name:" | sed "s/name: *//" won't correctly handle quoted workflow names like name: "CI" or name: 'CI'. If someone adds quotes, the check will fail incorrectly.

♻️ More robust extraction
-          CI_NAME=$(grep -m1 "^name:" .github/workflows/ci.yml | sed "s/name: *//")
-          if [ "$CI_NAME" != "CI" ]; then
+          CI_NAME=$(grep -m1 "^name:" .github/workflows/ci.yml | sed "s/name: *//; s/^[\"']//; s/[\"']$//")
+          if [ "$CI_NAME" != "CI" ]; then
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/omni-standards-compliance.yml around lines 121 - 125, The
CI_NAME extraction fails for quoted values; update the command that sets CI_NAME
so it strips optional surrounding single or double quotes after removing the
leading "name:" token (i.e., normalize values like name: "CI" and name: 'CI' to
CI). Target the shell assignment to CI_NAME in the workflow snippet and adjust
the sed/grep pipeline to remove surrounding quotes and whitespace so the
subsequent comparison against "CI" works regardless of quoting.
.github/workflows/todo-audit-on-merge.yml (2)

101-114: Shell variable interpolation in Python string could cause issues.

The Python code uses shell variable expansion (${FOLLOWUP_TITLE}, ${TICKET_ID}) directly in string literals. This works but is fragile—if FOLLOWUP_TITLE contains single quotes or special characters, the Python code will have syntax errors.

Consider passing these values via environment variables:

♻️ Safer approach using environment variables
+          FOLLOWUP_TITLE="$FOLLOWUP_TITLE" TICKET_ID="$TICKET_ID" \
           EXISTING=$(echo "$SEARCH_RESPONSE" | python3 -c "
-          import json, sys
+          import json, sys, os
           data = json.load(sys.stdin)
+          followup_title = os.environ['FOLLOWUP_TITLE']
+          ticket_id = os.environ['TICKET_ID']
           nodes = data.get('data', {}).get('issueSearch', {}).get('nodes', [])
           for n in nodes:
-              if n.get('title', '') == '${FOLLOWUP_TITLE}':
+              if n.get('title', '') == followup_title:
                   print(n['identifier'])
                   sys.exit(0)
               desc = n.get('description', '') or ''
-              if '<!-- source: ${TICKET_ID} -->' in desc:
+              if f'<!-- source: {ticket_id} -->' in desc:
                   print(n['identifier'])
                   sys.exit(0)
           print('')
           " 2>/dev/null || echo "")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/todo-audit-on-merge.yml around lines 101 - 114, The
embedded Python block that builds EXISTING from SEARCH_RESPONSE is vulnerable
because it injects shell variables (${FOLLOWUP_TITLE}, ${TICKET_ID}) directly
into Python string literals; change it to export/prefix the variables into the
Python environment and have the Python snippet read them via os.environ (e.g.,
read FOLLOWUP_TITLE and TICKET_ID inside the python3 -c block) instead of
interpolating into the string, so the code that parses SEARCH_RESPONSE (the
python3 block that reads data and checks n.get('title') and the '<!-- source:
... -->' marker) safely compares against environment-provided values and avoids
shell-quoting issues.

143-146: Loose UUID validation for team ID.

The regex ^[0-9a-f-]+$ is very permissive and would match strings like --- or a-b-c. Consider using a proper UUID pattern for consistency with the validation in linear-close-on-merge.yml:

-          if ! echo "$TEAM_ID" | grep -qE '^[0-9a-f-]+$'; then
+          if ! echo "$TEAM_ID" | grep -qE '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'; then
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/todo-audit-on-merge.yml around lines 143 - 146, The
TEAM_ID validation uses an overly permissive regex; update the check that
references TEAM_ID to use a strict UUID (RFC4122) pattern instead of
^[0-9a-f-]+$, e.g. replace the grep -qE pattern with a full UUID regex like
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ so
strings like '---' or 'a-b-c' are rejected while valid UUIDs pass.
.github/workflows/stale-todo-gate.yml (1)

94-122: Consider consolidating Python parsing into a single invocation.

The same $RESPONSE JSON is parsed three separate times with nearly identical Python snippets to extract state.type, state.name, and title. This could be consolidated into a single Python call that outputs all three values.

♻️ Suggested consolidation
-          STATE_TYPE=$(echo "$RESPONSE" | python3 -c "
-          ...
-          " 2>/dev/null || echo "UNKNOWN")
-
-          STATE_NAME=$(echo "$RESPONSE" | python3 -c "
-          ...
-          " 2>/dev/null || echo "")
-
-          TITLE=$(echo "$RESPONSE" | python3 -c "
-          ...
-          " 2>/dev/null || echo "")
+          read -r STATE_TYPE STATE_NAME TITLE < <(echo "$RESPONSE" | python3 -c "
+          import json, sys
+          data = json.load(sys.stdin)
+          issue = data.get('data', {}).get('issue')
+          if issue:
+              print(issue.get('state', {}).get('type', ''))
+              print(issue.get('state', {}).get('name', ''))
+              print(issue.get('title', ''))
+          else:
+              print('NOT_FOUND')
+              print('')
+              print('')
+          " 2>/dev/null || echo -e "UNKNOWN\n\n")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/stale-todo-gate.yml around lines 94 - 122, Replace the
three separate python3 parses of $RESPONSE for STATE_TYPE, STATE_NAME and TITLE
with a single python3 invocation that loads stdin once, extracts
issue.state.type (default ""); issue.state.name (default ""); and issue.title
(default ""), prints them in a stable delimiter (e.g. newline or null) and exits
with appropriate fallbacks like "NOT_FOUND" for missing issue; then capture
those three outputs into the shell variables (STATE_TYPE, STATE_NAME, TITLE)
using a single read/IFS or mapfile call so the JSON is parsed only once; keep
the same default behaviors and error redirection (2>/dev/null || echo ...)
semantics.
.github/workflows/pr-title-check.yml (1)

13-13: Consider pinning the reusable workflow reference.

Using @main for the reusable workflow means breaking changes upstream could unexpectedly fail this workflow. Consider pinning to a specific tag or commit SHA for stability:

-    uses: OmniNode-ai/onex_change_control/.github/workflows/pr-title-check-reusable.yml@main
+    uses: OmniNode-ai/onex_change_control/.github/workflows/pr-title-check-reusable.yml@v1.0.0
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pr-title-check.yml at line 13, The reusable workflow
reference currently uses the floating ref
"OmniNode-ai/onex_change_control/.github/workflows/pr-title-check-reusable.yml@main";
change this to a pinned ref (a release tag like `@vX.Y.Z` or a specific commit
SHA) to prevent upstream breaking changes from affecting our CI. Locate the line
that imports the reusable workflow and replace "@main" with the chosen immutable
tag or full commit SHA, and ensure any repo/maintainer guidelines are followed
when selecting the tag or SHA.
.github/workflows/auto-merge.yml (1)

21-21: Hardcoded username may limit scalability.

The condition github.actor == 'jonahgabriel' restricts auto-merge to a single user. Consider using an organization variable or team membership check for better maintainability as the team grows.

# Option 1: Use a repository variable with comma-separated usernames
if: contains(vars.AUTO_MERGE_ACTORS, github.actor)

# Option 2: Use GitHub team membership (requires additional API call)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/auto-merge.yml at line 21, Replace the hardcoded condition
"github.actor == 'jonahgabriel'" in .github/workflows/auto-merge.yml with a
dynamic check against a repo variable or team membership: update the workflow's
if expression to test whether github.actor is listed in a repository variable
(e.g., AUTO_MERGE_ACTORS) using the contains function, or implement a pre-step
that verifies the actor's GitHub team membership via the API and sets an
output/variable the if can reference; locate the condition by searching for
"github.actor == 'jonahgabriel'" and change it to reference
AUTO_MERGE_ACTORS/contains or the team-membership output accordingly.
.github/workflows/linear-close-on-merge.yml (1)

36-62: Duplicate ticket extraction logic across workflows.

The branch name parsing logic (epic branches, standard omn-XXXX patterns) is nearly identical to .github/workflows/todo-audit-on-merge.yml (lines 34-60). Consider extracting this into a reusable composite action to avoid duplication and ensure consistent behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/linear-close-on-merge.yml around lines 36 - 62, The
branch-parsing logic in the job step named "Extract ticket ID from branch name"
is duplicated across workflows; extract this logic into a reusable composite
action (e.g., action name "extract-ticket-id") and replace the inline step with
a single step that calls that action from both workflows; ensure the composite
action accepts BRANCH (default to github.event.pull_request.head.ref),
implements the same epic and standard OMN-XXXX parsing (including producing the
"ticket_id" output and the same uppercase normalization), and preserves the
exact output key "ticket_id" so existing consumers remain unchanged.
.github/workflows/contract-validation.yml (1)

16-35: Add explicit least-privilege GITHUB_TOKEN permissions.

The workflow uses gh api to access repository metadata and runs a composite action that validates contracts. Add a top-level permissions block to ensure token scope is deterministic and minimized.

Suggested change
 name: Contract Validation
 
 on:
   pull_request:
     branches: [main]
   merge_group:
   workflow_dispatch:
+permissions:
+  contents: read
+
 concurrency:
   group: contract-validation-${{ github.ref }}
   cancel-in-progress: true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/contract-validation.yml around lines 16 - 35, Add a
top-level permissions block to the workflow to explicitly scope GITHUB_TOKEN for
the contract-validation job: insert a permissions map at the root (above jobs)
that grants only the minimal required scopes (for example: contents: read,
pull-requests: read, actions: read, metadata: read) so the gh api call and the
composite contract validation action have deterministic, least-privilege access;
update the root YAML to include this permissions block (affects the
contract-validation job run) rather than relying on implicit token scopes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/contract-validation.yml:
- Around line 112-114: The workflow currently treats unknown VALIDATION_STATUS
values as skipped in the default case; change that behavior to fail closed by
replacing the default case that echoes a warning with a failing path: log an
error mentioning the unexpected VALIDATION_STATUS and exit non-zero (e.g., exit
1) so the job fails when the upstream contract returns an unexpected status;
refer to the case handling of VALIDATION_STATUS in the workflow to locate and
update the default (*) branch.
- Line 81: The workflow step using the external action
"OmniNode-ai/onex_change_control/.github/actions/validate-contract@main" must be
pinned to an immutable full commit SHA; locate the target repo
"OmniNode-ai/onex_change_control", find the exact commit you want to use (copy
the 40‑character commit SHA from that repo), and replace the "@main" suffix in
the uses string with "@<full-commit-sha>" so the uses line reads the same path
but pinned to that commit; commit the change and, when you intentionally want to
update the action, repeat this process and update the SHA explicitly.

In @.github/workflows/onex-schema-compat.yml:
- Line 126: Replace the hardcoded reader_version = '0.1.0' with a dynamic
extraction from the project's pyproject.toml (or package metadata) so the
workflow always uses the actual project version; update the workflow to parse
pyproject.toml (or run a short python snippet) at runtime to set the
reader_version variable, referencing the reader_version symbol in the YAML and
the version key in pyproject.toml to keep them in sync.

---

Nitpick comments:
In @.github/workflows/auto-merge.yml:
- Line 21: Replace the hardcoded condition "github.actor == 'jonahgabriel'" in
.github/workflows/auto-merge.yml with a dynamic check against a repo variable or
team membership: update the workflow's if expression to test whether
github.actor is listed in a repository variable (e.g., AUTO_MERGE_ACTORS) using
the contains function, or implement a pre-step that verifies the actor's GitHub
team membership via the API and sets an output/variable the if can reference;
locate the condition by searching for "github.actor == 'jonahgabriel'" and
change it to reference AUTO_MERGE_ACTORS/contains or the team-membership output
accordingly.

In @.github/workflows/contract-validation.yml:
- Around line 16-35: Add a top-level permissions block to the workflow to
explicitly scope GITHUB_TOKEN for the contract-validation job: insert a
permissions map at the root (above jobs) that grants only the minimal required
scopes (for example: contents: read, pull-requests: read, actions: read,
metadata: read) so the gh api call and the composite contract validation action
have deterministic, least-privilege access; update the root YAML to include this
permissions block (affects the contract-validation job run) rather than relying
on implicit token scopes.

In @.github/workflows/linear-close-on-merge.yml:
- Around line 36-62: The branch-parsing logic in the job step named "Extract
ticket ID from branch name" is duplicated across workflows; extract this logic
into a reusable composite action (e.g., action name "extract-ticket-id") and
replace the inline step with a single step that calls that action from both
workflows; ensure the composite action accepts BRANCH (default to
github.event.pull_request.head.ref), implements the same epic and standard
OMN-XXXX parsing (including producing the "ticket_id" output and the same
uppercase normalization), and preserves the exact output key "ticket_id" so
existing consumers remain unchanged.

In @.github/workflows/omni-standards-compliance.yml:
- Around line 121-125: The CI_NAME extraction fails for quoted values; update
the command that sets CI_NAME so it strips optional surrounding single or double
quotes after removing the leading "name:" token (i.e., normalize values like
name: "CI" and name: 'CI' to CI). Target the shell assignment to CI_NAME in the
workflow snippet and adjust the sed/grep pipeline to remove surrounding quotes
and whitespace so the subsequent comparison against "CI" works regardless of
quoting.

In @.github/workflows/pr-title-check.yml:
- Line 13: The reusable workflow reference currently uses the floating ref
"OmniNode-ai/onex_change_control/.github/workflows/pr-title-check-reusable.yml@main";
change this to a pinned ref (a release tag like `@vX.Y.Z` or a specific commit
SHA) to prevent upstream breaking changes from affecting our CI. Locate the line
that imports the reusable workflow and replace "@main" with the chosen immutable
tag or full commit SHA, and ensure any repo/maintainer guidelines are followed
when selecting the tag or SHA.

In @.github/workflows/stale-todo-gate.yml:
- Around line 94-122: Replace the three separate python3 parses of $RESPONSE for
STATE_TYPE, STATE_NAME and TITLE with a single python3 invocation that loads
stdin once, extracts issue.state.type (default ""); issue.state.name (default
""); and issue.title (default ""), prints them in a stable delimiter (e.g.
newline or null) and exits with appropriate fallbacks like "NOT_FOUND" for
missing issue; then capture those three outputs into the shell variables
(STATE_TYPE, STATE_NAME, TITLE) using a single read/IFS or mapfile call so the
JSON is parsed only once; keep the same default behaviors and error redirection
(2>/dev/null || echo ...) semantics.

In @.github/workflows/todo-audit-on-merge.yml:
- Around line 101-114: The embedded Python block that builds EXISTING from
SEARCH_RESPONSE is vulnerable because it injects shell variables
(${FOLLOWUP_TITLE}, ${TICKET_ID}) directly into Python string literals; change
it to export/prefix the variables into the Python environment and have the
Python snippet read them via os.environ (e.g., read FOLLOWUP_TITLE and TICKET_ID
inside the python3 -c block) instead of interpolating into the string, so the
code that parses SEARCH_RESPONSE (the python3 block that reads data and checks
n.get('title') and the '<!-- source: ... -->' marker) safely compares against
environment-provided values and avoids shell-quoting issues.
- Around line 143-146: The TEAM_ID validation uses an overly permissive regex;
update the check that references TEAM_ID to use a strict UUID (RFC4122) pattern
instead of ^[0-9a-f-]+$, e.g. replace the grep -qE pattern with a full UUID
regex like
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ so
strings like '---' or 'a-b-c' are rejected while valid UUIDs pass.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 88b1091a-03c2-45eb-8b04-11644e52d7d3

📥 Commits

Reviewing files that changed from the base of the PR and between 5f88d0d and 92c23c1.

📒 Files selected for processing (9)
  • .github/workflows/auto-merge.yml
  • .github/workflows/ci.yml
  • .github/workflows/contract-validation.yml
  • .github/workflows/linear-close-on-merge.yml
  • .github/workflows/omni-standards-compliance.yml
  • .github/workflows/onex-schema-compat.yml
  • .github/workflows/pr-title-check.yml
  • .github/workflows/stale-todo-gate.yml
  • .github/workflows/todo-audit-on-merge.yml

Comment thread .github/workflows/contract-validation.yml
Comment thread .github/workflows/contract-validation.yml
Comment thread .github/workflows/onex-schema-compat.yml
The schema compatibility check imports is_compatible() from
omnibase_spi, but omnimarket doesn't list it as a dependency.
Clone and install omnibase_spi alongside omnibase_core.
@jonahgabriel
jonahgabriel added this pull request to the merge queue Apr 7, 2026
Merged via the queue into main with commit 2f5b54a Apr 7, 2026
13 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-7648-ci-standardization branch April 7, 2026 16:10
jonahgabriel added a commit that referenced this pull request Apr 7, 2026
Follow-up to PR #7 — adds 3 remaining standard workflows not covered:
- check-handshake.yml: architecture handshake validation via omnibase_core
- release-dry-run.yml: manual workflow to simulate a release build
- security-scan.yml: dependency, secret, and CodeQL security scanning
github-merge-queue Bot pushed a commit that referenced this pull request Apr 7, 2026
* ci: add check-handshake, release-dry-run, and security-scan workflows

Follow-up to PR #7 — adds 3 remaining standard workflows not covered:
- check-handshake.yml: architecture handshake validation via omnibase_core
- release-dry-run.yml: manual workflow to simulate a release build
- security-scan.yml: dependency, secret, and CodeQL security scanning

* ci: remove check-handshake workflow

omnimarket is not in the architecture-handshakes repos.conf and has
no .claude/architecture-handshake.md installed. The check-handshake
workflow always fails with "No handshake installed."
jonahgabriel added a commit that referenced this pull request Apr 21, 2026
…, fix deps

New nodes (picks #2 and #7 from prioritized list):

- node_two_strike_arbiter (effect): Monitors consecutive fix-attempt failures.
  After 2 strikes, writes a diagnosis document, moves Linear ticket to Blocked,
  and files a friction event. Implements the two-strike protocol from GEMINI.md.
  Subscribes: onex.evt.omnimarket.fix-attempt-failed.v1
  Publishes: onex.evt.omnimarket.two-strike-arbiter.v1

- node_audit_trail_compactor (compute): Reads friction + dispatch logs,
  computes failure modes, recurring tickets, stall heatmap. Compact output
  for overseer-verify and session-post-mortem consumption.
  Subscribes: onex.cmd.omnimarket.audit-trail-compact.v1
  Publishes: onex.evt.omnimarket.audit-trail-compacted.v1

Dependency fix (same as PR #372):
- Replace path sources with git sources for portable resolution
- Add git sources for omnibase-spi, omninode-memory (PyPI stale)
- Add omnibase-spi as explicit direct dep for git source override

Tests: 16 new golden chain tests (7 arbiter + 9 compactor), all pass.

Assisted-by: GLM-5.1 (z.ai) via Crush <crush@charm.land>
jonahgabriel added a commit that referenced this pull request Apr 22, 2026
…, fix deps

New nodes (picks #2 and #7 from prioritized list):

- node_two_strike_arbiter (effect): Monitors consecutive fix-attempt failures.
  After 2 strikes, writes a diagnosis document, moves Linear ticket to Blocked,
  and files a friction event. Implements the two-strike protocol from GEMINI.md.
  Subscribes: onex.evt.omnimarket.fix-attempt-failed.v1
  Publishes: onex.evt.omnimarket.two-strike-arbiter.v1

- node_audit_trail_compactor (compute): Reads friction + dispatch logs,
  computes failure modes, recurring tickets, stall heatmap. Compact output
  for overseer-verify and session-post-mortem consumption.
  Subscribes: onex.cmd.omnimarket.audit-trail-compact.v1
  Publishes: onex.evt.omnimarket.audit-trail-compacted.v1

Dependency fix (same as PR #372):
- Replace path sources with git sources for portable resolution
- Add git sources for omnibase-spi, omninode-memory (PyPI stale)
- Add omnibase-spi as explicit direct dep for git source override

Tests: 16 new golden chain tests (7 arbiter + 9 compactor), all pass.

Assisted-by: GLM-5.1 (z.ai) via Crush <crush@charm.land>
github-actions Bot pushed a commit to andywu42/omnimarket that referenced this pull request Apr 23, 2026
…9403] (OmniNode-ai#368)

* feat(linear-triage): replace gh subprocess with GitHub REST API [OMN-9403]

- Add GitHubClientProtocol + GitHubHttpClient using urllib (zero external deps)
- Reads GH_PAT from env (fail-fast, no silent fallback)
- Only PR-check tickets in In Progress/In Review (43 vs 682)
- Only check epic completion for active root tickets (25 vs 1663)
- Rate-limit awareness: auto-sleeps on x-ratelimit-remaining exhaustion
- Error handling for Linear list_children 400s on non-epic tickets
- Updated golden chain tests to use DI stubs (GitHubClientProtocol)
  instead of monkeypatching module-level functions
- All 8 golden chain tests pass
- End-to-end verified via: onex node node_linear_triage --input input.json

* fix: sort imports for ruff I001 [OMN-9403]

* feat(nodes): add node_two_strike_arbiter + node_audit_trail_compactor, fix deps

New nodes (picks OmniNode-ai#2 and OmniNode-ai#7 from prioritized list):

- node_two_strike_arbiter (effect): Monitors consecutive fix-attempt failures.
  After 2 strikes, writes a diagnosis document, moves Linear ticket to Blocked,
  and files a friction event. Implements the two-strike protocol from GEMINI.md.
  Subscribes: onex.evt.omnimarket.fix-attempt-failed.v1
  Publishes: onex.evt.omnimarket.two-strike-arbiter.v1

- node_audit_trail_compactor (compute): Reads friction + dispatch logs,
  computes failure modes, recurring tickets, stall heatmap. Compact output
  for overseer-verify and session-post-mortem consumption.
  Subscribes: onex.cmd.omnimarket.audit-trail-compact.v1
  Publishes: onex.evt.omnimarket.audit-trail-compacted.v1

Dependency fix (same as PR OmniNode-ai#372):
- Replace path sources with git sources for portable resolution
- Add git sources for omnibase-spi, omninode-memory (PyPI stale)
- Add omnibase-spi as explicit direct dep for git source override

Tests: 16 new golden chain tests (7 arbiter + 9 compactor), all pass.

Assisted-by: GLM-5.1 (z.ai) via Crush <crush@charm.land>

* fix: resolve 9 CodeRabbit review threads on PR OmniNode-ai#368

- handler_audit_trail_compactor: compare datetimes not ISO strings (thread 5);
  add _parse_recorded_at() helper; sort last_failure by timestamp not list order
  (thread 6)
- handler_linear_triage: narrow list_children except to only suppress known
  non-epic errors, re-raise auth/transport faults (thread 4); re-raise
  _get() failures in search_prs/search_prs_in_repo/list_prs_by_head instead
  of collapsing to [] (thread 7)
- handler_two_strike_arbiter: capture move_to_blocked() return value; report
  strongest successful side-effect action (TICKET_BLOCKED / FRICTION_FILED /
  DIAGNOSIS_WRITTEN) instead of always SECOND_STRIKE (thread 8)
- test_golden_chain_audit_trail_compactor: make timestamps relative to now()
  so suite does not break after 7-day lookback window expires (thread 9)

Threads 1/2/3 verified already addressed in current code.
jonahgabriel added a commit that referenced this pull request Jun 9, 2026
…ast (no relative default)

Defect #7 (close-loop blocker, diagnosed live in OMN-12853 loop re-run): the
generated node was never materialized — HandlerGeneratedExecutor._DEFAULT_SANDBOX
was a hardcoded relative '.onex_state/hackathon/generated' that resolved against
the runtime's non-writable effective CWD (Errno 13 Permission denied), so
sandbox-invoke fired but had no artifact to import (terminal status=failed).

Fix (CLAUDE.md Rule 6/8 — no hardcoded paths, no silent defaults): the sandbox
dir is resolved from the runtime writable state root (ONEX_STATE_DIR preferred,
then ONEX_STATE_ROOT) and FAILS FAST when neither is set — the relative
_DEFAULT_SANDBOX and its silent fallback are removed. The stability-test compose
already sets ONEX_STATE_ROOT/ONEX_STATE_DIR=/app/data/.onex_state_stability_test
(a rw volume) for both runtime + runtime-effects, so no compose change is needed;
the bug was purely the handler ignoring that env via a relative fallback.

TDD: sandbox resolves under ONEX_STATE_DIR (preferred) / ONEX_STATE_ROOT
(fallback), and raises RuntimeError when both are unset (no relative default).
151 generation node tests + 2057 unit tests green; mypy --strict + ruff +
pre-commit + runtime sweep (296/296) + metadata check clean.

Evidence-Source: b520235a68e580985160bd7deb87bc3baa8a2dc4
Evidence-Ticket: OMN-12854
jonahgabriel added a commit that referenced this pull request Jun 9, 2026
…ast (no relative default)

Defect #7 (close-loop blocker, diagnosed live in OMN-12853 loop re-run): the
generated node was never materialized — HandlerGeneratedExecutor._DEFAULT_SANDBOX
was a hardcoded relative '.onex_state/hackathon/generated' that resolved against
the runtime's non-writable effective CWD (Errno 13 Permission denied), so
sandbox-invoke fired but had no artifact to import (terminal status=failed).

Fix (CLAUDE.md Rule 6/8 — no hardcoded paths, no silent defaults): the sandbox
dir is resolved from the runtime writable state root (ONEX_STATE_DIR preferred,
then ONEX_STATE_ROOT) and FAILS FAST when neither is set — the relative
_DEFAULT_SANDBOX and its silent fallback are removed. The stability-test compose
already sets ONEX_STATE_ROOT/ONEX_STATE_DIR=/app/data/.onex_state_stability_test
(a rw volume) for both runtime + runtime-effects, so no compose change is needed;
the bug was purely the handler ignoring that env via a relative fallback.

TDD: sandbox resolves under ONEX_STATE_DIR (preferred) / ONEX_STATE_ROOT
(fallback), and raises RuntimeError when both are unset (no relative default).
151 generation node tests + 2057 unit tests green; mypy --strict + ruff +
pre-commit + runtime sweep (296/296) + metadata check clean.

Evidence-Source: b520235a68e580985160bd7deb87bc3baa8a2dc4
Evidence-Ticket: OMN-12854
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant