Repository navigation
feat: workspace roles — admins review and manage like the owner - #1707
saravmajestic wants to merge 2 commits into
Conversation
…mbers send for review The server now sends the caller's `role` (`owner`, `admin` or `member`) next to `is_owner` on the review summary, the rules summary and rules `/sync`. `WorkspaceRole.roleOf` reads it, falling back to `is_owner` for an older server or a role this version does not know; `manages` is owner or admin. - Rule cards: an admin is offered "approve" like the owner; a member "send". The role from the last pull is kept in the rules state, and the remember tool says "you (a workspace admin)". - `skill publish`: review off refuses members only; an admin's skill is attached directly by the server; an admin whose server turns out to have no review falls back to attaching. A server without review still needs ownership. - Wording that named only the owner as reviewer now says "the owner or an admin" (plugin host sessions, the pending heading, the review-off error, `learn propose --send`), and the docs say admins review too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rywhere - `learn reply --approve` help: "(workspace owner or an admin)"; `--send-for-review` help and the bootstrap / import-reviews epilogs and prompts say the owner or an admin decides. - Rule replies, queued sends and history-staged sends say "Sent for review in <workspace>: <owner> or an admin decides" instead of naming the owner's queue. - TUI card hint: an admin's approve says "You are an admin of <workspace>", not "You own". - The training tool's description: a rule goes for review by the workspace owner or an admin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
There was a problem hiding this comment.
7 issues found across 24 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docs/docs/configure/learn.md">
<violation number="1" location="docs/docs/configure/learn.md:190">
P2: The Commands paragraph still says `--approve` and `--approve-anyway` are for the workspace owner only. Update it to say the owner or an admin, matching the rest of this section and `learn proposals reply --help`.</violation>
<violation number="2" location="docs/docs/configure/learn.md:202">
P3: Scope-choice cards put **Memory** first, so this says Enter sends or approves when it actually saves memory. Document choosing **Team rule** to submit or approve that variant.
(Based on your team's feedback about distinguishing proposal-card actions.) [484f6eca-c407-40d3-b009-05cd43569716]</violation>
</file>
<file name="packages/opencode/src/altimate/rules/proposal.ts">
<violation number="1" location="packages/opencode/src/altimate/rules/proposal.ts:8">
P3: The header still says only the owner gets the approve action, but admins now get it too through `WorkspaceRole.manages`. Update the owner line to cover admins.</violation>
<violation number="2" location="packages/opencode/src/altimate/rules/proposal.ts:262">
P3: The proposal-card contract still documents approval as owner-only, while `actionsFor` now gives admins the same `approve` action. Update that header bullet to say “owner or admin” so it matches the implementation.</violation>
</file>
<file name="packages/opencode/src/altimate/tools/training-save.ts">
<violation number="1" location="packages/opencode/src/altimate/tools/training-save.ts:24">
P3: This description tells admins to send project rules for review even though manager cards offer `approve` directly. Describe both paths: members send rules for review, while the owner or an admin can approve them.</violation>
</file>
<file name="packages/opencode/src/cli/cmd/learn.ts">
<violation number="1" location="packages/opencode/src/cli/cmd/learn.ts:791">
P3: Both `learn bootstrap` and `learn import-reviews` now print “workspace workspace owner's ...” in their epilogs. Remove the duplicated `workspace` in both strings.</violation>
</file>
<file name="packages/opencode/src/plugin/tui/altimate/rules.tsx">
<violation number="1" location="packages/opencode/src/plugin/tui/altimate/rules.tsx:117">
P3: This role check can read a stored card's stale workspace role. A card saved before promotion to admin is recomputed with the current `approve` action but still displays “You own”; refresh `card.workspace` from the current workspace when recomputing the card, then derive this label from that value.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| ## Workspace rules | ||
|
|
||
| In a project linked to an Altimate workspace (`altimate-code link`), what you teach the agent can become a **team rule**: a one-line instruction every teammate's sessions in the workspace's repositories follow once the workspace owner approves it. | ||
| In a project linked to an Altimate workspace (`altimate-code link`), what you teach the agent can become a **team rule**: a one-line instruction every teammate's sessions in the workspace's repositories follow once the workspace owner or one of its admins approves it. Admins are named on the workspace's share screen in the Altimate web app and have the owner's review rights. |
There was a problem hiding this comment.
P2: The Commands paragraph still says --approve and --approve-anyway are for the workspace owner only. Update it to say the owner or an admin, matching the rest of this section and learn proposals reply --help.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/docs/configure/learn.md, line 190:
<comment>The Commands paragraph still says `--approve` and `--approve-anyway` are for the workspace owner only. Update it to say the owner or an admin, matching the rest of this section and `learn proposals reply --help`.</comment>
<file context>
@@ -187,7 +187,7 @@ Delivery waits at most about 5 seconds for the learn lock; if another process st
## Workspace rules
-In a project linked to an Altimate workspace (`altimate-code link`), what you teach the agent can become a **team rule**: a one-line instruction every teammate's sessions in the workspace's repositories follow once the workspace owner approves it.
+In a project linked to an Altimate workspace (`altimate-code link`), what you teach the agent can become a **team rule**: a one-line instruction every teammate's sessions in the workspace's repositories follow once the workspace owner or one of its admins approves it. Admins are named on the workspace's share screen in the Altimate web app and have the owner's review rights.
**Rules need a git remote.** Team rules are kept per repository, keyed by its git remote. A project with no remote can be linked by its path, but rules stay off there: `learn status` and `learn sync` say so. Add a remote and run `altimate-code link` again, picking the same workspace: the link keeps its workspace and gains the remote, and rules sync from then on.
</file context>
| // - linked, member: send (to the review queue: the owner or an admin decides), edit, dismiss ("Not a rule") | ||
| // - linked, owner: approve instead of send (send and approve in one step; "approve anyway" when flagged): an owner | ||
| // reviewing their own proposal later adds nothing, so the card offers one team action, never both |
There was a problem hiding this comment.
P3: The header still says only the owner gets the approve action, but admins now get it too through WorkspaceRole.manages. Update the owner line to cover admins.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/altimate/rules/proposal.ts, line 8:
<comment>The header still says only the owner gets the approve action, but admins now get it too through `WorkspaceRole.manages`. Update the owner line to cover admins.</comment>
<file context>
@@ -5,7 +5,7 @@
//
// The card never blocks the turn. Actions depend on the project:
-// - linked, member: send (to the owner's review queue), edit, dismiss ("Not a rule")
+// - linked, member: send (to the review queue: the owner or an admin decides), edit, dismiss ("Not a rule")
// - linked, owner: approve instead of send (send and approve in one step; "approve anyway" when flagged): an owner
// reviewing their own proposal later adds nothing, so the card offers one team action, never both
</file context>
| // - linked, member: send (to the review queue: the owner or an admin decides), edit, dismiss ("Not a rule") | |
| // - linked, owner: approve instead of send (send and approve in one step; "approve anyway" when flagged): an owner | |
| // reviewing their own proposal later adds nothing, so the card offers one team action, never both | |
| // - linked, member: send (to the review queue: the owner or an admin decides), edit, dismiss ("Not a rule") | |
| // - linked, owner or admin: approve instead of send (send and approve in one step; "approve anyway" when flagged): a manager | |
| // reviewing their own proposal later adds nothing, so the card offers one team action, never both |
| Cards are shown by the TUI and by the VS Code extension from its release with workspace rules, for the project they have open and in its top-level sessions. Where no attached client shows cards (`altimate-code run`, ACP, the Claude Code and Codex plugins), a "remember …" is kept as a **stored proposal** instead: it waits, with the same actions as a card, until you answer it with `altimate-code learn proposals` (the plugins' `/altimate-code:rules`), and nothing is saved or sent before that. Stored proposals are kept per project: at most 20 for the account and workspace you are signed in to, the ones you asked for included, and a "remember" is still kept past that, up to 100 in all (past that, it is saved as before cards in `altimate-code run` and ACP, and said at the next session start in Claude Code and Codex). What a stored proposal offers, and whether it needs "Approve anyway", is worked out again from its wording when you answer it; one that changes or retires a team rule is closed if that rule was changed or removed since; one raised before the project was linked can only be saved for this project; one raised from corrections is dropped after 14 days unanswered, one you asked for waits until you answer it. In a subagent's session the save tools work as they did before cards: a rule is saved for this project only, a memory to memory, and nothing goes to review. Corrections in `altimate-code run` and ACP sessions are kept, and proposed the next time that session runs with a client that shows cards. A card you asked for ("remember …") that closes without an answer (after a day, or when the session server stops) is saved the same way. Requests are kept in your rules state for the project while their card is open: if the server exits unexpectedly, or a save fails for a passing reason (a busy disk, a lock), the next session server that opens the project saves them. A request is dropped, with a log line, only when it can never be saved as asked (the project's memory or training is full, or the text is too long for a memory block). While 50 requested cards are open, a new request is saved right away instead of raising a card. | ||
|
|
||
| The card never blocks the input: keep typing, and answer it when you are ready. **ctrl+x p** (or a click) moves to the card; **←/→** choose an action, **Enter** confirms, **Esc** goes back to typing. The card shows the proposed wording, what it applies to, why it was proposed and your correction. **Enter** on the first action sends it to the owner's review queue (the workspace's **Rules** tab); for the workspace owner, it approves it at once instead. **e** edits the wording, and **n** ("Not a rule") stops a correction's topic from being proposed for 30 days (on a card you asked for, it just closes it). A rule that tells the agent to skip or disable verification (tests, CI, hooks, `--no-verify`) is flagged: the owner approves it with "Approve anyway", which takes a second Enter (a client answers it with the `approve_anyway` action; a plain `approve` is refused). Nothing reaches a teammate until it is approved. A card nobody answers is dropped when the session server stops, and after a day (an answer after that closes it instead). A card is answered for the account and workspace it was shown for: after signing in as someone else or relinking, it closes without sending anything. | ||
| The card never blocks the input: keep typing, and answer it when you are ready. **ctrl+x p** (or a click) moves to the card; **←/→** choose an action, **Enter** confirms, **Esc** goes back to typing. The card shows the proposed wording, what it applies to, why it was proposed and your correction. **Enter** on the first action sends it to the review queue (the workspace's **Rules** tab); for the workspace owner or an admin, it approves it at once instead. **e** edits the wording, and **n** ("Not a rule") stops a correction's topic from being proposed for 30 days (on a card you asked for, it just closes it). A rule that tells the agent to skip or disable verification (tests, CI, hooks, `--no-verify`) is flagged: the owner or an admin approves it with "Approve anyway", which takes a second Enter (a client answers it with the `approve_anyway` action; a plain `approve` is refused). Nothing reaches a teammate until it is approved. A card nobody answers is dropped when the session server stops, and after a day (an answer after that closes it instead). A card is answered for the account and workspace it was shown for: after signing in as someone else or relinking, it closes without sending anything. |
There was a problem hiding this comment.
P3: Scope-choice cards put Memory first, so this says Enter sends or approves when it actually saves memory. Document choosing Team rule to submit or approve that variant.
(Based on your team's feedback about distinguishing proposal-card actions.) [484f6eca-c407-40d3-b009-05cd43569716]
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At docs/docs/configure/learn.md, line 202:
<comment>Scope-choice cards put **Memory** first, so this says Enter sends or approves when it actually saves memory. Document choosing **Team rule** to submit or approve that variant.
(Based on your team's feedback about distinguishing proposal-card actions.) [484f6eca-c407-40d3-b009-05cd43569716]</comment>
<file context>
@@ -199,7 +199,7 @@ In a project linked to an Altimate workspace (`altimate-code link`), what you te
Cards are shown by the TUI and by the VS Code extension from its release with workspace rules, for the project they have open and in its top-level sessions. Where no attached client shows cards (`altimate-code run`, ACP, the Claude Code and Codex plugins), a "remember …" is kept as a **stored proposal** instead: it waits, with the same actions as a card, until you answer it with `altimate-code learn proposals` (the plugins' `/altimate-code:rules`), and nothing is saved or sent before that. Stored proposals are kept per project: at most 20 for the account and workspace you are signed in to, the ones you asked for included, and a "remember" is still kept past that, up to 100 in all (past that, it is saved as before cards in `altimate-code run` and ACP, and said at the next session start in Claude Code and Codex). What a stored proposal offers, and whether it needs "Approve anyway", is worked out again from its wording when you answer it; one that changes or retires a team rule is closed if that rule was changed or removed since; one raised before the project was linked can only be saved for this project; one raised from corrections is dropped after 14 days unanswered, one you asked for waits until you answer it. In a subagent's session the save tools work as they did before cards: a rule is saved for this project only, a memory to memory, and nothing goes to review. Corrections in `altimate-code run` and ACP sessions are kept, and proposed the next time that session runs with a client that shows cards. A card you asked for ("remember …") that closes without an answer (after a day, or when the session server stops) is saved the same way. Requests are kept in your rules state for the project while their card is open: if the server exits unexpectedly, or a save fails for a passing reason (a busy disk, a lock), the next session server that opens the project saves them. A request is dropped, with a log line, only when it can never be saved as asked (the project's memory or training is full, or the text is too long for a memory block). While 50 requested cards are open, a new request is saved right away instead of raising a card.
-The card never blocks the input: keep typing, and answer it when you are ready. **ctrl+x p** (or a click) moves to the card; **←/→** choose an action, **Enter** confirms, **Esc** goes back to typing. The card shows the proposed wording, what it applies to, why it was proposed and your correction. **Enter** on the first action sends it to the owner's review queue (the workspace's **Rules** tab); for the workspace owner, it approves it at once instead. **e** edits the wording, and **n** ("Not a rule") stops a correction's topic from being proposed for 30 days (on a card you asked for, it just closes it). A rule that tells the agent to skip or disable verification (tests, CI, hooks, `--no-verify`) is flagged: the owner approves it with "Approve anyway", which takes a second Enter (a client answers it with the `approve_anyway` action; a plain `approve` is refused). Nothing reaches a teammate until it is approved. A card nobody answers is dropped when the session server stops, and after a day (an answer after that closes it instead). A card is answered for the account and workspace it was shown for: after signing in as someone else or relinking, it closes without sending anything.
+The card never blocks the input: keep typing, and answer it when you are ready. **ctrl+x p** (or a click) moves to the card; **←/→** choose an action, **Enter** confirms, **Esc** goes back to typing. The card shows the proposed wording, what it applies to, why it was proposed and your correction. **Enter** on the first action sends it to the review queue (the workspace's **Rules** tab); for the workspace owner or an admin, it approves it at once instead. **e** edits the wording, and **n** ("Not a rule") stops a correction's topic from being proposed for 30 days (on a card you asked for, it just closes it). A rule that tells the agent to skip or disable verification (tests, CI, hooks, `--no-verify`) is flagged: the owner or an admin approves it with "Approve anyway", which takes a second Enter (a client answers it with the `approve_anyway` action; a plain `approve` is refused). Nothing reaches a teammate until it is approved. A card nobody answers is dropped when the session server stops, and after a day (an answer after that closes it instead). A card is answered for the account and workspace it was shown for: after signing in as someone else or relinking, it closes without sending anything.
**Rule or memory.** A personal preference ("I prefer CTEs") or a fact ("our warehouse is Snowflake") is saved to memory without review. When the agent saved it with `training_save`, a preference goes to your own memory (all your projects) and a fact to this project's memory (outside a linked project, `training_save` saves project training as before). When it saved it with the memory tool, it stays in that tool's project memory. When the wording does not say which, the card asks: Memory, Team rule, or Skip.
</file context>
| The card never blocks the input: keep typing, and answer it when you are ready. **ctrl+x p** (or a click) moves to the card; **←/→** choose an action, **Enter** confirms, **Esc** goes back to typing. The card shows the proposed wording, what it applies to, why it was proposed and your correction. **Enter** on the first action sends it to the review queue (the workspace's **Rules** tab); for the workspace owner or an admin, it approves it at once instead. **e** edits the wording, and **n** ("Not a rule") stops a correction's topic from being proposed for 30 days (on a card you asked for, it just closes it). A rule that tells the agent to skip or disable verification (tests, CI, hooks, `--no-verify`) is flagged: the owner or an admin approves it with "Approve anyway", which takes a second Enter (a client answers it with the `approve_anyway` action; a plain `approve` is refused). Nothing reaches a teammate until it is approved. A card nobody answers is dropped when the session server stops, and after a day (an answer after that closes it instead). A card is answered for the account and workspace it was shown for: after signing in as someone else or relinking, it closes without sending anything. | |
| The card never blocks the input: keep typing, and answer it when you are ready. **ctrl+x p** (or a click) moves to the card; **←/→** choose an action, **Enter** confirms, **Esc** goes back to typing. The card shows the proposed wording, what it applies to, why it was proposed and your correction. **Enter** on the first action sends it to the review queue (the workspace's **Rules** tab); for the workspace owner or an admin, it approves it at once instead. On a linked card that asks **Memory**, **Team rule**, or **Skip**, choose **Team rule** to send or approve the rule; **Memory** saves it to memory and **Skip** dismisses it. **e** edits the wording, and **n** ("Not a rule") stops a correction's topic from being proposed for 30 days (on a card you asked for, it just closes it). A rule that tells the agent to skip or disable verification (tests, CI, hooks, `--no-verify`) is flagged: the owner or an admin approves it with "Approve anyway", which takes a second Enter (a client answers it with the `approve_anyway` action; a plain `approve` is refused). Nothing reaches a teammate until it is approved. A card nobody answers is dropped when the session server stops, and after a day (an answer after that closes it instead). A card is answered for the account and workspace it was shown for: after signing in as someone else or relinking, it closes without sending anything. |
| function actionsFor(change: Draft["change"], choose: boolean | undefined, workspace: RulesStore.State["workspace"]): ProposalCard["actions"] { | ||
| const team: ProposalCard["actions"] = workspace ? [workspace.is_owner ? "approve" : "send"] : ["save_local"] | ||
| // A manager (the owner or an admin) approves; a member sends for review. | ||
| const team: ProposalCard["actions"] = workspace ? [WorkspaceRole.manages(workspace) ? "approve" : "send"] : ["save_local"] |
There was a problem hiding this comment.
P3: The proposal-card contract still documents approval as owner-only, while actionsFor now gives admins the same approve action. Update that header bullet to say “owner or admin” so it matches the implementation.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/altimate/rules/proposal.ts, line 262:
<comment>The proposal-card contract still documents approval as owner-only, while `actionsFor` now gives admins the same `approve` action. Update that header bullet to say “owner or admin” so it matches the implementation.</comment>
<file context>
@@ -257,7 +258,8 @@ async function publish<T extends (typeof RuleEvents.Event)[keyof typeof RuleEven
function actionsFor(change: Draft["change"], choose: boolean | undefined, workspace: RulesStore.State["workspace"]): ProposalCard["actions"] {
- const team: ProposalCard["actions"] = workspace ? [workspace.is_owner ? "approve" : "send"] : ["save_local"]
+ // A manager (the owner or an admin) approves; a member sends for review.
+ const team: ProposalCard["actions"] = workspace ? [WorkspaceRole.manages(workspace) ? "approve" : "send"] : ["save_local"]
return choose
? ["save_memory", ...team, "dismiss"]
</file context>
| "- rule: A specific rule from a correction (e.g., 'never use FLOAT for financial columns')", | ||
| " A rule is an instruction for how work must be done in this repository, for everyone. In a project linked", | ||
| " to an Altimate workspace it becomes a proposed team rule the person sends for the owner's review.", | ||
| " to an Altimate workspace it becomes a proposed team rule the person sends for review by the workspace owner or an admin.", |
There was a problem hiding this comment.
P3: This description tells admins to send project rules for review even though manager cards offer approve directly. Describe both paths: members send rules for review, while the owner or an admin can approve them.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/altimate/tools/training-save.ts, line 24:
<comment>This description tells admins to send project rules for review even though manager cards offer `approve` directly. Describe both paths: members send rules for review, while the owner or an admin can approve them.</comment>
<file context>
@@ -21,7 +21,7 @@ export const TrainingSaveTool = Tool.define("training_save", {
"- rule: A specific rule from a correction (e.g., 'never use FLOAT for financial columns')",
" A rule is an instruction for how work must be done in this repository, for everyone. In a project linked",
- " to an Altimate workspace it becomes a proposed team rule the person sends for the owner's review.",
+ " to an Altimate workspace it becomes a proposed team rule the person sends for review by the workspace owner or an admin.",
" A personal preference ('I prefer...', 'for me...') or a fact ('our warehouse is...') is not a rule:",
" save it with altimate_memory_write instead.",
</file context>
| " to an Altimate workspace it becomes a proposed team rule the person sends for review by the workspace owner or an admin.", | |
| " to an Altimate workspace it becomes a proposed team rule: members send it for review, while the workspace owner or an admin can approve it.", |
| .option("max-reflections", { type: "number", default: DEFAULT_MAX_REFLECTIONS, describe: "maximum reflection batches; 0 imports signals only" }) | ||
| .option("max-seconds", { type: "number", default: DEFAULT_MAX_SECONDS, describe: "total time budget after confirmation, in seconds" }) | ||
| .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace owner's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."), | ||
| .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."), |
There was a problem hiding this comment.
P3: Both learn bootstrap and learn import-reviews now print “workspace workspace owner's ...” in their epilogs. Remove the duplicated workspace in both strings.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/cli/cmd/learn.ts, line 791:
<comment>Both `learn bootstrap` and `learn import-reviews` now print “workspace workspace owner's ...” in their epilogs. Remove the duplicated `workspace` in both strings.</comment>
<file context>
@@ -784,11 +784,11 @@ const BootstrapCommand = effectCmd({
.option("max-reflections", { type: "number", default: DEFAULT_MAX_REFLECTIONS, describe: "maximum reflection batches; 0 imports signals only" })
.option("max-seconds", { type: "number", default: DEFAULT_MAX_SECONDS, describe: "total time budget after confirmation, in seconds" })
- .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace owner's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."),
+ .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."),
handler: Effect.fn("Cli.learn.bootstrap")(function* (args) {
// altimate_change start — workspace rules: the candidate before this run, so only what it stages is sent
</file context>
| if (action === "approve") return `You own ${ws}: it reaches every teammate's sessions within a few minutes.` | ||
| if (action === "send") return `Goes to the review queue in ${ws} → Rules (${owner} or an admin decides). Nothing changes for the team until approved.` | ||
| if (action === "approve") | ||
| return `${card.workspace && WorkspaceRole.roleOf(card.workspace) === "admin" ? "You are an admin of" : "You own"} ${ws}: it reaches every teammate's sessions within a few minutes.` |
There was a problem hiding this comment.
P3: This role check can read a stored card's stale workspace role. A card saved before promotion to admin is recomputed with the current approve action but still displays “You own”; refresh card.workspace from the current workspace when recomputing the card, then derive this label from that value.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At packages/opencode/src/plugin/tui/altimate/rules.tsx, line 117:
<comment>This role check can read a stored card's stale workspace role. A card saved before promotion to admin is recomputed with the current `approve` action but still displays “You own”; refresh `card.workspace` from the current workspace when recomputing the card, then derive this label from that value.</comment>
<file context>
@@ -111,8 +112,9 @@ function buttons(card: ProposalCard): { action: ProposalCard["actions"][number];
- if (action === "approve") return `You own ${ws}: it reaches every teammate's sessions within a few minutes.`
+ if (action === "send") return `Goes to the review queue in ${ws} → Rules (${owner} or an admin decides). Nothing changes for the team until approved.`
+ if (action === "approve")
+ return `${card.workspace && WorkspaceRole.roleOf(card.workspace) === "admin" ? "You are an admin of" : "You own"} ${ws}: it reaches every teammate's sessions within a few minutes.`
if (action === "save_local") return "Not linked to a workspace: saved as project training, no review."
if (action === "save_memory")
</file context>
| .option("max-reflections", { type: "number", default: DEFAULT_MAX_REFLECTIONS, describe: "maximum reflection batches; 0 imports signals only" }) | ||
| .option("max-seconds", { type: "number", default: DEFAULT_MAX_SECONDS, describe: "total time budget after confirmation, in seconds" }) | ||
| .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace owner's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."), | ||
| .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."), |
There was a problem hiding this comment.
SUGGESTION: Duplicated word in the epilog: "the workspace workspace owner's or an admin's review". The same typo appears in the import-reviews epilog at line 860.
| .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."), | |
| .epilog("Bootstrap sends redacted excerpts of past sessions to the chosen model. Review the scope before confirming. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to finish pending reflections and continue the history cursor."), |
| // altimate_change end | ||
| .option("max-reflections", { type: "number", default: DEFAULT_MAX_REFLECTIONS, describe: "maximum reflection batches; 0 imports signals only" }) | ||
| .epilog("Requires gh installed and authenticated for the repository host. Review import sends redacted review comments to the chosen model after confirmation. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace owner's review (you are asked; --send-for-review skips the question). Rerun to resume a checkpoint or finish pending reflections."), | ||
| .epilog("Requires gh installed and authenticated for the repository host. Review import sends redacted review comments to the chosen model after confirmation. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to resume a checkpoint or finish pending reflections."), |
There was a problem hiding this comment.
SUGGESTION: Same duplicated "workspace workspace" as the bootstrap epilog above.
| .epilog("Requires gh installed and authenticated for the repository host. Review import sends redacted review comments to the chosen model after confirmation. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to resume a checkpoint or finish pending reflections."), | |
| .epilog("Requires gh installed and authenticated for the repository host. Review import sends redacted review comments to the chosen model after confirmation. Rules are candidates only: learn show, then learn promote; in a project linked to a workspace they can be sent to the workspace owner's or an admin's review (you are asked; --send-for-review skips the question). Rerun to resume a checkpoint or finish pending reflections."), |
| if (action === "approve") return `You own ${ws}: it reaches every teammate's sessions within a few minutes.` | ||
| if (action === "send") return `Goes to the review queue in ${ws} → Rules (${owner} or an admin decides). Nothing changes for the team until approved.` | ||
| if (action === "approve") | ||
| return `${card.workspace && WorkspaceRole.roleOf(card.workspace) === "admin" ? "You are an admin of" : "You own"} ${ws}: it reaches every teammate's sessions within a few minutes.` |
There was a problem hiding this comment.
SUGGESTION: The hint reads card.workspace.role, but a stored card keeps the workspace snapshot taken when it was raised, while its actions are recomputed from the current state in proposal.ts (recomputed, line 490). An admin promoted after the proposal was stored gets the approve action but still sees "You own ". Refresh workspace in recomputed() (or derive the hint from the same current workspace used for actions) so the action and the wording cannot disagree.
| server(() => reply(summary({ role: "admin" })), () => reply({ detail: { code: "reviews_not_available", message: "x" } }, 404)) | ||
| const report = await publish() | ||
| expect(report.review).toBeUndefined() | ||
| expect(attaches()).toHaveLength(1) |
There was a problem hiding this comment.
SUGGESTION: This test also passes if the admin path never attempts the submission and attaches directly up front, so it does not pin the fallback-after-404 behavior it is named for. The sibling test at line 1240 asserts posted(), so add expect(posted()).toHaveLength(1) here as well.
Code Review SummaryStatus: 4 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (23 files)
Fix these issues in Kilo Cloud Reviewed by deepseek-v4.1-flash-1017 · Input: 118.8K · Output: 25.5K · Cached: 1.7M Review guidance: REVIEW.md from base branch |
Workspace roles in the CLI. Stacked on #1685. The backend adds admins to workspaces: owner and admins decide review requests and rules, and their own submissions go in without review.
What it does
src/altimate/workspace/role.ts:roleOfreads the server'srole(owner, admin or member) and falls back tois_owneron older servers.managesmeans owner or admin.role, and the rules state stores it from each pull.skill publish:learnhelp and prompts, send and approve messages, the TUI hint, plugin host headings, and the docs. Owner names and link/bind messages stay owner-only, since the backend still requires the owner there.Testing
role.test.ts; rule-card actions per role, including an older server and an unknown role; the role kept from a pull; publish for an admin with review off, for an admin whose server has no review, and for a member on an older server.🤖 Generated with Claude Code
Summary by cubic
Adds workspace roles to the CLI: workspace admins can now review and manage like the owner, while members still send items for review.
role(owner,admin, ormember) from the review summary and rules sync, falling back tois_ownerfor older servers.skill publish(review off refuses only members).Written for commit cf65041. Summary will update on new commits.