Skip to content

fix(ops): make operator export scripts honor --help and refuse out-of-repo output paths - #55

Closed
nish3451 wants to merge 2 commits into
mainfrom
fix/lane1-operator-export-cli-help
Closed

fix(ops): make operator export scripts honor --help and refuse out-of-repo output paths#55
nish3451 wants to merge 2 commits into
mainfrom
fix/lane1-operator-export-cli-help

Conversation

@nish3451

Copy link
Copy Markdown
Collaborator

What

Closes the operator-export CLI safety gap: export scripts ignored --help and
accepted --output/--html/--ops/--loom-links paths that could write or
overwrite cockpits, missions, and other files anywhere on the machine.

Repro against origin/main: node scripts/export-growth-metrics.mjs --help
exits 0 while silently regenerating and overwriting the tracked
growth-brain/ops/live-metrics.md, and
node scripts/export-daily-money-mission.mjs --output=/tmp/escape.md writes
outside the repository.

Changes

  • New scripts/lib/operator-cli.mjs
    • handleHelp(args, usage) — prints usage and exits 0 before any work when
      --help / -h is present.
    • resolveOutputPath(value, {flag, fallback}) — resolves operator-supplied
      output paths against the service repository root and refuses paths that
      escape it via absolute paths, .. traversal, or symlinks. Component-wise
      lstatSync checks catch live symlink escapes and dangling symlinks
      (whose target writeFileSync would silently create outside the repo).
  • Wired into all 21 npm-script-backed export scripts: every output flag is
    validated before any dependency exporter runs or any artifact is written;
    parent dirs derive from dirname() instead of split("/").
  • export-internal-dashboard no longer writes its parity scratch file to
    /tmp; it uses a unique, gitignored runs/ path cleaned up in finally.
  • export-market-benchmark reports operator-facing relative paths in its
    JSON output so the tracked market-parity-readiness artifact content is
    unchanged.
  • Extended test-active-operator-surfaces.mjs: every active export script
    must exit 0 on --help and -h, print usage, and leave tracked + private
    artifacts untouched; escaping --output/--html/--ops/--loom-links
    probes (confined to a test-owned tmp dir), a live-symlink escape, and a
    dangling-symlink escape are all refused without creating files.

Validation

  • npm test passes end to end (all suites, including tracked-artifact
    byte-identical regeneration checks).

…-repo output paths

Every active operator export script now handles --help/-h before doing any
work: it prints usage and exits 0 without writing or overwriting any cockpit
or mission artifact. Operator-supplied output paths (--output, --html, --ops,
--loom-links) are resolved against the service repository root and refused
when they escape it via absolute paths, .. traversal, or symlinks -- including
dangling symlinks whose target writeFileSync would silently create outside
the repo -- so an export can no longer write or overwrite files anywhere.

- Add scripts/lib/operator-cli.mjs with handleHelp() and resolveOutputPath()
- Wire both into all 21 npm-script-backed export scripts; validate every
  output path before any dependency exporter runs or any artifact is written
- Route the internal-dashboard parity scratch inside the repo (unique
  runs/ path, cleaned up in finally) instead of /tmp
- Extend test-active-operator-surfaces.mjs: --help and -h contract for every
  active export script (exit 0 + usage + untouched artifacts), escape probes
  confined to a test-owned tmp directory, and symlink/dangling-symlink
  refusal probes

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

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@nish3451, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b52ec313-783f-4abb-9c86-c9df957eceb6

📥 Commits

Reviewing files that changed from the base of the PR and between 2e3c00e and d144035.

📒 Files selected for processing (23)
  • scripts/export-client-delivery-cockpit.mjs
  • scripts/export-daily-money-mission.mjs
  • scripts/export-followup-cockpit.mjs
  • scripts/export-growth-cockpit.mjs
  • scripts/export-growth-doctor.mjs
  • scripts/export-growth-metrics.mjs
  • scripts/export-internal-dashboard.mjs
  • scripts/export-lead-scoring-cockpit.mjs
  • scripts/export-managed-it-one-pager.mjs
  • scripts/export-market-benchmark.mjs
  • scripts/export-market-learning-review.mjs
  • scripts/export-market-proof-cockpit.mjs
  • scripts/export-market-proof-run.mjs
  • scripts/export-proof-library.mjs
  • scripts/export-prospect-outbox.mjs
  • scripts/export-recording-cockpit.mjs
  • scripts/export-recording-queue.mjs
  • scripts/export-recording-rehearsal-check.mjs
  • scripts/export-recording-teleprompter.mjs
  • scripts/export-sales-cockpit.mjs
  • scripts/export-sender-setup-guide.mjs
  • scripts/lib/operator-cli.mjs
  • scripts/test-active-operator-surfaces.mjs

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5416994af7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}
}
}
return resolved;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep reported paths repository-relative

When an export uses either its default path or a relative output flag, this return value converts the path to an absolute host-specific path, and callers then serialize it directly (for example, export-recording-queue.mjs returns it as path, while prepare-recording-batch.mjs propagates that value and export-internal-dashboard.mjs embeds dependent exporters' paths in generated documents). This breaks the existing repository-relative CLI result contract and leaks checkout-specific prefixes into operator output; retain the raw repository-relative path for reporting while using the resolved path only for filesystem operations.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

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

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

nish3451 added a commit that referenced this pull request Aug 11, 2026
The fleet keeps dispatching the same finding to multiple lanes, producing
duplicate same-fix PR pairs: #36/#44 and #55/#56 are byte-identical or
near-identical patches of the operator export --help fix, #39/#49 the
offername article fix, #40/#52 the recording exporter --help fix, plus
#38/#48/#51, #30/#61/#72, #45/#64, #42/#60, #43/#54 and #46/#74.

Add a PR Duplicate Guard:
- scripts/check-pr-duplicates.mjs compares a PR's diff against every other
  open PR (shared changed-file coverage >= 0.8 and patch similarity >= 0.5).
  Calibrated on all 79 open PRs on 2026-08-11: every pair above the
  thresholds was a genuine duplicate-cluster member, zero false positives.
- .github/workflows/pr-duplicate-guard.yml runs it on every PR event and
  posts one marker comment naming the duplicate(s) and the canonical PR; the
  check fails loudly when a duplicate is found. Informational, not required.
- scripts/test-pr-duplicates.mjs covers parsing, similarity, detection, and
  comment upsert with an injected API; wired into npm ci and npm test.
@nish3451

Copy link
Copy Markdown
Collaborator Author

Superseded by #56 — same shared-helper approach, and #56 is a strict superset (99% of this PR's changes are contained in it, plus 8 more exporters). Closing in favour of #56.

@nish3451 nish3451 closed this Aug 19, 2026
@nish3451

Copy link
Copy Markdown
Collaborator Author

Correction to my closing comment above: the keeper for this cluster is #160, not #56.

I had wrongly concluded that main had no exporters wired for --help. In fact main already wires 18 of 29 exporters to scripts/lib/operator-cli.mjs; only 11 remain, and #160 covers exactly those 11 using main's current helper. #56 has since been closed because it would revert main's newer operator-cli.mjs and re-apply an older calling convention across 18 already-finished exporters.

This PR stays closed either way — its content is superseded by what is already on main plus #160 — but the pointer should be to #160.

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