Skip to content

fix: recover Classic roots and parse raw Codex patches - #283

Merged
benym merged 5 commits into
masterfrom
codex/hotfix-issue-277-282
Aug 5, 2026
Merged

fix: recover Classic roots and parse raw Codex patches#283
benym merged 5 commits into
masterfrom
codex/hotfix-issue-277-282

Conversation

@benym

@benym benym commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes fix: openspec/ 迁移到 docs/openspec/ 后 Classic 双根冲突硬性阻断且无法回退 #277 by making classic.artifact_layout the sole Comet ownership boundary: openspec/ and docs/openspec/ can coexist, while Classic commands, status, guards, evidence, and Factory routing use only the configured root.
  • A standalone OpenSpec root is never scanned, written, or treated as Comet evidence; first-time Comet docs initialization can create docs/openspec/ beside an existing pure openspec/ root.
  • Explicit comet classic root move docs --apply remains fail-closed when its destination is non-empty.
  • Fixes fix: Codex raw apply_patch input bypasses Native Hook phase protection #282 by attributing raw Codex apply_patch input, including Add/Update/Delete and standard +++ b/... headers, before Native phase enforcement.
  • Bumps the release metadata to 0.4.0-beta.16 and refreshes generated runtimes.

Verification

  • npx vitest run test/domains/comet-classic test/domains/comet-entry: 829 passed, 16 skipped.
  • npx vitest run test/domains/factory/factory-package.test.ts: 39 passed.
  • pnpm build passed.
  • pnpm check:generated passed.
  • pnpm lint and architecture lint passed.
  • Full pnpm test was attempted locally on Windows but exceeded 10 minutes without a failure assertion; CI remains the final full-suite check.

Closes #277
Closes #282

Summary by CodeRabbit

  • New Features
    • Added Classic root inspection with visibility into configured and alternate roots.
    • Improved detection of raw patches and unified-diff headers as file-write requests.
  • Bug Fixes
    • Classic workflows now use the configured root when a standalone OpenSpec root exists.
    • Root migration refuses to overwrite non-empty destinations.
    • Checkpoint files now end with a newline.
    • Improved YAML parsing and serialization reliability.
  • Release
    • Updated to 0.4.0-beta.16 with security updates.

@sourcery-ai sourcery-ai 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.

Sorry @benym, your pull request is larger than the review limit of 150000 diff characters

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

👋 Thanks for opening your first PR to Comet, @benym.

Before review, please make sure the PR title follows Conventional Commits, for example fix: handle project-scope init, and that the checklist in the PR template is up to date.

🧪 The most useful local checks are:

pnpm build
pnpm lint
pnpm format:check
pnpm test

🧰 If your change touches assets/skills/comet/scripts/, please also check script portability across macOS, Linux, and Windows Git Bash. Avoid sed -i, support both sha256sum and shasum -a 256, and guard optional grep pipelines with || true.

✨ We appreciate the contribution and will take a look as soon as we can.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 744f3396-824d-4157-9cfa-088312b6a26d

📥 Commits

Reviewing files that changed from the base of the PR and between 580500a and bb5e90b.

📒 Files selected for processing (1)
  • test/app/doctor.test.ts

📝 Walkthrough

Walkthrough

The PR removes Classic dual-root blocking, adds raw Codex patch target extraction, regenerates bundled Comet assets, updates dependency overrides, and releases version 0.4.0-beta.16.

Changes

Classic layout coexistence

