Skip to content

feat: raptor profile cross-check in status/login + local-mode docs in meta-skill - #68

Merged
anujhydrabadi merged 1 commit into
mainfrom
feat/raptor-profile-awareness
Aug 4, 2026
Merged

feat: raptor profile cross-check in status/login + local-mode docs in meta-skill#68
anujhydrabadi merged 1 commit into
mainfrom
feat/raptor-profile-awareness

Conversation

@anujhydrabadi

Copy link
Copy Markdown
Contributor

Problem

praxis and raptor keep completely independent credential stores and profile selection (~/.praxis/credentials + pointer files vs ~/.facets/credentials + FACETS_PROFILE env). Nothing cross-checks them. For a power user with multiple profiles on each side, an AI host passes the skills' raptor preflight (raptor whoami succeeds — on the wrong control plane) and then mixes control-plane reads/writes on tenant A with praxis mcp k8s/cloud ops on tenant B, with no error anywhere.

Separately: local mode (per-directory profiles) was not explained in any installed skill — only in --help and CLAUDE.md, so AI hosts never learn it exists.

Changes

  1. internal/raptorstate (new, 95.9% cov) — read-only mirror of raptor's own profile-resolution chain (raptor/pkg/config.GetProfile): env override → praxis pin → FACETS_PROFILE[default] → sole profile. Never writes raptor's store, never touches its tokens.
  2. praxis status gains a raptor block:
    "raptor": {"installed": true, "found": true, "pinned": false,
               "profile": "default", "source": "default",
               "control_plane_url": "https://root.console.facets.cloud",
               "username": "", "matches_praxis_url": false}
    matches_praxis_url is a host comparison against the active praxis profile URL. Human output gets a one-line raptor: row.
  3. praxis login --raptor-profile <name> — durable pairing stored as raptor_profile on the praxis profile (INI-charset validated at the store boundary). Validation is advisory: warnings on a missing or host-mismatched raptor profile, never a failed login. Plain re-logins preserve the pairing; status resolves raptor via the pin ("pinned": true, "source": "pin").
  4. ExecutionPreamble + praxis meta-skill teach AI hosts the contract: check the raptor block; when pinned, prefix every raptor command with FACETS_PROFILE=<profile> (per-command — env doesn't persist across shell calls); on an unexplained matches_praxis_url: false, ask the user before any raptor write. askpraxis.ai profiles are called out as expected-mismatch.
  5. Meta-skill: "Per-directory profiles (local mode)" section — documents login --profile X --local, refresh-skills --project, the .praxis/config.json pointer, and profile_source: "project" / project_root in status.
  6. README (command surface, new "Pairing with raptor profiles" section) + CLAUDE.md structure note.

Testing

  • make test / make lint green; go test -race ./... clean.
  • New coverage: raptorstate 95.9%; cmd 68.1% → 68.6% (new funcs 90–100%).
  • Live-verified on a machine with 7 praxis / 6 raptor profiles: caught a real mismatch (repo tree pinned to facetsdemo, raptor default → root); --raptor-profile root reuse-path login stored the pairing, status reported "source": "pin", "matches_praxis_url": true, and the reinstalled skills carry the new preamble + sections.

🤖 Generated with Claude Code

praxis and raptor keep independent credential stores (~/.praxis vs
~/.facets, pointer files vs FACETS_PROFILE), and nothing linked them: a
multi-profile user could pass the skills' raptor preflight on the WRONG
control plane and mix raptor writes on tenant A with praxis mcp ops on
tenant B without any error.

- internal/raptorstate: read-only mirror of raptor's profile resolution
  (env override → pin → FACETS_PROFILE → default → sole); never writes
  raptor's store or uses its tokens.
- `praxis status` gains a `raptor` block: resolved profile, source,
  control_plane_url, and matches_praxis_url (host comparison against
  the active praxis profile URL).
- `praxis login --raptor-profile <name>` stores a durable pairing
  (raptor_profile INI key) on the praxis profile; validation is
  advisory (warns on missing/mismatched raptor profile, never fails
  login); re-logins without the flag preserve the pairing. Status
  resolves raptor via the pin (`pinned: true`).
- ExecutionPreamble + praxis meta-skill teach AI hosts to check the
  raptor block, prefix raptor commands with FACETS_PROFILE=<pin>, and
  ask before writes on an unexplained mismatch.
- Meta-skill also documents local mode (per-directory profiles) —
  previously only in --help and CLAUDE.md, invisible to AI hosts.

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

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 26 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4d9b5d33-7724-4e52-a823-e2a5bce88bb4

📥 Commits

Reviewing files that changed from the base of the PR and between 50972a7 and 32bfee0.

📒 Files selected for processing (15)
  • CLAUDE.md
  • README.md
  • cmd/login.go
  • cmd/login_raptor_test.go
  • cmd/login_reuse_test.go
  • cmd/status.go
  • cmd/status_test.go
  • internal/credentials/credentials.go
  • internal/credentials/credentials_test.go
  • internal/raptorstate/raptorstate.go
  • internal/raptorstate/raptorstate_test.go
  • internal/render/preamble.go
  • internal/render/preamble_test.go
  • internal/skillinstall/dummy.go
  • internal/skillinstall/dummy_test.go

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

@anujhydrabadi
anujhydrabadi merged commit 5cd09ae into main Aug 4, 2026
3 checks passed
@anujhydrabadi
anujhydrabadi deleted the feat/raptor-profile-awareness branch August 4, 2026 09:24
anshulsao added a commit that referenced this pull request Aug 5, 2026
Extends #68 rather than sitting beside it. That PR taught hosts to act on
the `raptor` block in `praxis status --json`, but its cases all assume
raptor is already present: `pinned`, `matches_praxis_url`, `found: false`.
The absent case had no bullet, and `found: false` told the host to "ask
the user to run raptor login" — which dead-ended, since nothing in this
repo said how to install raptor in the first place.

  - `raptor.install_hint` (inside #68's block, not a new top-level key, so
    the "act on the raptor block" contract keeps holding). Carries the
    asset URL and shell commands already resolved for this machine's
    OS/arch — praxis is the only party that knows those, skill text can't.
    Installs to ~/.local/bin: `sudo` prompts for a password and would hang
    a non-interactive host. Omitted once raptor is installed. Platforms
    raptor publishes no build for get `docs` and no fabricated URL.
  - Meta-skill: new `installed: false` bullet in #68's own list, in its
    style; `found: false` amended from "ask the user" to RUN `raptor
    login` for them — the same treatment `praxis login` already gets in
    this file (browser opens, user completes it, host waits for exit 0).
  - Preflight section updated to match; it still said "don't install it
    yourself", which now contradicts the bullets below it.

Credential guardrails are unchanged and pinned by test: never ask for a
token in chat, never write ~/.facets/credentials. Running a browser login
is not the same as handling the secret.

Asset names verified against the real v0.1.91 release; the generated
darwin-arm64 URL was fetched and returns 200.

Part 1 of #72.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpVxm5k6cuVWnz5pKsFUdT
anujhydrabadi pushed a commit that referenced this pull request Aug 5, 2026
…able setup steps (#73)

* feat(status): make an unusable raptor obvious and actionable

#68 added a `raptor:` line to `praxis status`, which fixed the silent
case. But when raptor is absent that line reads only "not installed" —
it names no consequence and no next step, and `logged in: yes` prints
directly beneath it, so the output as a whole still scans as healthy.
Nothing in this repo told a user where to get raptor either.

That matters because raptor is not optional. Facets projects, resources,
environments and releases all go through it, and 450 of the shell
commands inside the skills praxis installs are `raptor ...`. A user who
stops after `praxis login` has a working praxis and cannot do the work.

Three changes:

  - `raptor: not installed` now points at the releases page. raptor ships
    no Homebrew formula or cask today (only Casks/praxis.rb exists in
    Facets-cloud/homebrew-tap), so the releases page is the install path
    we can honestly name.
  - A closing `⚠ setup incomplete` notice prints last, after the skills
    and agents listings, so an unfinished setup isn't buried above them.
    It distinguishes not-installed (install + login) from installed-but-
    not-logged-in (login only) — telling someone who already has raptor
    to go install it sends them down the wrong path, so that case is
    pinned by its own test.
  - `setup_complete` in the JSON, so an AI host can branch on one field
    instead of re-deriving usability from installed/found/logged_in. The
    skills' raptor preflight currently dead-ends at "ask the user to
    install it"; it can now point at `praxis status` and follow it.

Behavior change: the not-installed string is no longer exactly
"not installed", so TestRaptorStatusLine's case was updated.

Part 1 of #72. Whether `praxis login` should offer to install raptor,
and whether raptor should get a Homebrew cask, is still open there.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpVxm5k6cuVWnz5pKsFUdT

* feat(status): give AI hosts runnable steps to install and sign in raptor

Extends #68 rather than sitting beside it. That PR taught hosts to act on
the `raptor` block in `praxis status --json`, but its cases all assume
raptor is already present: `pinned`, `matches_praxis_url`, `found: false`.
The absent case had no bullet, and `found: false` told the host to "ask
the user to run raptor login" — which dead-ended, since nothing in this
repo said how to install raptor in the first place.

  - `raptor.install_hint` (inside #68's block, not a new top-level key, so
    the "act on the raptor block" contract keeps holding). Carries the
    asset URL and shell commands already resolved for this machine's
    OS/arch — praxis is the only party that knows those, skill text can't.
    Installs to ~/.local/bin: `sudo` prompts for a password and would hang
    a non-interactive host. Omitted once raptor is installed. Platforms
    raptor publishes no build for get `docs` and no fabricated URL.
  - Meta-skill: new `installed: false` bullet in #68's own list, in its
    style; `found: false` amended from "ask the user" to RUN `raptor
    login` for them — the same treatment `praxis login` already gets in
    this file (browser opens, user completes it, host waits for exit 0).
  - Preflight section updated to match; it still said "don't install it
    yourself", which now contradicts the bullets below it.

Credential guardrails are unchanged and pinned by test: never ask for a
token in chat, never write ~/.facets/credentials. Running a browser login
is not the same as handling the secret.

Asset names verified against the real v0.1.91 release; the generated
darwin-arm64 URL was fetched and returns 200.

Part 1 of #72.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpVxm5k6cuVWnz5pKsFUdT

* refactor(status): point at raptor's README, keep no-sudo as an escape hatch

The previous commit restated raptor's install steps inside praxis, with
~/.local/bin swapped in for the documented `sudo mv … /usr/local/bin`.
Two problems with that:

  - It forks instructions raptor owns. That README already drifts from
    reality (it documents Windows binaries the releases don't publish),
    and a second copy in praxis would drift further.
  - The ~/.local/bin substitution was mine, not sourced from any doc, and
    the output presented it as if it were the official path.

So `docs` now points at the README (#installation) and is the primary
answer, and the no-sudo path is demoted to an explicitly-labelled hatch:

  install_hint.docs             raptor's own instructions — prefer these
  install_hint.asset_url        exact build for this OS/arch
  install_hint.no_sudo_commands hatch for hosts that can't answer a sudo
                                password prompt (it would hang, not fail)
  install_hint.note             says the hatch deviates, and that
                                ~/.local/bin must be on PATH

The meta-skill bullet mirrors that order: docs first, hatch only when the
user can't use them or asks the host to do it.

Unpublished platforms get docs and nothing else — no fabricated asset URL,
and no hatch we can't stand behind.

Both URLs verified reachable (200). Asset names verified against v0.1.91.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpVxm5k6cuVWnz5pKsFUdT

---------

Co-authored-by: Claude Opus 5 (1M context) <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.

1 participant