Skip to content

feat/RR-1024-cli-rocketride-init#1034

Open
EdwardLien0426 wants to merge 27 commits into
rocketride-org:developfrom
EdwardLien0426:feat/RR-1024-agents-core-and-init
Open

feat/RR-1024-cli-rocketride-init#1034
EdwardLien0426 wants to merge 27 commits into
rocketride-org:developfrom
EdwardLien0426:feat/RR-1024-agents-core-and-init

Conversation

@EdwardLien0426
Copy link
Copy Markdown
Collaborator

@EdwardLien0426 EdwardLien0426 commented May 29, 2026

Closes #1024

Why

Make the VS Code extension's project scaffolding available headlessly via
rocketride init. The extension's installers were coupled to vscode APIs, so
P1 extracts a framework-agnostic core and P2 builds the CLI on top.

What

P1 — @rocketride/agents-core (new workspace package)

  • Ports BaseAgentInstaller, the six installers, installDocs, ensureGitignore,
    syncServiceCatalog, AgentManager — fs/promises + path only, no vscode.
  • Injected Logger; bundles the 8 docs + 6 stubs so it's self-contained.

P2 — rocketride init (in packages/client-typescript)

  • init [--agent <slug...>] [--no-catalog] [--apikey] [--uri]; default installs
    all agents; slugs map to canonical names; unknown slug exits 1.
  • Scaffolds .rocketride/docs, agent stubs, .gitignore, and a .env template
    (created only if absent; .env added to .gitignore).
  • Catalog sync is graceful: no apikey / unreachable server → warn + continue.
  • Fix: removed import * as process (crashed the CLI bin at startup on Node 26).

Out of scope

  • P3: migrate the extension to consume agents-core (auto-detect stays there).

Verification

  • pnpm -F @rocketride/agents-core test → 29 passed
  • pnpm -F ./packages/client-typescript exec jest init.test.ts → 9 passed
  • pnpm -F ./packages/client-typescript exec tsc -p tsconfig.cli.json --noEmit → clean
  • Built bin: rocketride init --no-catalog scaffolds correctly; --agent foo exits 1

Summary by CodeRabbit

  • New Features

    • Added rocketride init CLI to scaffold projects with agent stubs, non‑destructive .env creation, optional service-catalog sync, and idempotent installs
    • New packaged agent-install tooling and bundled docs for automatic workspace onboarding
  • Documentation

    • Many new RocketRide docs: quickstart, SDK API references, pipeline rules, component reference, observability, troubleshooting, and editor/tool stubs
  • Tests

    • Extensive tests for installers, docs/catalog sync, init flow, and idempotency
  • Chores

    • Workspace and build/task updates to include the new package and CI/dev tooling adjustments

Review Change Stack

EdwardLien0426 and others added 22 commits May 28, 2026 13:50
…indsurf / Copilot / CLAUDE.md / AGENTS.md)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
`import * as process from 'process'` compiles to __importStar(), which
copies only own-enumerable properties and drops EventEmitter prototype
methods like process.on. On Node >=~20 (seen on Node 26) this crashed the
CLI binary at startup in setupSignalHandlers (process.on is not a function),
breaking every command. process is a Node global, so the import is removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

📝 Walkthrough

Walkthrough

Adds a headless rocketride init CLI command and a new @rocketride/agents-core package to scaffold bundled docs, IDE stubs, .env (idempotent), and optionally sync a services catalog; includes tests, package/task wiring, and CLI registration.

Changes

rocketride init CLI Feature