Layer / File(s) Summary
Configured-root layout handling
app/commands/doctor.ts, domains/comet-classic/classic-layout.ts, domains/comet-classic/classic-root-command.ts, domains/factory/package.ts, docs/comet/specs/unified-product-catalogue/spec.md
Classic layout validation uses the configured root. Root inspection reports both roots without treating coexistence as a conflict.
Initialization and evidence handling
domains/comet-classic/classic-layout-initialization.ts, domains/comet-classic/classic-evidence.ts, test/domains/comet-classic/classic-layout-initialization.test.ts, test/domains/comet-classic/classic-evidence.test.ts
Initialization permits the configured root when an alternate root exists. Evidence checks reject alternate-root files as Comet artifacts and preserve layout errors.
Coexistence workflow validation
test/app/doctor.test.ts, test/domains/comet-classic/*, test/domains/comet-entry/*, test/domains/factory/factory-package.test.ts
Command, resume, state, guard, status, and migration tests now validate configured-root precedence and standalone-root coexistence.

Raw Codex patch parsing

Layer / File(s) Summary
Patch target extraction
domains/comet-entry/hook-adapter.ts, test/domains/comet-entry/hook-adapter.test.ts
Raw patch blocks and unified-diff headers now produce deduplicated write targets with tool name apply_patch.
Patch phase enforcement
test/domains/comet-entry/hook-router-runtime.test.ts
Raw patch input is rejected outside the Native build phase.

Bundled runtime regeneration

Layer / File(s) Summary
Regenerated bundled scripts
assets/skills/comet*/scripts/*
Embedded YAML parsers and Comet runtime, hook, state, handoff, archive, and validation implementations were regenerated.

Beta release metadata

Layer / File(s) Summary
Version and dependency metadata
CHANGELOG.md, assets/manifest.json, package.json, test/app/cli-help.test.ts, test/repository/release-metadata.test.ts
Release metadata now uses 0.4.0-beta.16. Dependency overrides for brace-expansion, postcss, and undici were updated.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Codex
  participant HookAdapter
  participant HookRouter
  participant NativePhaseGuard
  Codex->>HookAdapter: send raw apply_patch text
  HookAdapter->>HookRouter: return apply_patch write targets
  HookRouter->>NativePhaseGuard: validate project phase
  NativePhaseGuard-->>HookRouter: allow build or reject other phases
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.15% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main changes: recovering Classic roots and parsing raw Codex patches, which aligns with the primary objectives of fixing #277 and #282.
Linked Issues check ✅ Passed Changes address both linked issues: #277 by removing dual-root conflict blocking and using configured roots as sole boundaries; #282 by parsing raw Codex apply_patch input including Add/Update/Delete and +++ headers with full target attribution.
Out of Scope Changes check ✅ Passed All changes focus on Classic layout dual-root handling, raw patch parsing, generated runtime updates, test alignment, and version/metadata updates directly supporting the stated objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/hotfix-issue-277-282

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@sourcery-ai

sourcery-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Reviewer's Guide

Updates the Classic root CLI to safely inspect and migrate between legacy and docs layouts (including dual-root scenarios), and enhances the Hook router/adapter to attribute and enforce raw Codex apply_patch inputs as Native writes before runtime dispatch, while bumping the bundled Comet runtime.

Sequence diagram for parsing Codex apply_patch as Native writes

sequenceDiagram
  participant Codex
  participant HookRouter
  participant HookAdapter
  participant NativeGuard

  Codex->>HookRouter: apply_patch payload
  HookRouter->>HookAdapter: parseCometHookRequest(source, filePath)
  activate HookAdapter
  HookAdapter->>HookAdapter: JSON.parse(source)
  alt parse fails
    HookAdapter->>HookAdapter: patchTargets(source)
    alt targets found
      HookAdapter-->>HookRouter: intent write, targets, toolName apply_patch
    else no targets
      HookAdapter-->>HookRouter: intent unknown, targets [], toolName null
    end
  else parse succeeds
    HookAdapter-->>HookRouter: structured request
  end
  deactivate HookAdapter

  HookRouter->>NativeGuard: inspectNative(projectRoot, request)
  NativeGuard-->>HookRouter: allow / block decision
  HookRouter-->>Codex: platform-specific response (allow/deny)
Loading

Flow diagram for Classic dual-root inspection and migration

flowchart TD
  A[User runs
comet classic root show] --> B[classicRootCommand]
  B --> C[discoverClassicProject]
  C --> D[assertClassicLayoutReadable
allowAlternateRoot true]
  D --> E[inspectClassicLayout]
  E --> F{dualRoots?}
  F -- yes --> G[Emit layout JSON
with alternateRoot
and dualRoots true]
  F -- no --> H[Emit layout JSON
with single root]

  subgraph Doctor
    I[comet doctor
checkClassicLayout]
    I --> J[inspectClassicLayout]
    J --> K{dualRoots?}
    K -- yes --> L[Fail with detailed
conflict message]
    K -- no --> M[Pass Classic
layout check]
  end
Loading

File-Level Changes

Change Details Files
Regenerate and update the bundled Comet runtime script to a newer YAML implementation and internal utilities.
  • Replace the previous minified YAML runtime bundle with a newer version that includes updated schema, parsing, and stringification utilities.
  • Adjust internal helper functions (e.g., tag resolution, collection handling, flow scalar handling) to match the new library API.
assets/skills/comet/scripts/comet-runtime.mjs
Make Classic root show/move tolerant of dual classic roots and expose a safe dry-run migration path.
  • Change classic root show to report both configured and alternate roots (and their existence) instead of failing when both exist.
  • Allow root move docs --dry-run to run even when both openspec/ and docs/openspec/ exist, surfacing conflicts (e.g., non-empty docs target) without mutating config.
  • Preserve the legacy behavior of failing apply when the docs root is non-empty, and ensure config.yaml is unchanged on failed apply.
  • Extend tests to assert the new dual-root reporting and dry-run behavior.
assets/skills/comet/scripts/comet-runtime.mjs
test/domains/comet-classic/classic-root-command.test.ts
Normalize raw Codex apply_patch input into Native-shaped write requests and enforce Native Shape checks.
  • Extend the Hook adapter to parse raw apply_patch bodies from stdin, recognizing both Codex-style *** Begin/End Patch headers and standard unified diff +++ b/... headers.
  • Derive target file paths from raw patches and populate the write targets list for Native Shape enforcement before routing to the runtime.
  • Add tests to ensure raw Codex apply_patch input is normalized to apply_patch writes and that Native Shape violations are enforced for raw patches in non-build phases.
  • Keep existing behavior for toolName=apply_patch while adding support for raw stdin-based patches.
assets/skills/comet/scripts/comet-runtime.mjs
test/domains/comet-entry/hook-adapter.test.ts
test/domains/comet-entry/hook-router-runtime.test.ts

Assessment against linked issues

Issue Objective Addressed Explanation
#277 Allow Classic read-only commands (e.g., comet classic root show, comet doctor, and related inspection commands) to continue working and report a dual-root conflict when both openspec/ and docs/openspec/ exist, instead of hard-blocking Classic as unusable.
#277 Provide a clear and safe migration path when both Classic roots exist by supporting comet classic root move docs --dry-run that reports the target state and conflicts (e.g., non-empty docs/openspec/), while keeping actual writes (config/layout changes) fail-closed and not modifying project state in conflict scenarios.
#282 Update the Hook adapter so that parseCometHookRequest recognizes raw Codex apply_patch input (*** Begin Patch / Add/Update/Delete blocks and standard unified-diff headers) and correctly extracts all target file paths for write intents.
#282 Ensure the Hook router/runtime enforces Native Shape phase protection for writes originating from raw Codex apply_patch stdin (so such writes cannot bypass Native phase guards), with regression tests covering this behavior.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@greptile-apps

greptile-apps Bot commented Aug 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR makes the configured Classic artifact layout the exclusive Comet ownership boundary and adds target extraction for raw Codex patches.

  • Allows configured Classic roots to coexist with an ignored standalone OpenSpec root while preserving fail-closed explicit migrations.
  • Routes Classic evidence and Factory behavior through the configured root.
  • Parses raw apply_patch directives and unified-diff headers before Native guard enforcement.
  • Updates generated runtimes, dependency locks, tests, and release metadata to 0.4.0-beta.16.

Confidence Score: 4/5

The PR is not yet safe to merge because quoted unified-diff paths can still be evaluated against the wrong target during Native phase enforcement.

The new raw-patch parser captures quoted Git paths without removing quotes, stripping the enclosed b/ prefix, or decoding Git escapes, so the guard resolves a path different from the patch destination and can reject legitimate writes or misapply phase protection.

Files Needing Attention: domains/comet-entry/hook-adapter.ts

Important Files Changed

Filename Overview
domains/comet-entry/hook-adapter.ts Adds raw patch target extraction, but the previously reported quoted Git-path parsing defect remains at HEAD.
domains/comet-classic/classic-layout.ts Makes the configured artifact layout authoritative and permits an alternate standalone OpenSpec root.
domains/comet-classic/classic-root-command.ts Reports root inspection details and preserves no-op behavior once the docs layout is configured.
domains/comet-classic/classic-evidence.ts Restricts Classic evidence detection to the configured Comet-owned root.
domains/factory/package.ts Aligns Factory routing with the configured Classic artifact root.

Reviews (5): Last reviewed commit: "fix(test): align standalone OpenSpec lay..." | Re-trigger Greptile

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.72%. Comparing base (966d6cb) to head (bb5e90b).

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #283   +/-   ##
=======================================
  Coverage   74.71%   74.72%           
=======================================
  Files         242      242           
  Lines       23483    23488    +5     
  Branches     7563     7564    +1     
=======================================
+ Hits        17546    17551    +5     
  Misses       3008     3008           
  Partials     2929     2929           
Flag Coverage Δ
unittests 74.72% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@domains/comet-classic/classic-root-command.ts`:
- Around line 212-214: Update
domains/comet-classic/classic-root-command.ts:212-214 around
assertClassicLayoutReadable to detect a docs-layout dual-root conflict and
return an actionable conflict result rather than an already-migrated success.
Update app/commands/doctor.ts:315-315 to recommend move docs --dry-run only for
legacy layouts, with safe cleanup or layout-switch guidance for docs layouts.
Update domains/comet-classic/classic-layout.ts:66-66 so
ClassicLayoutConflictError provides layout-specific remediation. Add a
regression test in
test/domains/comet-classic/classic-root-command.test.ts:100-123 verifying
docs-layout dual-root handling does not report completed migration.
🪄 Autofix

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 Plus

Run ID: 9a29382b-2665-47ce-a62a-2cfd82ae4bd0

📥 Commits

Reviewing files that changed from the base of the PR and between 966d6cb and 224dd8d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (25)
  • CHANGELOG.md
  • app/commands/doctor.ts
  • assets/manifest.json
  • assets/skills/comet-native/scripts/comet-native-hook-guard.mjs
  • assets/skills/comet-native/scripts/comet-native-runtime.mjs
  • assets/skills/comet/scripts/comet-archive.mjs
  • assets/skills/comet/scripts/comet-guard.mjs
  • assets/skills/comet/scripts/comet-handoff.mjs
  • assets/skills/comet/scripts/comet-hook-guard.mjs
  • assets/skills/comet/scripts/comet-hook-router.mjs
  • assets/skills/comet/scripts/comet-resume-probe.mjs
  • assets/skills/comet/scripts/comet-runtime.mjs
  • assets/skills/comet/scripts/comet-state.mjs
  • assets/skills/comet/scripts/comet-yaml-validate.mjs
  • domains/comet-classic/classic-layout.ts
  • domains/comet-classic/classic-root-command.ts
  • domains/comet-entry/hook-adapter.ts
  • package.json
  • test/app/cli-help.test.ts
  • test/app/doctor.test.ts
  • test/domains/comet-classic/classic-root-command.test.ts
  • test/domains/comet-entry/hook-adapter.test.ts
  • test/domains/comet-entry/hook-router-runtime.test.ts
  • test/domains/comet-entry/project-status.test.ts
  • test/repository/release-metadata.test.ts

Comment thread domains/comet-classic/classic-root-command.ts Outdated

@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: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/skills/comet/scripts/comet-archive.mjs`:
- Around line 136-166: Regenerate the Classic runtime bundles from their current
source so they pass pnpm build:classic-runtime --check and remain consistent:
update assets/skills/comet/scripts/comet-archive.mjs lines 136-166,
assets/skills/comet/scripts/comet-hook-guard.mjs lines 136-154, and
assets/skills/comet/scripts/comet-state.mjs lines 136-166; no source-level
behavior changes are required.

In `@assets/skills/comet/scripts/comet-runtime.mjs`:
- Around line 4-5: Add the missing reproducibility check for the generated
Classic runtime bundles by running pnpm build:classic-runtime with --check
before merge. Apply this to assets/skills/comet/scripts/comet-runtime.mjs lines
4-5, assets/skills/comet/scripts/comet-yaml-validate.mjs lines 4-5, and
assets/skills/comet/scripts/comet-handoff.mjs lines 4-5 so the release assets
are compared against the checked build output.
- Around line 177-186: Update the Classic root-move write flow in
classic-root-command.ts and classic-root-move.ts to call
assertClassicLayoutWritable() before performing writes, including the recovery
path. Do not rely solely on guarded file operations, and ensure the check occurs
after resolving the layout so managed root paths are rejected before any
root-move changes are applied.

In `@assets/skills/comet/scripts/comet-yaml-validate.mjs`:
- Line 4: Do not edit the generated comet-yaml-validate.mjs asset directly;
update the corresponding source under domains/comet-classic, then run pnpm
build:classic-runtime to regenerate and synchronize the asset.

In `@domains/comet-classic/classic-evidence.ts`:
- Around line 229-235: Update the layout-validation flow around
assertClassicLayoutReadable and linkedFileEvidence so a failed layout check
cannot continue into the generic file check or return satisfied: true. Propagate
the layout error to linked evidence, or explicitly return unsatisfied linked
evidence until a valid ClassicLayoutPaths value is available, while preserving
normal linked evidence behavior for valid layouts.

In `@domains/comet-classic/classic-layout.ts`:
- Around line 233-236: Update assertClassicLayoutReadable so
assertClassicManagedRootsPhysical validates only the Comet-managed
artifact_layout root and does not validate inspection.alternateRoot. Keep
alternateRoot available as untrusted reporting state, preserve configured-root
reads and writes when it is unsafe, and add a regression case covering an unsafe
alternate-root symlink or junction with a valid configured root.
🪄 Autofix

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 Plus

Run ID: 818a31e3-c8bb-4cda-a8c3-9fbd0d13042a

📥 Commits

Reviewing files that changed from the base of the PR and between 224dd8d and 49cd9b4.

📒 Files selected for processing (28)
  • CHANGELOG.md
  • app/commands/doctor.ts
  • assets/skills/comet/scripts/comet-archive.mjs
  • assets/skills/comet/scripts/comet-guard.mjs
  • assets/skills/comet/scripts/comet-handoff.mjs
  • assets/skills/comet/scripts/comet-hook-guard.mjs
  • assets/skills/comet/scripts/comet-hook-router.mjs
  • assets/skills/comet/scripts/comet-resume-probe.mjs
  • assets/skills/comet/scripts/comet-runtime.mjs
  • assets/skills/comet/scripts/comet-state.mjs
  • assets/skills/comet/scripts/comet-yaml-validate.mjs
  • docs/comet/specs/unified-product-catalogue/spec.md
  • domains/comet-classic/classic-evidence.ts
  • domains/comet-classic/classic-layout-initialization.ts
  • domains/comet-classic/classic-layout.ts
  • domains/comet-classic/classic-root-command.ts
  • domains/factory/package.ts
  • test/app/doctor.test.ts
  • test/domains/comet-classic/classic-evidence.test.ts
  • test/domains/comet-classic/classic-layout-initialization.test.ts
  • test/domains/comet-classic/classic-layout.test.ts
  • test/domains/comet-classic/classic-openspec-command.test.ts
  • test/domains/comet-classic/classic-resume-probe.test.ts
  • test/domains/comet-classic/classic-runtime.test.ts
  • test/domains/comet-classic/comet-scripts-guard.test.ts
  • test/domains/comet-entry/hook-router.test.ts
  • test/domains/comet-entry/project-status.test.ts
  • test/domains/factory/factory-package.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • test/domains/comet-entry/project-status.test.ts
  • CHANGELOG.md
  • assets/skills/comet/scripts/comet-resume-probe.mjs
  • assets/skills/comet/scripts/comet-guard.mjs

Comment thread domains/comet-classic/classic-evidence.ts
Comment thread domains/comet-classic/classic-layout.ts

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/skills/comet/scripts/comet-archive.mjs`:
- Around line 136-166: Regenerate the Classic runtime bundles from their current
source so they pass pnpm build:classic-runtime --check and remain consistent:
update assets/skills/comet/scripts/comet-archive.mjs lines 136-166,
assets/skills/comet/scripts/comet-hook-guard.mjs lines 136-154, and
assets/skills/comet/scripts/comet-state.mjs lines 136-166; no source-level
behavior changes are required.

In `@assets/skills/comet/scripts/comet-runtime.mjs`:
- Around line 4-5: Add the missing reproducibility check for the generated
Classic runtime bundles by running pnpm build:classic-runtime with --check
before merge. Apply this to assets/skills/comet/scripts/comet-runtime.mjs lines
4-5, assets/skills/comet/scripts/comet-yaml-validate.mjs lines 4-5, and
assets/skills/comet/scripts/comet-handoff.mjs lines 4-5 so the release assets
are compared against the checked build output.
- Around line 177-186: Update the Classic root-move write flow in
classic-root-command.ts and classic-root-move.ts to call
assertClassicLayoutWritable() before performing writes, including the recovery
path. Do not rely solely on guarded file operations, and ensure the check occurs
after resolving the layout so managed root paths are rejected before any
root-move changes are applied.

In `@assets/skills/comet/scripts/comet-yaml-validate.mjs`:
- Line 4: Do not edit the generated comet-yaml-validate.mjs asset directly;
update the corresponding source under domains/comet-classic, then run pnpm
build:classic-runtime to regenerate and synchronize the asset.

In `@domains/comet-classic/classic-evidence.ts`:
- Around line 229-235: Update the layout-validation flow around
assertClassicLayoutReadable and linkedFileEvidence so a failed layout check
cannot continue into the generic file check or return satisfied: true. Propagate
the layout error to linked evidence, or explicitly return unsatisfied linked
evidence until a valid ClassicLayoutPaths value is available, while preserving
normal linked evidence behavior for valid layouts.

In `@domains/comet-classic/classic-layout.ts`:
- Around line 233-236: Update assertClassicLayoutReadable so
assertClassicManagedRootsPhysical validates only the Comet-managed
artifact_layout root and does not validate inspection.alternateRoot. Keep
alternateRoot available as untrusted reporting state, preserve configured-root
reads and writes when it is unsafe, and add a regression case covering an unsafe
alternate-root symlink or junction with a valid configured root.
🪄 Autofix

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 Plus

Run ID: 818a31e3-c8bb-4cda-a8c3-9fbd0d13042a

📥 Commits

Reviewing files that changed from the base of the PR and between 224dd8d and 49cd9b4.

📒 Files selected for processing (28)
  • CHANGELOG.md
  • app/commands/doctor.ts
  • assets/skills/comet/scripts/comet-archive.mjs
  • assets/skills/comet/scripts/comet-guard.mjs
  • assets/skills/comet/scripts/comet-handoff.mjs
  • assets/skills/comet/scripts/comet-hook-guard.mjs
  • assets/skills/comet/scripts/comet-hook-router.mjs
  • assets/skills/comet/scripts/comet-resume-probe.mjs
  • assets/skills/comet/scripts/comet-runtime.mjs
  • assets/skills/comet/scripts/comet-state.mjs
  • assets/skills/comet/scripts/comet-yaml-validate.mjs
  • docs/comet/specs/unified-product-catalogue/spec.md
  • domains/comet-classic/classic-evidence.ts
  • domains/comet-classic/classic-layout-initialization.ts
  • domains/comet-classic/classic-layout.ts
  • domains/comet-classic/classic-root-command.ts
  • domains/factory/package.ts
  • test/app/doctor.test.ts
  • test/domains/comet-classic/classic-evidence.test.ts
  • test/domains/comet-classic/classic-layout-initialization.test.ts
  • test/domains/comet-classic/classic-layout.test.ts
  • test/domains/comet-classic/classic-openspec-command.test.ts
  • test/domains/comet-classic/classic-resume-probe.test.ts
  • test/domains/comet-classic/classic-runtime.test.ts
  • test/domains/comet-classic/comet-scripts-guard.test.ts
  • test/domains/comet-entry/hook-router.test.ts
  • test/domains/comet-entry/project-status.test.ts
  • test/domains/factory/factory-package.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • test/domains/comet-entry/project-status.test.ts
  • CHANGELOG.md
  • assets/skills/comet/scripts/comet-resume-probe.mjs
  • assets/skills/comet/scripts/comet-guard.mjs
🛑 Comments failed to post (4)
assets/skills/comet/scripts/comet-archive.mjs (1)

136-166: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Confirm domains/comet-classic sources exist and the build script regenerates
# comet-archive.mjs, comet-hook-guard.mjs, and comet-state.mjs consistently.
set -euo pipefail

rg -n '"build:classic-runtime"' package.json
fd . domains/comet-classic --type f
fd 'comet-(archive|hook-guard|state)\.mjs$' assets/skills/comet/scripts

Repository: rpamis/comet

Length of output: 2450


🏁 Script executed:

#!/bin/bash
# Inspect the Classic build script usage and the generated/imported source fragments.
set -euo pipefail
printf '--- build-classic-runtime outline ---\n'
sed -n '1,220p' scripts/build/build-classic-runtime.mjs
printf '\n--- package build script context ---\n'
python3 - <<'PY'
import json
from pathlib import Path
data=json.loads(Path('package.json').read_text())
for k in ('build:classic-runtime','clean:skills','build'):
    print(f'{k}: {data.get("scripts", {}).get(k)!r}')
PY
printf '\n--- generated script entry/import references ---\n'
for f in assets/skills/comet/scripts/comet-{archive,hook-guard,state}.mjs; do
  echo "### $f"
  sed -n '1,80p' "$f" | sed -n '/import\|export\|process\.exitCode/p'
done

Repository: rpamis/comet

Length of output: 241


🏁 Script executed:

# No results to apply yet.

Repository: rpamis/comet

Length of output: 150


🏁 Script executed:

#!/bin/bash
# Inspect the Classic build script and generated entry references.
set -euo pipefail
printf '%s\n' '--- build-classic-runtime outline ---'
sed -n '1,220p' scripts/build/build-classic-runtime.mjs
printf '%s\n' ''
printf '%s\n' '--- package build script context ---'
python3 - <<'PY'
import json
from pathlib import Path
data=json.loads(Path('package.json').read_text())
for k in ('build:classic-runtime','clean:skills','build'):
    print(f'{k}: {data.get("scripts", {}).get(k)!r}')
PY
printf '%s\n' ''
printf '%s\n' '--- generated script entry/import references ---'
for f in assets/skills/comet/scripts/comet-{archive,hook-guard,state}.mjs; do
  printf '### %s\n' "$f"
  sed -n '1,80p' "$f" | sed -n '/import\|export\|process\.exitCode/p'
done

Repository: rpamis/comet

Length of output: 23687


Make these Classic assets pass pnpm build:classic-runtime --check. The Classic runtime build generates separate bundles for assets/skills/comet/scripts/comet-archive.mjs, assets/skills/comet/scripts/comet-hook-guard.mjs, and assets/skills/comet/scripts/comet-state.mjs; regenerate them with the same source to keep the asset outputs consistent.

📍 Affects 3 files
  • assets/skills/comet/scripts/comet-archive.mjs#L136-L166 (this comment)
  • assets/skills/comet/scripts/comet-hook-guard.mjs#L136-L154
  • assets/skills/comet/scripts/comet-state.mjs#L136-L166
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/skills/comet/scripts/comet-archive.mjs` around lines 136 - 166,
Regenerate the Classic runtime bundles from their current source so they pass
pnpm build:classic-runtime --check and remain consistent: update
assets/skills/comet/scripts/comet-archive.mjs lines 136-166,
assets/skills/comet/scripts/comet-hook-guard.mjs lines 136-154, and
assets/skills/comet/scripts/comet-state.mjs lines 136-166; no source-level
behavior changes are required.

Source: Coding guidelines

assets/skills/comet/scripts/comet-runtime.mjs (2)

4-5: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify Classic source ownership and generated-bundle reproducibility.
set -euo pipefail

# Confirm the declared generator command.
rg -n '"build:classic-runtime"' package.json

# Confirm Classic logic lives in the source domain.
rg -n -C4 'dualRoots|alternateRoot|configuredRootExists|standalone OpenSpec root' domains --type=ts || true

# Confirm the repository asserts generated-runtime parity in tests.
fd -t f -g '*runtime-assets*.test.ts' test || true
rg -n -C4 'comet-runtime.mjs|comet-handoff.mjs|comet-yaml-validate.mjs' test/repository config/repository-layout.json assets/manifest.json || true

Repository: rpamis/comet

Length of output: 18534


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== classic-runtime build script outline =="
wc -l scripts/build/build-classic-runtime.mjs
ast-grep outline scripts/build/build-classic-runtime.mjs || true
echo

echo "== key build-classic-runtime sections =="
rg -n -C4 'classicRuntime|manifest|repository-layout|readJson|cpSync|generate|outputs|dual|alternate|standalone' scripts/build/build-classic-runtime.mjs || true
echo

echo "== source references to validation/standalone/evidence text in bundles =="
python3 - <<'PY'
from pathlib import Path
import re
bundles = [
    Path('assets/skills/comet/scripts/comet-runtime.mjs'),
    Path('assets/skills/comet/scripts/comet-yaml-validate.mjs'),
    Path('assets/skills/comet/scripts/comet-handoff.mjs'),
]
patterns = {
    'dual': r'dualRoots|alternateRoot|configuredRootExists|Artifact root is not found in the configured Classic OpenSpec root|dual |two|^' + re.escape('standalone OpenSpec root is not a Comet artifact root') + r'|refusing to move|Refusing to move',
    'validate': r'Refusing to remove an OpenSpec root that does not match project config|Refusing to remove conflicting legacy and docs OpenSpec roots|dualRoots|alternateRootExists',
    'handoff': r'Configured Classic OpenSpec root is missing|alternate is .*present|standalone OpenSpec root is not a Comet artifact root|root ownership boundary',
}
for bundle in bundles:
    text = bundle.read_text(errors='replace')
    print(f'-- {bundle}')
    for name, pat in patterns.items():
        print(f'{name}:', 'YES' if re.search(pat, text, re.S) else 'NO')
        if name != 'validate':
            for i, line in enumerate(text.splitlines(), 1):
                if re.search(pat, line):
                    print(f'  {i}: {line[:220]!r}')
    print()
PY

echo "== test coverage around runtime assets reproducibility =="
wc -l test/repository/classic-runtime-assets.test.ts
cat -n test/repository/classic-runtime-assets.test.ts
echo

echo "== git status stat/diff summary =="
git status --short
git diff --stat
echo

Repository: rpamis/comet

Length of output: 9019


Run the reproducibility check for the three Classic runtime bundles. These are generated release assets, and the current test coverage does not compare them against pnpm build:classic-runtime. Run the build with --check before merge to cover comet-runtime.mjs, comet-yaml-validate.mjs, and comet-handoff.mjs.

📍 Affects 3 files
  • assets/skills/comet/scripts/comet-runtime.mjs#L4-L5 (this comment)
  • assets/skills/comet/scripts/comet-yaml-validate.mjs#L4-L5
  • assets/skills/comet/scripts/comet-handoff.mjs#L4-L5
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/skills/comet/scripts/comet-runtime.mjs` around lines 4 - 5, Add the
missing reproducibility check for the generated Classic runtime bundles by
running pnpm build:classic-runtime with --check before merge. Apply this to
assets/skills/comet/scripts/comet-runtime.mjs lines 4-5,
assets/skills/comet/scripts/comet-yaml-validate.mjs lines 4-5, and
assets/skills/comet/scripts/comet-handoff.mjs lines 4-5 so the release assets
are compared against the checked build output.

Source: Coding guidelines


177-186: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify that Classic write paths use the write-guarded layout resolver.
set -euo pipefail

# Find both resolvers in source and list their callers.
rg -n -C5 'classic-root-move.json' domains --type=ts || true
rg -n -C3 'ensureClassicLayout|requireWritableClassicLayout|resolveClassicLayout' domains app --type=ts || true

# Confirm regression coverage for the read-relaxed and write-blocked cases.
rg -n -C4 'dualRoots|alternateRootExists|configuredRootExists' test --type=ts || true

Repository: rpamis/comet

Length of output: 6612


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== classic-layout exports and layout resolver =="
ast-grep outline domains/comet-classic/classic-layout.ts --view expanded | sed -n '1,220p'
echo
echo "== classic-layout relevant sections =="
sed -n '140,280p' domains/comet-classic/classic-layout.ts | cat -n
echo
echo "== writes using assertClassicLayoutWritable / direct Classic writer APIs =="
rg -n -C3 'assertClassicLayoutWritable|writeClassicArtifactLayout|runClassic|commitClassicClassic|classic-root-move|requireWritableClassicLayout|resolveClassicLayout' --glob '!**/dist/**' --glob '!**/build/**' .
echo
echo "== command callers of layout resolvers =="
for f in app/commands/doctor.ts app/commands/*.ts domains/comet-classic/*.ts; do
  [ -f "$f" ] || continue
  echo "-- $f"
  rg -n 'resolveClassicLayout|assertClassicLayoutWritable|inspectClassicLayout|writeClassicArtifactLayout|classic-root-move' "$f" || true
done

Repository: rpamis/comet

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== classic command tests with layout assertions =="
rg -n -C4 'assertClassicLayoutWritable|resolveClassicLayout|dualRoots|alternateRootExists|configuredRootExists|root move|old|new|legacy|docs' test/domains test/app --type=ts || true
echo
echo "== relevant test files =="
wc -l test/domains/comet-classic/classic-root-command.test.ts domains/comet-classic/classic-layout.ts domains/comet-classic/classic-root-move.ts

Repository: rpamis/comet

Length of output: 50369


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== sources importing resolver functions =="
rg -n 'from .*classic-layout\.js|from ./classic-layout' domains app --type=ts --type-add ts:*.ts --type-add ts:*.tsx --type-add ts:*.mjs --type-add ts:*.cjs || true

echo
echo "== Classic command/source files under domains/comet-classic =="
git ls-files 'domains/comet-classic/*.ts' 'app/commands/*.ts' | sed 's#^\./##' | sort

echo
echo "== exports/usages in source file names =="
for f in $(git ls-files 'domains/comet-classic/*.ts' 'app/commands/*.ts' | sort); do
  echo "-- $f"
  rg -n 'resolveClassicLayout|assertClassicLayoutWritable|inspectClassicLayout|writeClassicArtifactLayout|classic-root-move|classic/layout|resolveClassic.*Root|Ee|G\(' "$f" || true
done

echo
echo "== classic root move relevant section =="
sed -n '280,520p' domains/comet-classic/classic-root-move.ts | cat -n

echo
echo "== deterministic behavior probe from source text =="
python3 - <<'PY'
from pathlib import Path
p=Path('domains/comet-classic/classic-layout.ts')
s=p.read_text()
start=s.find('async function G(')
end=s.find('async function Ee(', start)
print(s[start:end])
print('\n--- assertClassicLayoutWritable ---')
a=s.find('export async function assertClassicLayoutWritable(')
print(s[a:a+1200])
PY

Repository: rpamis/comet

Length of output: 24346


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== inspectClassicLayout source =="
sed -n '150,240p' domains/comet-classic/classic-layout.ts | cat -n

echo
echo "== exports from classic-layout =="
sed -n '1,180p' domains/comet-classic/classic-layout.ts | cat -n

echo
echo "== classic-layout-initialization around legacy root write guards =="
sed -n '920,1185p' domains/comet-classic/classic-layout-initialization.ts | cat -n

echo
echo "== writeClassicArtifactLayout source =="
sed -n '90,150p' domains/comet-classic/classic-layout.ts | cat -n

echo
echo "== focused Classic write entry points using assertClassicLayoutWritable/source paths directly =="
python3 - <<'PY'
from pathlib import Path
for p in Path('domains/comet-classic').glob('*.ts'):
    text=p.read_text()
    if 'resolveClassicLayout(' in text or 'assertClassicLayoutReadable(' in text:
        print(f'-- {p}')
        for i,line in enumerate(text.splitlines(),1):
            if 'resolveClassicLayout(' in line or 'assertClassicLayoutReadable(' in line or 'classicLayoutPaths(' in line and 'resolveClassicLayout' not in line:
                print(f'{i}: {line.strip()}')
    if 'assertClassicLayoutWritable(' in text:
        print(f'-- {p}')
        for i,line in enumerate(text.splitlines(),1):
            if 'assertClassicLayoutWritable(' in line:
                print(f'{i}: {line.strip()}')
PY

Repository: rpamis/comet

Length of output: 29439


Gate root-move writes through the write-safe layout resolver.

resolveClassicLayout() now skips managed root paths, while classic-root-command.ts still calls it before classic-root-move.ts can apply root-move write guards. Use assertClassicLayoutWritable() before Classic root-move writes, including the recovery path, before relying only on guarded file operations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/skills/comet/scripts/comet-runtime.mjs` around lines 177 - 186, Update
the Classic root-move write flow in classic-root-command.ts and
classic-root-move.ts to call assertClassicLayoutWritable() before performing
writes, including the recovery path. Do not rely solely on guarded file
operations, and ensure the check occurs after resolving the layout so managed
root paths are rejected before any root-move changes are applied.
assets/skills/comet/scripts/comet-yaml-validate.mjs (1)

4-4: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Confirm Classic layout changes exist in source and that generated bundles are reproducible.
set -euo pipefail

# Locate the Classic layout source that owns configured-root inspection.
fd -t f 'classic-layout*.ts' domains || true
rg -n -C4 'ClassicLayoutConflictError|dualRoots|alternateRoot|configuredRootExists' domains --type=ts || true

# Confirm the build script exists and is the declared generator for the bundles.
rg -n '"build:classic-runtime"' package.json
rg -n -C3 'comet-yaml-validate|comet-handoff|comet-runtime' package.json scripts 2>/dev/null || true

Repository: rpamis/comet

Length of output: 17027


🏁 Script executed:

#!/bin/bash
# Inspect the generated bundle size and whether it is tracked / gitignored.
set -euo pipefail
printf 'tracked:\n'
git ls-files assets/skills/comet/scripts/comet-yaml-validate.mjs assets/skills/comet/scripts/comet-runtime.mjs || true
printf '\nignore patterns:\n'
git check-ignore -v assets/skills/comet/scripts/comet-yaml-validate.mjs assets/skills/comet/scripts/comet-runtime.mjs || true
printf '\nalphabetical hashes and sizes:\n'
git ls-tree HEAD assets/skills/comet/scripts --no-renames | sort
printf '\nsize:\n'
wc -c assets/skills/comet/scripts/comet-yaml-validate.mjs assets/skills/comet/scripts/comet-runtime.mjs 2>/dev/null || true

Repository: rpamis/comet

Length of output: 1043


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'package scripts around build:classic-runtime:\n'
python3 - <<'PY'
import json
from pathlib import Path
p=Path('package.json')
if p.exists():
    data=json.loads(p.read_text())
    print(data.get('scripts',{}).get('build:classic-runtime')or '')
PY

printf '\nbuild script references:\n'
rg -n 'build-classic-runtime|mjs$|bundle|esbuild|vite|rollup|webpack' scripts/build -g '*.mjs' -g '*.ts' || true
fd -t f 'build-classic-runtime\.mjs|build-classic-runtime\.ts' scripts/assets scripts -i || true

printf '\nasset files in comet scripts:\n'
git ls-tree --name-only HEAD -- assets/skills/comet/scripts/ | sort

printf '\nfile sizes:\n'
wc -c assets/skills/comet/scripts/comet-yaml-validate.mjs assets/skills/comet/scripts/comet-runtime.mjs

Repository: rpamis/comet

Length of output: 3190


Keep generated Classic assets in sync with the build script.

comet-yaml-validate.mjs is produced by pnpm build:classic-runtime, whose sources live under domains/comet-classic/. Run that build and check the generated asset; edit source code before assets/skills/comet/scripts/comet-yaml-validate.mjs instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/skills/comet/scripts/comet-yaml-validate.mjs` at line 4, Do not edit
the generated comet-yaml-validate.mjs asset directly; update the corresponding
source under domains/comet-classic, then run pnpm build:classic-runtime to
regenerate and synchronize the asset.

Source: Coding guidelines

@benym
benym merged commit 07c5b64 into master Aug 5, 2026
21 checks passed
@benym
benym deleted the codex/hotfix-issue-277-282 branch August 5, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant