Skip to content

feat: seed the catalog with the slack feature - #2

Open
AhmedTMM wants to merge 2 commits into
mainfrom
feat/init-slack-feature
Open

feat: seed the catalog with the slack feature#2
AhmedTMM wants to merge 2 commits into
mainfrom
feat/init-slack-feature

Conversation

@AhmedTMM

@AhmedTMM AhmedTMM commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Initializes ori-feature-catalog as a remote feature root and seeds it with its first
feature, slack, lifted from OpenRouterInterns/egg.

Replaces #1, which GitHub auto-closed and will not let me reopen — I force-pushed
main to correct commit authorship, and force-pushing a PR's base ref permanently
closes it. @louisgv's six review comments are preserved on #1 and re-posted inline here.

A catalog is the list you pick from, distinct from a "feature set", which is what an
individual intern assembles in its own features/ directory. The name also avoids the
X/X slug — the path reads ori-feature-catalog/features/slack, not features/features.

What changed for users

An intern can load the Slack surface without egg. Point --features at the repo root:

ori dev --features github.com/OpenRouterLabs/ori-feature-catalog

Nothing is removed from egg — this is a copy, not a move.

Provenance

features/slack is lifted from egg at 401b2064df6ec72885a70707d151aae93aaf9c86, the
head of egg's slack-surface branch. Stating this precisely, since a review questioned it:

  • 401b206 is in egg — it is slack-surface's current head, dated 2026-08-20.
  • It is not an ancestor of egg's main. Slack was reverted from main in c2dc603
    ("Revert 'feat(slack): bring the Slack chat surface into egg' (#522)"), so features/
    on egg's main is linear notion rules self-update working-with-github — no slack.
  • A clone without that branch fetched will not find the commit, which is the likely source
    of the discrepancy. gh api repos/OpenRouterInterns/egg/commits/401b206 resolves.

That the feature has no home on egg's main is the argument for this repo, not against it.

Review guide

  • package.json, tsconfig.json, bunfig.toml, .gitignore — root scaffolding
    mirrored from egg, minus egg-only wiring (lefthook, commitlint, ori lint).
  • .github/workflows/ci.ymlbun install && bun test. No secrets needed.
  • README.md — how to consume the catalog, and rules for adding a feature.
  • features/slack/** — 171 files, verbatim from egg 401b206 except one line: the
    docs/slack-surface-rebuild.md link at AGENTS.md:5, removed because the target
    exists in neither repo (egg has no docs/ at that commit).

Self-contained: the only non-relative imports are declared dependencies, node/bun
builtins, its own package name, and ori. Nothing reaches into egg's root or a sibling.

Fixed after review

  • --features path was wrong (blocking). The README said
    .../ori-feature-catalog/features/slack, which does not load the feature.
    resolveFeaturesRoot descends one level only, so that path becomes the root and
    enumerates src and skills as features. Now points at the repo root. Thanks Devin.
  • Shadowing paragraph was wrong for the flag form. A single --features <remote>
    replaces the local features root rather than composing with it, so nothing shadows.
    Composition happens only via ori.md. README now distinguishes them.
  • No CI. Added.
  • Dead doc link at AGENTS.md:5. Removed.
  • README now documents that the repo-root form loads every feature in the catalog,
    and that ori init . is what makes bun run typecheck meaningful.

How I verified

  • bun test659 pass, 0 fail, 1150 assertions across 59 files, standalone with no
    egg present. Independently reproduced by Devin.
  • diff -r vs egg 401b206:features/slack — zero differences at the time of the lift.
  • resolveFeaturesRoot and resolveLocalFeaturesRoot read directly in
    OpenRouterIncubator/ori to confirm both README bugs before fixing them.

Corrections to my earlier numbers, both of which Devin was right about:

  • bun run typecheck emits 21 diagnostics, 14 of them TS2307, not one. The other 7
    are implicit-any cascades from the same missing SDK. Expected: ori resolves through
    optionalDependencies to a generated, git-ignored .ori/sdk. Run ori init . first.
  • The package count is bun-version dependent (426 on 1.3.14, 214 on 1.4.0), so I have
    dropped the claim rather than pick a number.

Follow-ups, deliberately not here

  • Repo is internal, not public. Visibility is an owner call.
  • No per-feature selection. The repo-root form loads the whole catalog. Fine at one
    feature; worth a design decision before the catalog grows.
  • Package is still @ori-monorepo/slack. Renaming means rewriting its
    self-referential imports; deserves its own PR with tests.
  • No lint config, so the oxlint-disable directives in the lifted source are
    unenforced here.
  • @louisgv's six items are unchanged, pre-existing in egg. Per Devin, the relative
    cross-skill imports are load-bearing — skills materialize as symlinks and resolution
    follows the real path — so the imports-map alternative should be proven before it is
    adopted. The blocks?: unknown[]KnownBlock[] tightening is worth doing, in egg
    first or as a follow-up the two repos then diverge on.

Initializes ori-feature-catalog as a remote feature root: a `features/*`
workspace that any intern can load with
`--features github.com/OpenRouterLabs/ori-feature-catalog/features/slack`.

`features/slack` is lifted verbatim from OpenRouterInterns/egg at
401b2064df6ec72885a70707d151aae93aaf9c86 (branch `slack-surface`), the same
tree ira runs. No source file was modified in the move.

The feature is self-contained: its only non-relative imports are its own
declared dependencies, node/bun builtins, and the `ori` runtime the consuming
workspace provides. Nothing is pulled from egg's root or sibling features,
which is what makes it liftable at all.

Root scaffolding mirrors egg (workspaces, tsconfig, bunfig exact-install,
gitignore) minus the bits that only make sense inside egg: no lefthook,
commitlint, or `ori lint` wiring, since the catalog carries no CI yet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@AhmedTMM AhmedTMM left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Re-posting @louisgv's inline review from #1, which GitHub will not let me reopen after I force-pushed the base ref. Same branch, identical content, so every anchor below is the same file and line.

All six land on code lifted verbatim from egg 401b206, so they are pre-existing rather than regressions from this move — worth deciding whether to fix here or fix in egg and re-lift.

import { retryPolicies, WebClient } from "@slack/web-api";
import { slackifyMarkdown } from "slackify-markdown";

import { recordLiveLine } from "../../../src/turn/live-line.ts";

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Carried over from #1 — originally by @louisgv:

weird path

// keep importing from their local guards module.

// oxlint-disable-next-line import/no-relative-parent-imports -- skills are materialized side by side in the agent workspace; the sibling skill's script is the real runtime path
export { isString, tryCatchAsync } from "../../slack-api/scripts/result.ts";

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Carried over from #1 — originally by @louisgv:

weird path/weird-re-export?..

makeClient,
markdownToSlack,
resolveThreadTs,
} from "../../slack-api/scripts/helpers.ts";

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Carried over from #1 — originally by @louisgv:

weird path -- we can use the absolute import via the imports declaration from package.json nowaday, let's leverage that

noThread?: boolean | undefined;
/** Env map for SLACK_* configuration; defaults to Bun.env. */
env?: Record<string, string | undefined> | undefined;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Carried over from #1 — originally by @louisgv:

This should use proper effect schema

originChannel: string | undefined;
originTs: string | undefined;
anchorTs?: string | undefined;
}): unknown[] => {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Carried over from #1 — originally by @louisgv:

unknown type is weird here -- we should always return proper slack block

status: HTTP_UNAUTHORIZED,
}),
};
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Carried over from #1 — originally by @louisgv:

avoid manual try/catch. Use proper Effect idiom

): Result.Result<number | undefined, Error> => {
if (raw === undefined) {
// oxlint-disable-next-line unicorn/no-useless-undefined -- Result.succeed needs an explicit arg to infer Result<number | undefined, Error>
return Result.succeed(undefined);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

instead of using undefined, let's use Option isntead

The README told an intern to run

  ori dev --features github.com/OpenRouterLabs/ori-feature-catalog/features/slack

which does not load the slack feature. `--features` takes a features *root*, and
`resolveFeaturesRoot` (framework/runloop/src/feature-boot-services.ts) descends one
level only: it returns `<input>/features` when that exists and `<input>` otherwise.
Pointing at `features/slack` therefore makes that directory the root and enumerates
its own subdirectories as features — `src` and `skills`, never `slack`. Pointing at
the repo root resolves to the nested `features/` and discovers `slack` correctly.

The shadowing paragraph was also wrong for the flag form. `resolveLocalFeaturesRoot`
uses the `--features` value *as* the local root, so a single flag replaces the
workspace's own features rather than composing with it, leaving nothing to shadow.
Composition happens only for sources declared in `ori.md`, where the local root is
appended after the declared ones. The README now says which form gives forking.

Also documents that the repo-root form loads every feature in the catalog, that
`ori init .` is what makes `bun run typecheck` meaningful, and links to
openrouter.ai/ori rather than the internal repo.

Adds a CI workflow. Tests need no secrets, so `bun install && bun test` is cheap, and
interns consume this repo's default-branch tip with nothing checking it today.

Drops the `docs/slack-surface-rebuild.md` link at features/slack/AGENTS.md:5. The
target exists in neither repo — egg has no `docs/` at 401b206 — so it was a dead
pointer telling the reader to read a nonexistent file first. This is the only
departure from a verbatim lift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

2 participants