Layer / File(s) Summary
Design specs and bundled docs
docs/superpowers/specs/2026-05-29-rocketride-init-design.md, docs/superpowers/plans/2026-05-29-p2-rocketride-init.md, packages/agents-core/docs/*, packages/agents-core/docs/stubs/*
Spec and plan for rocketride init plus eight bundled RocketRide docs and six stub files to be synced into workspaces.
agents-core package infra
packages/agents-core/package.json, packages/agents-core/tsconfig.json, packages/agents-core/jest.config.js, packages/agents-core/src/types.ts, .devcontainer/devcontainer-lock.json
New package @rocketride/agents-core with TypeScript/Jest config, shared Logger/ResourceBundle types, and devcontainer lock.
Installer base & concrete installers
packages/agents-core/src/installers/base-installer.ts, packages/agents-core/src/installers/*
BaseAgentInstaller implements marker-aware insertion/removal; six concrete installers expose name, stubSource, and stubTarget.
Docs & catalog sync utilities
packages/agents-core/src/docs-sync.ts, packages/agents-core/src/catalog-sync.ts
installDocs() syncs bundled docs into .rocketride/docs/ idempotently; ensureGitignore() appends .rocketride/; syncServiceCatalog() writes sanitized per-service schemas and a consolidated services-catalog.json only on changes.
AgentManager & package exports
packages/agents-core/src/agent-manager.ts, packages/agents-core/src/index.ts
AgentManager orchestrates installs/uninstalls and package index re-exports public API plus defaultBundle().
agents-core tests
packages/agents-core/test/*, packages/agents-core/test/helpers.ts
Jest suites validate installer marker behavior, docs/catalog sync, AgentManager flows, helpers, and smoke/idempotency checks.
CLI init implementation
packages/client-typescript/src/cli/init.ts
resolveAgents() slug → canonical mapping and validation; scaffoldEnv() writes .env only when missing and ensures .gitignore; runInit() uses AgentManager to install stubs, optionally fetches and syncs catalog via injected fetchCatalog, and returns an exit code; defaultFetchCatalog() uses the TypeScript SDK and returns null on failure.
CLI wiring & workspace integration
packages/client-typescript/src/cli/rocketride.ts, packages/client-typescript/package.json, pnpm-workspace.yaml, packages/client-typescript/scripts/tasks.js
Registers init subcommand with --agent/--no-catalog, adds @rocketride/agents-core as a workspace dependency, includes packages/agents-core in pnpm workspace, and ensures client build runs agents-core build first.
CLI init tests
packages/client-typescript/tests/init.test.ts
Offline and catalog-mode tests for resolveAgents() and runInit() verifying scaffolding, idempotency, selective agent installs, and graceful catalog handling.
CI & tooling updates
.github/workflows/discord-discussions.yml, .github/copilot-instructions.md, .devcontainer/devcontainer-lock.json
Discord webhook URL normalization and safer endpoints; Copilot instructions file; pinned devcontainer features.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • #1024 — Implements the requested rocketride init headless scaffolding feature described in the issue.

Possibly related PRs

Suggested labels

module:client-typescript

Suggested reviewers

  • jmaionchi
  • stepmikhaylov
  • kwit75

"— a rabbit's note —
I hopped through docs and stubs so neat,
Seeded .env and stashed each stub complete.
Agents lined up, catalogs synced (or skipped),
Tests run, idempotent — no files ripped.
Hooray — the CLI now scaffolds on repeat!"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

@github-actions
Copy link
Copy Markdown

No description provided.

The custom ./builder discovers per-package scripts/tasks.js; agents-core had
none, so it was never built (or tested) in CI. client-typescript:compile-cli
runs 'tsc -p tsconfig.cli.json' and imports @rocketride/agents-core, which
needs its built dist/index.d.ts — absent in CI, causing TS2307.

- Add packages/agents-core/scripts/tasks.js with agents-core:build / :test /
  :clean (auto-discovered by the builder; build/test now run in CI).
- Prepend agents-core:build to client-typescript:build steps so the CLI
  compile resolves agents-core types regardless of parallel module ordering.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 `@packages/agents-core/package.json`:
- Around line 19-23: The package.json currently mixes Jest major versions:
"`@jest/globals`" and "`@types/jest`" are v30 while "jest" and "ts-jest" are v29;
pick a single major and make all jest-related dependencies consistent (update
either "jest" and "ts-jest" to v30 to match "`@jest/globals`"/"`@types/jest`" or
downgrade "`@jest/globals`" and "`@types/jest`" to v29), adjusting the versions for
the keys "jest", "ts-jest", "`@jest/globals`", and "`@types/jest`" accordingly, then
reinstall/update lockfile and run the test suite to verify tooling/type
compatibility.

In `@packages/agents-core/src/catalog-sync.ts`:
- Around line 76-88: The map creating catalog must guard against null/undefined
service entries: inside the serviceNames.map callback, check if services[name]
(svc) is nullish before accessing properties and build a safe entry with
defaults (e.g., classType: [], description: undefined/'' via firstSentence,
lanes: {}, and only add invoke when present); update the logic around const svc
= services[name] as Record<string, unknown> and the entry creation in the
catalog variable so accessing svc.classType, svc.description or svc.lanes cannot
throw when svc is null.

In `@packages/agents-core/src/installers/base-installer.ts`:
- Around line 53-60: The uninstall flow in base-installer.ts is returning true
even when no markers were found because stripMarkedContent(existing) returns the
original content; change the logic in the uninstall method (the block that uses
stripMarkedContent and fs.unlink/fs.writeFile) to detect when stripped ===
existing and return false (no-op) instead of true; keep the existing behavior of
removing the file when stripped.trim() is empty and writing when different, and
make the same change to the second similar block (the one around lines 83-87) so
both locations return false when there is no content change.

In `@packages/agents-core/test/smoke.test.ts`:
- Around line 5-25: The smoke test currently uses defaultBundle() (from
packages/agents-core) which resolves docs via __dirname in source layout and
misses issues in the emitted ESM/dist artifact; update the test to exercise the
same bundle resolution used in production by invoking the packaged entrypoint
(import/require the built/compiled module that exports defaultBundle or call
AgentManager.installAll against the runtime-resolved artifact bundle) instead of
calling defaultBundle() from src, so the test imports/loads the bundle path the
distributed package would use and then runs mkTempWorkspace(), new
AgentManager(), and installAll(...) to assert the same DOC_FILES and stub paths
exist; reference defaultBundle(), AgentManager.installAll, and mkTempWorkspace()
when making this change.

In `@packages/client-typescript/src/cli/init.ts`:
- Around line 108-126: Refactor scaffoldEnv to be async and use fs/promises:
replace synchronous fs calls (existsSync, readFileSync, writeFileSync) with the
promise-based APIs (fs.promises.access or stat to check existence, readFile,
writeFile) and propagate errors appropriately; update scaffoldEnv signature to
async scaffoldEnv(cwd: string, log: (msg: string) => void): Promise<void> and
ensure it returns after awaiting file operations. Also update the runInit caller
to await scaffoldEnv(...) so the init flow waits for the async I/O to complete.
Keep the same behavior (create .env if missing, append .env to .gitignore if not
present) and preserve log('Created .env') when the file is created.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6203586e-600d-4d41-910c-1d268f019f47

📥 Commits

Reviewing files that changed from the base of the PR and between 753530b and 08ef524.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (45)
  • docs/superpowers/plans/2026-05-29-p2-rocketride-init.md
  • docs/superpowers/specs/2026-05-29-rocketride-init-design.md
  • packages/agents-core/.gitignore
  • packages/agents-core/docs/ROCKETRIDE_COMMON_MISTAKES.md
  • packages/agents-core/docs/ROCKETRIDE_COMPONENT_REFERENCE.md
  • packages/agents-core/docs/ROCKETRIDE_OBSERVABILITY.md
  • packages/agents-core/docs/ROCKETRIDE_PIPELINE_RULES.md
  • packages/agents-core/docs/ROCKETRIDE_QUICKSTART.md
  • packages/agents-core/docs/ROCKETRIDE_README.md
  • packages/agents-core/docs/ROCKETRIDE_python_API.md
  • packages/agents-core/docs/ROCKETRIDE_typescript_API.md
  • packages/agents-core/docs/stubs/AGENTS.md
  • packages/agents-core/docs/stubs/CLAUDE.md
  • packages/agents-core/docs/stubs/claude-code.md
  • packages/agents-core/docs/stubs/copilot-instructions.md
  • packages/agents-core/docs/stubs/cursor.mdc
  • packages/agents-core/docs/stubs/windsurf.md
  • packages/agents-core/jest.config.js
  • packages/agents-core/package.json
  • packages/agents-core/scripts/sync-bundle.ts
  • packages/agents-core/src/agent-manager.ts
  • packages/agents-core/src/catalog-sync.ts
  • packages/agents-core/src/docs-sync.ts
  • packages/agents-core/src/index.ts
  • packages/agents-core/src/installers/agents-md-installer.ts
  • packages/agents-core/src/installers/base-installer.ts
  • packages/agents-core/src/installers/claude-code-installer.ts
  • packages/agents-core/src/installers/claude-md-installer.ts
  • packages/agents-core/src/installers/copilot-installer.ts
  • packages/agents-core/src/installers/cursor-installer.ts
  • packages/agents-core/src/installers/windsurf-installer.ts
  • packages/agents-core/src/types.ts
  • packages/agents-core/test/agent-manager.test.ts
  • packages/agents-core/test/base-installer.test.ts
  • packages/agents-core/test/catalog-sync.test.ts
  • packages/agents-core/test/docs-sync.test.ts
  • packages/agents-core/test/helpers.ts
  • packages/agents-core/test/installers.test.ts
  • packages/agents-core/test/smoke.test.ts
  • packages/agents-core/tsconfig.json
  • packages/client-typescript/package.json
  • packages/client-typescript/src/cli/init.ts
  • packages/client-typescript/src/cli/rocketride.ts
  • packages/client-typescript/tests/init.test.ts
  • pnpm-workspace.yaml

Comment thread packages/agents-core/package.json Outdated
Comment thread packages/agents-core/src/catalog-sync.ts
Comment on lines +53 to +60
const stripped = this.stripMarkedContent(existing);
if (stripped.trim() === '') {
await fs.unlink(target);
} else {
await fs.writeFile(target, stripped, 'utf8');
}
return true;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return false when uninstall makes no content change.

If markers are missing/invalid, stripMarkedContent() returns the original content, but uninstall() still returns true. That reports a successful uninstall when nothing was removed.

Targeted fix
   async uninstall(workspaceRoot: string): Promise<boolean> {
@@
     const stripped = this.stripMarkedContent(existing);
+    if (stripped === existing) {
+      return false;
+    }
     if (stripped.trim() === '') {
       await fs.unlink(target);
     } else {
       await fs.writeFile(target, stripped, 'utf8');
     }
     return true;
   }

Also applies to: 83-87

🤖 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 `@packages/agents-core/src/installers/base-installer.ts` around lines 53 - 60,
The uninstall flow in base-installer.ts is returning true even when no markers
were found because stripMarkedContent(existing) returns the original content;
change the logic in the uninstall method (the block that uses stripMarkedContent
and fs.unlink/fs.writeFile) to detect when stripped === existing and return
false (no-op) instead of true; keep the existing behavior of removing the file
when stripped.trim() is empty and writing when different, and make the same
change to the second similar block (the one around lines 83-87) so both
locations return false when there is no content change.

Comment on lines +5 to +25
describe('smoke: installAll using bundled docs', () => {
it('produces the canonical .rocketride/ + agent stub layout', async () => {
const ws = await mkTempWorkspace();
const mgr = new AgentManager();
await mgr.installAll(defaultBundle(), ws, () => undefined);

for (const f of DOC_FILES) {
expect(await exists(path.join(ws, '.rocketride/docs', f))).toBe(true);
}
expect(await exists(path.join(ws, '.gitignore'))).toBe(true);
for (const stubTarget of [
'.claude/rules/rocketride.md',
'.cursor/rules/rocketride.mdc',
'.windsurf/rules/rocketride.md',
'.github/copilot-instructions.md',
'CLAUDE.md',
'AGENTS.md',
]) {
expect(await exists(path.join(ws, stubTarget))).toBe(true);
}
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Smoke test won't validate the packaged artifact's bundle path.

This relies on defaultBundle(), which resolves __dirname/../docs. Under ts-jest it runs against the src/ layout as CommonJS, so it passes even if the emitted ESM/dist artifact resolves the docs path incorrectly or trips over an undefined __dirname. This is the downstream blind spot for the defaultBundle() concern raised in packages/agents-core/src/index.ts; resolving the root cause there covers this.

🤖 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 `@packages/agents-core/test/smoke.test.ts` around lines 5 - 25, The smoke test
currently uses defaultBundle() (from packages/agents-core) which resolves docs
via __dirname in source layout and misses issues in the emitted ESM/dist
artifact; update the test to exercise the same bundle resolution used in
production by invoking the packaged entrypoint (import/require the
built/compiled module that exports defaultBundle or call AgentManager.installAll
against the runtime-resolved artifact bundle) instead of calling defaultBundle()
from src, so the test imports/loads the bundle path the distributed package
would use and then runs mkTempWorkspace(), new AgentManager(), and
installAll(...) to assert the same DOC_FILES and stub paths exist; reference
defaultBundle(), AgentManager.installAll, and mkTempWorkspace() when making this
change.

Comment thread packages/client-typescript/src/cli/init.ts Outdated
- agents-core: pin Jest devDeps to v29 line (package.json)
- agents-core: add null-guard in catalog-sync.ts
- cli: refactor scaffoldEnv to async (init.ts)
- docs: add P1 agents-core extraction plan
- chore: add copilot-instructions, devcontainer lock, discord workflow tweak

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@EdwardLien0426 EdwardLien0426 requested a review from kwit75 as a code owner May 29, 2026 18:47
@github-actions github-actions Bot added the ci/cd CI/CD and build system label May 29, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 @.github/workflows/discord-discussions.yml:
- Around line 213-219: The current code strips query params from
DISCORD_WEBHOOK_URL into BASE, losing thread-scoping (e.g. thread_id) for the
POST; preserve query params for the POST but keep a cleaned BASE for
PATCH/DELETE. Keep the existing BASE logic (BASE="${DISCORD_WEBHOOK_URL%%\?*}"
and BASE="${BASE%/}") for constructing PATCH/DELETE URLs like
"$BASE/messages/$DISCORD_MSG_ID" / "$BASE/messages/$NEW_MSG_ID", and separately
construct a POST_URL from the original DISCORD_WEBHOOK_URL (preserving any
existing query string) by appending wait=true with the correct separator (use &
if a query exists, ? otherwise). Use POST_URL for the POST request and
BASE/messages/... for PATCH/DELETE.

In `@docs/superpowers/plans/2026-05-28-p1-agents-core-extraction.md`:
- Around line 25-67: The fenced code blocks in the plan (e.g., the package tree
block in docs/superpowers/plans/2026-05-28-p1-agents-core-extraction.md) are
missing explicit languages and surrounding blank lines causing MD040/MD031 lint
warnings; update every fenced block to use a consistent fence style (triple
backticks) with an explicit language token (use "text" for plain tree/layout
blocks) and ensure there is a blank line before and after each fence so all
occurrences (the package tree and any other ``` blocks) conform to markdownlint
rules.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c86e6fda-de92-4f9b-b96e-741d6ac93449

📥 Commits

Reviewing files that changed from the base of the PR and between adfa2ef and a47dc30.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (7)
  • .devcontainer/devcontainer-lock.json
  • .github/copilot-instructions.md
  • .github/workflows/discord-discussions.yml
  • docs/superpowers/plans/2026-05-28-p1-agents-core-extraction.md
  • packages/agents-core/package.json
  • packages/agents-core/src/catalog-sync.ts
  • packages/client-typescript/src/cli/init.ts

Comment on lines +213 to +219
# Normalize webhook URL so POST and PATCH share one base. The previous
# awk-split approach desynced if DISCORD_DISCUSSIONS_WEBHOOK_URL had a
# trailing slash or query string (e.g. ?thread_id=...): PATCH 404'd,
# the 404 branch deleted the marker as "message gone", then fell through
# to POST → fresh repost on every discussion update.
BASE="${DISCORD_WEBHOOK_URL%%\?*}"
BASE="${BASE%/}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does Discord's webhook API require preserving query parameters such as thread_idon execute/edit/delete message endpoints, and canthread_idbe combined withwait=true on webhook POST requests?

💡 Result:

Discord's webhook API allows you to combine query parameters, including thread_id and wait=true, on POST requests [1][2][3]. Regarding the requirements for preserving thread_id across different endpoints: 1. Execute Webhook (POST): When sending a message to a specific thread, you must append the thread_id as a query parameter to the webhook URL [1][4][2]. If you want the API response to return the created message object (which includes the message ID), you must also include wait=true as a query parameter [1][5]. These parameters can be combined (e.g., ?thread_id=123&wait=true) [1][2][3]. 2. Edit/Delete Message (PATCH/DELETE): The endpoints for editing (PATCH) or deleting (DELETE) a webhook message typically follow the path pattern /webhooks/{webhook.id}/{webhook.token}/messages/{message.id} [5]. Once you have obtained the message.id (usually by using wait=true on the initial POST request), the thread_id is generally not required to perform subsequent operations on that specific message, as the message ID is unique to the webhook [5]. Therefore, you do not need to pass thread_id to the edit or delete endpoints to target the message itself [5].

Citations:


Preserve webhook query parameters (e.g., thread_id) when constructing the POST URL

Line 218 strips everything after ? from DISCORD_WEBHOOK_URL, so the POST at "$BASE?wait=true" loses thread-scoping params; Discord supports combining thread_id with wait=true on webhook POSTs, and that matters for where the message is created. The subsequent PATCH/DELETE calls operate on messages/{message.id}, so they don’t need thread_id.

♻️ Minimal direction for the fix
-          BASE="${DISCORD_WEBHOOK_URL%%\?*}"
-          BASE="${BASE%/}"
+          WEBHOOK_URL="${DISCORD_WEBHOOK_URL%/}"
+          BASE="${WEBHOOK_URL%%\?*}"
+          QUERY="${WEBHOOK_URL#"$BASE"}"
+
+          if [ -n "$QUERY" ]; then
+            POST_URL="$BASE${QUERY}&amp;wait=true"
+          else
+            POST_URL="$BASE?wait=true"
+          fi

Then use "$POST_URL" for the POST, and leave the PATCH/DELETE URLs as "$BASE/messages/$DISCORD_MSG_ID" / "$BASE/messages/$NEW_MSG_ID" (no query-string appending).

🤖 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 @.github/workflows/discord-discussions.yml around lines 213 - 219, The
current code strips query params from DISCORD_WEBHOOK_URL into BASE, losing
thread-scoping (e.g. thread_id) for the POST; preserve query params for the POST
but keep a cleaned BASE for PATCH/DELETE. Keep the existing BASE logic
(BASE="${DISCORD_WEBHOOK_URL%%\?*}" and BASE="${BASE%/}") for constructing
PATCH/DELETE URLs like "$BASE/messages/$DISCORD_MSG_ID" /
"$BASE/messages/$NEW_MSG_ID", and separately construct a POST_URL from the
original DISCORD_WEBHOOK_URL (preserving any existing query string) by appending
wait=true with the correct separator (use & if a query exists, ? otherwise). Use
POST_URL for the POST request and BASE/messages/... for PATCH/DELETE.

Comment on lines +25 to +67
```
packages/agents-core/
├── package.json
├── tsconfig.json
├── jest.config.js
├── src/
│ ├── index.ts Public API surface; re-exports.
│ ├── types.ts Logger type + shared interfaces.
│ ├── installers/
│ │ ├── base-installer.ts Marker-based idempotent install/uninstall.
│ │ ├── claude-code-installer.ts
│ │ ├── cursor-installer.ts
│ │ ├── windsurf-installer.ts
│ │ ├── copilot-installer.ts
│ │ ├── claude-md-installer.ts
│ │ └── agents-md-installer.ts
│ ├── agent-manager.ts Orchestrator: installAll / installFromList / uninstallAll.
│ ├── docs-sync.ts installDocs + ensureGitignore (was inline in extension's AgentManager).
│ └── catalog-sync.ts syncServiceCatalog (was apps/vscode/src/agents/services.ts).
├── docs/ Bundled doc files (checked in; copied from <repo>/docs/agents/).
│ ├── ROCKETRIDE_README.md
│ ├── ROCKETRIDE_QUICKSTART.md
│ ├── ROCKETRIDE_PIPELINE_RULES.md
│ ├── ROCKETRIDE_COMPONENT_REFERENCE.md
│ ├── ROCKETRIDE_COMMON_MISTAKES.md
│ ├── ROCKETRIDE_python_API.md
│ ├── ROCKETRIDE_typescript_API.md
│ ├── ROCKETRIDE_OBSERVABILITY.md
│ └── stubs/ Bundled stub files (from <repo>/docs/stubs/).
│ ├── claude-code.md
│ ├── cursor.mdc
│ ├── windsurf.md
│ ├── copilot-instructions.md
│ ├── CLAUDE.md
│ └── AGENTS.md
└── test/
├── helpers.ts tmpdir + writeBundle + readWorkspace helpers.
├── base-installer.test.ts
├── installers.test.ts
├── docs-sync.test.ts
├── catalog-sync.test.ts
└── agent-manager.test.ts
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix the repeated markdownlint fence violations in this plan.

This file has many fenced blocks without a language and several fences missing surrounding blank lines, which is already triggering MD040/MD031 warnings. Please make the fence style consistent throughout the document so the new plan doesn't add lint noise.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 25-25: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 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 `@docs/superpowers/plans/2026-05-28-p1-agents-core-extraction.md` around lines
25 - 67, The fenced code blocks in the plan (e.g., the package tree block in
docs/superpowers/plans/2026-05-28-p1-agents-core-extraction.md) are missing
explicit languages and surrounding blank lines causing MD040/MD031 lint
warnings; update every fenced block to use a consistent fence style (triple
backticks) with an explicit language token (use "text" for plain tree/layout
blocks) and ensure there is a blank line before and after each fence so all
occurrences (the package tree and any other ``` blocks) conform to markdownlint
rules.

@asclearuc asclearuc requested a review from joshuadarron June 1, 2026 14:55
Copy link
Copy Markdown
Collaborator

@joshuadarron joshuadarron left a comment

Choose a reason for hiding this comment

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

Thanks @EdwardLien0426. One bit of housekeeping before review: the diff is carrying a few files that aren't part of agents-core or rocketride init:

  • .github/workflows/discord-discussions.yml
  • .devcontainer/devcontainer-lock.json
  • .github/copilot-instructions.md (the repo-root one, not the stub this PR adds under packages/agents-core/docs/stubs/)

Those are develop-owned files. You already have a Merge upstream/develop commit (08ef524), so you synced once, but develop has moved on since then. GitHub diffs the PR from the merge base, and right now the branch's merge base is behind develop's tip, so changes that landed on develop after your merge are leaking in here. Rebasing onto the latest develop (or merging develop again) moves the merge base forward and drops them out.

Heads up that this won't shrink the file count by much. agents-core is a new workspace package with bundled docs and stubs, so most of the ~50 files are legitimately yours. The rebase is just to clear those three so the diff only shows what this PR actually changes.

EdwardLien0426 and others added 2 commits June 1, 2026 10:32
Neither file belongs to the agents-core / rocketride-init work:
- .github/copilot-instructions.md (repo root) was the CopilotInstaller's
  generated output (starts with the ROCKETRIDE marker), not source. The
  PR's actual Copilot stub lives at packages/agents-core/docs/stubs/.
- .devcontainer/devcontainer-lock.json is auto-generated devcontainer
  tooling; develop tracks only devcontainer.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot removed the ci/cd CI/CD and build system label Jun 1, 2026
@EdwardLien0426
Copy link
Copy Markdown
Collaborator Author

Thanks for the review @joshuadarron! I've cleared those 3 develop-owned files (.github/workflows/discord-discussions.yml, .devcontainer/devcontainer-lock.json, and the repo-root .github/copilot-instructions.md) — the diff now only shows the packages/agents-core/docs/stubs/copilot-instructions.md stub that this PR adds. Please take another look when you get a chance. 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

builder docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): add 'rocketride init' for headless project scaffolding (parity with VS Code extension)

2 participants