Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
packages/core/migration/**/snapshot.json linguist-generated
packages/core/src/database/migration.gen.ts linguist-generated
# Prompt fragments are byte-identity-pinned (sha256 asserted in
# packages/opencode/test/altimate/prompt-profiles.test.ts); force LF so
# autocrlf checkouts cannot alter the assembled prompt bytes.
packages/opencode/src/altimate/prompts/** text eol=lf
39 changes: 37 additions & 2 deletions packages/opencode/src/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import PROMPT_EXPLORE from "./prompt/explore.txt"
import PROMPT_SUMMARY from "./prompt/summary.txt"
import PROMPT_TITLE from "./prompt/title.txt"
// altimate_change start - import custom agent mode prompts
import PROMPT_BUILDER from "../altimate/prompts/builder.txt"
// PromptProfiles.PROMPT_BUILDER is assembled from core + pack fragments (byte-identical
// to the former builder.txt — see profiles.ts and test/altimate/prompt-profiles.test.ts)
import { PromptProfiles } from "../altimate/prompts/profiles"
import { Flag } from "@/flag/flag"
import PROMPT_ANALYST from "../altimate/prompts/analyst.txt"
import PROMPT_REVIEWER from "../altimate/prompts/reviewer.txt"
// altimate_change end
Expand Down Expand Up @@ -224,7 +227,7 @@ export const layer = Layer.effect(
builder: {
name: "builder",
description: "Create and modify dbt models, SQL, and data pipelines. Full read/write access.",
prompt: PROMPT_BUILDER,
prompt: PromptProfiles.PROMPT_BUILDER,
options: {},
permission: Permission.merge(
defaults,
Expand Down Expand Up @@ -315,6 +318,38 @@ export const layer = Layer.effect(
mode: "primary",
native: true,
},
// Opt-in data-qa profile (workload-adaptive harness PR 1): the invariant
// core + skills catalogue + teammate training — omits the Pre-Execution
// Protocol (sql-guard) pack and the build-oriented packs (dbt-ops,
// dbt-verify, dbt-workflow, pitfalls, self-review, finish). Ships the
// same DEFAULT permission ruleset as builder; per-agent config
// overrides apply per agent, as for every agent. Registered ONLY on
// explicit opt-in: ALTIMATE_DATA_QA_PROFILE=1/true, or an
// `agent: {"data-qa": {...}}` entry in config (which then overlays the
// native profile via the standard merge below). Nothing selects it
// implicitly; the default agent stays builder.
...(Flag.truthyEnv("ALTIMATE_DATA_QA_PROFILE") || cfg.agent?.["data-qa"] != null

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register data-qa when selected as the default agent

When a user explicitly selects this profile with only default_agent: "data-qa", the gate remains false because it checks only the environment and agent.data-qa. The profile is therefore absent, and defaultInfo() throws default agent "data-qa" not found when the configured default is resolved. Treat cfg.default_agent === "data-qa" as an opt-in too, rather than requiring a redundant empty agent override.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate data-qa against the attached server

When run --attach ... --agent data-qa targets a server where this profile is enabled only in the server's environment or config, the CLI still validates the name through its local Agent.get() call in cli/cmd/run.ts. Because this gate evaluates the client process independently, the local lookup reports the agent missing and drops the requested name, causing the remote server to run its default builder profile instead. Validate attached-run agents through the remote sdk.app.agents endpoint or defer validation to the server.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: When default_agent is "data-qa" without the environment flag or an agent.data-qa entry, this gate omits the profile and resolving the configured default throws default agent "data-qa" not found. Treat cfg.default_agent === "data-qa" as an explicit opt-in too.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/agent/agent.ts, line 331:

<comment>When `default_agent` is `"data-qa"` without the environment flag or an `agent.data-qa` entry, this gate omits the profile and resolving the configured default throws `default agent "data-qa" not found`. Treat `cfg.default_agent === "data-qa"` as an explicit opt-in too.</comment>

<file context>
@@ -318,19 +318,23 @@ export const layer = Layer.effect(
+          // `agent: {"data-qa": {...}}` entry in config (which then overlays the
+          // native profile via the standard merge below). Nothing selects it
+          // implicitly; the default agent stays builder.
+          ...(Flag.truthyEnv("ALTIMATE_DATA_QA_PROFILE") || cfg.agent?.["data-qa"] != null
             ? {
                 "data-qa": {
</file context>
Suggested change
...(Flag.truthyEnv("ALTIMATE_DATA_QA_PROFILE") || cfg.agent?.["data-qa"] != null
...(Flag.truthyEnv("ALTIMATE_DATA_QA_PROFILE") || cfg.agent?.["data-qa"] != null || cfg.default_agent === "data-qa"

? {
"data-qa": {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: When data-qa runs a final turn that crosses compaction, SessionTermination.completionInstruction() does not issue the DONE instruction because it recognizes only builder. Include builder-derived profiles in that completion check.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/agent/agent.ts, line 329:

<comment>When `data-qa` runs a final turn that crosses compaction, `SessionTermination.completionInstruction()` does not issue the `DONE` instruction because it recognizes only `builder`. Include builder-derived profiles in that completion check.</comment>

<file context>
@@ -315,6 +318,34 @@ export const layer = Layer.effect(
+          // TUI agent cycle, or `agent: "data-qa"` in config.
+          ...(Flag.truthyEnv("ALTIMATE_DATA_QA_PROFILE")
+            ? {
+                "data-qa": {
+                  name: "data-qa",
+                  description:
</file context>

name: "data-qa",
Comment on lines +333 to +334

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include data-qa in the run-mode completion contract

When altimate-code run --agent data-qa is used, run mode is armed but SessionTermination.completionInstruction() still returns an instruction only for the literal agent name builder. Consequently, if a data-qa final turn also crosses the compaction threshold, it was never told to emit DONE, so explicitDoneStop() cannot terminate that completed turn and the loop compacts and dispatches an unnecessary continuation. Treat this builder-derived profile as eligible for the run-mode completion instruction as well.

Useful? React with 👍 / 👎.

description:
"Opt-in data Q&A profile: builder toolset with a slimmer prompt (no dbt build protocols).",
prompt: PromptProfiles.PROMPT_DATA_QA,
options: {},
permission: Permission.merge(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: When agent.builder.permission denies a tool, selecting data-qa still uses this default-based ruleset and restores that capability. Derive its base permission from the fully configured builder rules before applying any data-qa-specific overrides.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/src/agent/agent.ts, line 335:

<comment>When `agent.builder.permission` denies a tool, selecting `data-qa` still uses this default-based ruleset and restores that capability. Derive its base permission from the fully configured builder rules before applying any `data-qa`-specific overrides.</comment>

<file context>
@@ -315,6 +318,34 @@ export const layer = Layer.effect(
+                    "Opt-in data Q&A profile: builder toolset with a slimmer prompt (no dbt build protocols).",
+                  prompt: PROMPT_DATA_QA,
+                  options: {},
+                  permission: Permission.merge(
+                    defaults,
+                    Permission.fromConfig({
</file context>

defaults,
Permission.fromConfig({
question: "allow",
plan_enter: "allow",
Comment on lines +339 to +343

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Inherit builder-specific permission overrides in data-qa

When a user has restricted agent.builder.permission in config—for example, denying edit or warehouse writes—this separately constructed ruleset starts again from defaults, and the later config loop applies the builder override only to the builder entry. Enabling and selecting data-qa therefore restores permissions that the user explicitly removed from builder, despite this profile being advertised as having identical permissions. Base it on the fully configured builder rules before applying any agent.data-qa overrides.

Useful? React with 👍 / 👎.

sql_execute_write: "ask",
}),
userWithSafety,
),
mode: "primary",
native: true,
} satisfies Info,
}
: {}),
// reviewer agent: dbt PR review verdict engine
reviewer: {
name: "reviewer",
Expand Down
230 changes: 0 additions & 230 deletions packages/opencode/src/altimate/prompts/builder.txt

This file was deleted.

24 changes: 24 additions & 0 deletions packages/opencode/src/altimate/prompts/builder/core-training.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
## Teammate Training

You are a trainable AI teammate. Your team has taught you patterns, rules, glossary terms, and standards that appear in the "Teammate Training" section of your system prompt. This is institutional knowledge — treat it as authoritative.

### Applying Training
- **Before writing code**: Check if any learned patterns or standards apply to what you're building. Follow them.
- **Attribution**: When your output is influenced by a learned entry, briefly note it (e.g., "Following your staging-model pattern, I used CTEs for renaming columns."). This helps the user see that training is working.
- **Conflicts**: If two training entries contradict each other, flag the conflict to the user and ask which takes precedence.

### Detecting Corrections
When the user corrects your behavior — explicitly or implicitly — recognize it as a teachable moment:
- Explicit: "We never use FLOAT", "Always prefix staging models with stg_", "ARR means Annual Recurring Revenue"
- Implicit: User rewrites your SQL to follow a convention, or consistently changes the same thing across interactions

When you detect a correction:
1. Acknowledge it and apply it immediately
2. Offer: "Want me to remember this as a rule for future sessions?"
3. If yes, use `training_save` with the appropriate kind, a slug name, and concise content

### Available Training Tools
- training_save — Save a learned pattern, rule, glossary term, or standard
- training_list — List all learned training entries with budget usage
- training_remove — Remove outdated training entries

Loading
Loading