Repository navigation
feat: standardize CI workflows and branch protection [OMN-7648] - #7
Conversation
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.
|
Warning Rate limit exceeded
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 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe 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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
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.
There was a problem hiding this comment.
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 likename: "CI"orname: '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—ifFOLLOWUP_TITLEcontains 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---ora-b-c. Consider using a proper UUID pattern for consistency with the validation inlinear-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
$RESPONSEJSON is parsed three separate times with nearly identical Python snippets to extractstate.type,state.name, andtitle. 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
@mainfor 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-XXXXpatterns) 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-privilegeGITHUB_TOKENpermissions.The workflow uses
gh apito access repository metadata and runs a composite action that validates contracts. Add a top-levelpermissionsblock 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
📒 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
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.
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: 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."
…, 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>
…, 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>
…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.
…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
…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
Summary
merge_grouptrigger andCI Summaryaggregator job for branch protection gatingTest plan
CI Summarystatus check after mergeSummary by CodeRabbit