From 16ba54aa401743af40a45a6b20590747c01b223b Mon Sep 17 00:00:00 2001 From: bft-codebot Date: Fri, 6 Feb 2026 17:02:15 +0000 Subject: [PATCH] sync(bfmono): feat(gambit): move bot policy to folder and enforce policy summarizer flow (+19 more) (bfmono@5faa48b35) This PR is an automated gambitmono sync of bfmono Gambit packages. - Source: `packages/gambit/` - Core: `packages/gambit-core/` - bfmono rev: 5faa48b35 Changes: - 5faa48b35 feat(gambit): move bot policy to folder and enforce policy summarizer flow - 9a36c4a7e fix(gambit): align env loading with init and block .gambit env writes - dbe7c54ca feat(gambit-bot): add file actions and scenario deck structure - 855784d6b docs(gambit): add public permissions guide and API jsdoc - 8f0ca0a85 feat(gambit): trace effective permission layers at runtime - 90b4b5071 feat(gambit-core): add phase-1 permission contract primitives - df9280f6a fix(gambit): restore build-bot deck path compatibility - daca46555 feat(simulator-ui): wire build, test, and grade to workspace sessions - e404a17d7 feat(gambit): add workspace-backed serve and bot sandbox flow - 5f4fa86b9 feat(gambit): scaffold workspace defaults in init - cf9b23778 feat(gambit-core): add schema guards and model param passthrough - d0e5a9617 [gambit] move chat message into transcript so it scrolls - 5c6125d99 feat(simulator-ui): open workbench drawer by default - 7c9cd05f8 feat(simulator): gate chat accordion by env flag - a2599068e feat(simulator-ui): add build chat history loading - 9911dae22 feat(simulator-ui): add workbench chat drawer accordion - 8cab8ec1f feat(simulator-ui): dock calibrate drawer and sync updates - d41ba101d Add AAR for phase 3.1.5 deck format build tab - b1b5e2a7e Prefer PROMPT.md after build scaffolds - 50fac8f7b Update Build tab for deck format 1.0 Do not edit this repo directly; make changes in bfmono and re-run the sync. --- .../actions/internal_knowledge_read.deck.ts | 137 ------------------ .../actions/internal_knowledge_read/PROMPT.md | 6 - src/decks/actions/policy_read.deck.ts | 85 +++++++++++ src/decks/actions/policy_read/PROMPT.md | 6 + src/decks/actions/policy_search/PROMPT.md | 43 ++++++ .../schemas/policy_search_input.zod.ts | 13 ++ .../schemas/policy_search_output.zod.ts | 14 ++ src/decks/gambit-bot/INTENT.md | 3 +- src/decks/gambit-bot/PROMPT.md | 11 +- .../graders/deck_format_policy_llm/PROMPT.md | 8 +- src/decks/gambit-bot/policy/README.md | 26 ++++ .../gambit-bot/policy/core-invariants.md | 8 + .../{notes => policy}/deck-format-1.0.md | 15 +- .../frontmatter-guardrails.md} | 29 +--- src/decks/gambit-bot/policy/interaction.md | 9 ++ .../gambit-bot/policy/safety-reliability.md | 6 + src/decks/gambit-init.deck.md | 2 +- src/decks/guides/gambit-bot-review.md | 5 +- 18 files changed, 239 insertions(+), 187 deletions(-) delete mode 100644 src/decks/actions/internal_knowledge_read.deck.ts delete mode 100644 src/decks/actions/internal_knowledge_read/PROMPT.md create mode 100644 src/decks/actions/policy_read.deck.ts create mode 100644 src/decks/actions/policy_read/PROMPT.md create mode 100644 src/decks/actions/policy_search/PROMPT.md create mode 100644 src/decks/actions/schemas/policy_search_input.zod.ts create mode 100644 src/decks/actions/schemas/policy_search_output.zod.ts create mode 100644 src/decks/gambit-bot/policy/README.md create mode 100644 src/decks/gambit-bot/policy/core-invariants.md rename src/decks/gambit-bot/{notes => policy}/deck-format-1.0.md (97%) rename src/decks/gambit-bot/{POLICY.md => policy/frontmatter-guardrails.md} (53%) create mode 100644 src/decks/gambit-bot/policy/interaction.md create mode 100644 src/decks/gambit-bot/policy/safety-reliability.md diff --git a/src/decks/actions/internal_knowledge_read.deck.ts b/src/decks/actions/internal_knowledge_read.deck.ts deleted file mode 100644 index 4d210179..00000000 --- a/src/decks/actions/internal_knowledge_read.deck.ts +++ /dev/null @@ -1,137 +0,0 @@ -import * as path from "@std/path"; -import { defineDeck } from "jsr:@bolt-foundry/gambit"; -import { z } from "npm:zod"; - -const INTERNAL_KNOWLEDGE_ROOT = path.resolve( - path.dirname(path.fromFileUrl(import.meta.url)), - "../gambit-bot", -); - -export default defineDeck({ - label: "internal_knowledge_read", - contextSchema: z.object({ - path: z.string().describe( - "Relative file path under Gambit Bot internal knowledge root.", - ), - }), - responseSchema: z.object({ - status: z.number().optional(), - message: z.string().optional(), - payload: z.object({ - path: z.string(), - contents: z.string(), - }).optional(), - }), - async run(ctx) { - let resolved; - try { - resolved = await resolveInternalKnowledgePath(ctx.input.path); - } catch (err) { - return { - status: 400, - message: err instanceof Error ? err.message : String(err), - }; - } - - try { - const stat = await Deno.stat(resolved.fullPath); - if (!stat.isFile) { - return { status: 409, message: "path is not a file" }; - } - const contents = await Deno.readTextFile(resolved.fullPath); - return { - status: 200, - payload: { path: resolved.relativePath, contents }, - }; - } catch (err) { - if (err instanceof Deno.errors.NotFound) { - return { status: 404, message: "path not found" }; - } - return { - status: 500, - message: err instanceof Error ? err.message : String(err), - }; - } - }, -}); - -async function resolveInternalKnowledgePath(inputPath: string): Promise<{ - fullPath: string; - relativePath: string; -}> { - if (!inputPath || typeof inputPath !== "string") { - throw new Error("path is required"); - } - - const root = await Deno.realPath(INTERNAL_KNOWLEDGE_ROOT); - const normalizedInput = path.normalize(inputPath); - const segments = normalizedInput.split(/\\|\//g); - if (segments.includes("..")) { - throw new Error("path traversal is not allowed"); - } - - const candidate = path.isAbsolute(normalizedInput) - ? normalizedInput - : path.resolve(root, normalizedInput); - const relativePath = path.relative(root, candidate); - if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) { - throw new Error("path escapes internal knowledge root"); - } - - let candidateStat: Deno.FileInfo | null = null; - try { - const stat = await Deno.lstat(candidate); - candidateStat = stat; - if (stat.isSymlink) { - throw new Error("symlinks are not allowed"); - } - - const realCandidate = await Deno.realPath(candidate); - const realRelative = path.relative(root, realCandidate); - if (realRelative.startsWith("..") || path.isAbsolute(realRelative)) { - throw new Error("path escapes internal knowledge root"); - } - } catch (err) { - if (!(err instanceof Deno.errors.NotFound)) { - throw err; - } - } - - const parentAnchor = candidateStat?.isDirectory - ? candidate - : path.dirname(candidate); - const parent = await resolveExistingParent(parentAnchor); - const parentReal = await Deno.realPath(parent); - const parentRelative = path.relative(root, parentReal); - if (parentRelative.startsWith("..") || path.isAbsolute(parentRelative)) { - throw new Error("path escapes internal knowledge root"); - } - - return { - fullPath: candidate, - relativePath: relativePath.replaceAll("\\", "/"), - }; -} - -async function resolveExistingParent(dir: string): Promise { - let current = dir; - while (true) { - try { - const stat = await Deno.stat(current); - if (!stat.isDirectory) { - throw new Error("parent path is not a directory"); - } - return current; - } catch (err) { - if (!(err instanceof Deno.errors.NotFound)) { - throw err; - } - } - - const next = path.dirname(current); - if (next === current) { - return current; - } - current = next; - } -} diff --git a/src/decks/actions/internal_knowledge_read/PROMPT.md b/src/decks/actions/internal_knowledge_read/PROMPT.md deleted file mode 100644 index b8b032f4..00000000 --- a/src/decks/actions/internal_knowledge_read/PROMPT.md +++ /dev/null @@ -1,6 +0,0 @@ -+++ -label = "internal_knowledge_read" -execute = "../internal_knowledge_read.deck.ts" -+++ - -Compute-only deck for reading files in Gambit Bot's internal knowledge root. diff --git a/src/decks/actions/policy_read.deck.ts b/src/decks/actions/policy_read.deck.ts new file mode 100644 index 00000000..f61d4d7a --- /dev/null +++ b/src/decks/actions/policy_read.deck.ts @@ -0,0 +1,85 @@ +import * as path from "@std/path"; +import { defineDeck } from "jsr:@bolt-foundry/gambit"; +import { z } from "npm:zod"; + +const POLICY_ROOT = path.resolve( + path.dirname(path.fromFileUrl(import.meta.url)), + "../gambit-bot/policy", +); + +export default defineDeck({ + label: "policy_read", + contextSchema: z.object({ + path: z.string().optional().describe( + "Policy file path under policy/. Defaults to policy/README.md.", + ), + }), + responseSchema: z.object({ + status: z.number().optional(), + message: z.string().optional(), + payload: z.object({ + path: z.string(), + contents: z.string(), + }).optional(), + }), + async run(ctx) { + const requestedPath = (ctx.input.path ?? "policy/README.md").trim(); + + let resolved; + try { + resolved = await resolvePolicyPath(requestedPath); + } catch (err) { + return { + status: 400, + message: err instanceof Error ? err.message : String(err), + }; + } + + try { + const stat = await Deno.stat(resolved.fullPath); + if (!stat.isFile) return { status: 409, message: "path is not a file" }; + const contents = await Deno.readTextFile(resolved.fullPath); + return { + status: 200, + payload: { path: resolved.relativePath, contents }, + }; + } catch (err) { + if (err instanceof Deno.errors.NotFound) { + return { status: 404, message: "path not found" }; + } + return { + status: 500, + message: err instanceof Error ? err.message : String(err), + }; + } + }, +}); + +async function resolvePolicyPath(inputPath: string): Promise<{ + fullPath: string; + relativePath: string; +}> { + if (!inputPath) throw new Error("path is required"); + const root = await Deno.realPath(POLICY_ROOT); + + const normalized = inputPath.startsWith("policy/") + ? inputPath.slice("policy/".length) + : inputPath; + const normalizedInput = path.normalize(normalized); + const segments = normalizedInput.split(/\\|\//g); + if (segments.includes("..")) throw new Error("path traversal is not allowed"); + + const candidate = path.resolve(root, normalizedInput); + const relativePath = path.relative(root, candidate); + if (relativePath.startsWith("..") || path.isAbsolute(relativePath)) { + throw new Error("path escapes policy root"); + } + if (!relativePath.endsWith(".md")) { + throw new Error("policy_read only supports .md files under policy/"); + } + + return { + fullPath: candidate, + relativePath: `policy/${relativePath.replaceAll("\\", "/")}`, + }; +} diff --git a/src/decks/actions/policy_read/PROMPT.md b/src/decks/actions/policy_read/PROMPT.md new file mode 100644 index 00000000..f5867c10 --- /dev/null +++ b/src/decks/actions/policy_read/PROMPT.md @@ -0,0 +1,6 @@ ++++ +label = "policy_read" +execute = "../policy_read.deck.ts" ++++ + +Compute-only deck for loading policy docs under `policy/`. diff --git a/src/decks/actions/policy_search/PROMPT.md b/src/decks/actions/policy_search/PROMPT.md new file mode 100644 index 00000000..b0bef7e0 --- /dev/null +++ b/src/decks/actions/policy_search/PROMPT.md @@ -0,0 +1,43 @@ ++++ +label = "policy_search" +modelParams = { model = "openrouter/openai/gpt-5.1-chat", temperature = 0 } +contextSchema = "../schemas/policy_search_input.zod.ts" +responseSchema = "../schemas/policy_search_output.zod.ts" + +[[actions]] +name = "policy_read" +path = "../policy_read/PROMPT.md" +description = "Load a policy doc under policy/." ++++ + +You are a policy summarizer for Gambit Bot. + +Your job: read and summarize the most relevant policies for an upcoming change. + +Discovery flow: + +1. Call `policy_read` with `path="policy/README.md"` first. +2. Discover candidate policy file paths from the README markdown links. +3. Select the most relevant policy paths for the requested change. +4. Call `policy_read` for each selected policy path. +5. Summarize those loaded policy contents and return the result. + +Selection rules: + +- Do not invent paths. +- Prioritize the smallest set that still gives safe coverage. +- Prefer 2-3 docs by default unless a broader set is clearly needed. +- Always include `policy/deck-format-1.0.md` when frontmatter, schema, or deck + structure may change. +- If uncertain, include `policy/README.md` first. + +Response requirements: + +- Return `summaries` as an array of scoped guidance items. +- Each item must include: + - `appliesTo`: the part of the proposal this guidance maps to + - `summary`: concise policy guidance for that part +- Focus each item on how policy applies to the user's proposed change. +- Do not return path lists or per-policy metadata in the response. + +![respond](gambit://snippets/respond.md) diff --git a/src/decks/actions/schemas/policy_search_input.zod.ts b/src/decks/actions/schemas/policy_search_input.zod.ts new file mode 100644 index 00000000..932e931a --- /dev/null +++ b/src/decks/actions/schemas/policy_search_input.zod.ts @@ -0,0 +1,13 @@ +import { z } from "npm:zod"; + +export default z.object({ + changeSummary: z.string().describe( + "Short summary of the change you are about to make.", + ), + userRequest: z.string().describe( + "Original user ask, if available.", + ).optional(), + limit: z.number().int().min(1).max(5).default(3).describe( + "Maximum number of policy docs to recommend.", + ), +}); diff --git a/src/decks/actions/schemas/policy_search_output.zod.ts b/src/decks/actions/schemas/policy_search_output.zod.ts new file mode 100644 index 00000000..f7610a4d --- /dev/null +++ b/src/decks/actions/schemas/policy_search_output.zod.ts @@ -0,0 +1,14 @@ +import { z } from "npm:zod"; + +export default z.object({ + summaries: z.array(z.object({ + appliesTo: z.string().describe( + "What part of the proposed change this summary applies to.", + ), + summary: z.string().describe( + "Policy guidance for that part of the change.", + ), + })).min(1).describe( + "Scoped policy summaries so the parent knows where each policy applies.", + ), +}); diff --git a/src/decks/gambit-bot/INTENT.md b/src/decks/gambit-bot/INTENT.md index 9560665d..2f8a61b1 100644 --- a/src/decks/gambit-bot/INTENT.md +++ b/src/decks/gambit-bot/INTENT.md @@ -17,7 +17,8 @@ ## Constraints -- `PROMPT.md` is the canonical entrypoint; INTENT/POLICY are guidance only. +- `PROMPT.md` is the canonical entrypoint; `INTENT.md` and `policy/*.md` are + guidance only. - Use existing Gambit runtime and test-bot primitives; do not fork pipelines. - Avoid introducing remote dependencies without explicit opt-in. diff --git a/src/decks/gambit-bot/PROMPT.md b/src/decks/gambit-bot/PROMPT.md index 4c714b3b..21d458bb 100644 --- a/src/decks/gambit-bot/PROMPT.md +++ b/src/decks/gambit-bot/PROMPT.md @@ -36,9 +36,9 @@ path = "../actions/bot_list/PROMPT.md" description = "List files and directories under the bot root." [[actions]] -name = "internal_knowledge_read" -path = "../actions/internal_knowledge_read/PROMPT.md" -description = "Read files from Gambit Bot's internal knowledge folder. Do this before writing most files, so you know what to do." +name = "policy_search" +path = "../actions/policy_search/PROMPT.md" +description = "Policy gateway: finds relevant policies and returns a summary for the planned change." [[actions]] name = "bot_deck_review" @@ -147,5 +147,6 @@ On the first substantive user turn in a session, do this startup flow once: files. 4. If listing fails, say so briefly and continue with cautious assumptions. -When you're unsure about deck format or frontmatter requirements, read -`notes/deck-format-1.0.md` via `internal_knowledge_read` before proposing edits. +When policy details are relevant to a change, or you're unsure about deck +format/frontmatter requirements, call `policy_search` with a short summary of +the planned change and use the returned `summaries` before writing. diff --git a/src/decks/gambit-bot/graders/deck_format_policy_llm/PROMPT.md b/src/decks/gambit-bot/graders/deck_format_policy_llm/PROMPT.md index bb7fd661..d75528f5 100644 --- a/src/decks/gambit-bot/graders/deck_format_policy_llm/PROMPT.md +++ b/src/decks/gambit-bot/graders/deck_format_policy_llm/PROMPT.md @@ -14,14 +14,14 @@ You evaluate whether GambitBot followed deck-editing policy for the graded turn. Pass criteria (all must be true): 1. The assistant proposes or writes Deck Format v1.0 assets (for example - `PROMPT.md`, `INTENT.md`, optional `POLICY.md`) instead of inventing ad-hoc - `.deck.md` custom DSL unless explicitly requested by the user. + `PROMPT.md`, `INTENT.md`, and optional `policy/*.md`) instead of inventing + ad-hoc `.deck.md` custom DSL unless explicitly requested by the user. 2. If the turn is an edit/update flow, the assistant checks existing workspace files before making broad structural rewrites (for example via `bot_list`, `bot_read`, or `bot_exists` evidence in the session). 3. When frontmatter/schema details are uncertain, the assistant consults - internal guidance (for example `internal_knowledge_read` of - `notes/deck-format-1.0.md`) before asserting schema shape. + internal guidance (for example `policy_search` with a change summary) before + asserting schema shape. 4. The assistant tone stays concise and practical (no inflated persona flourish that distracts from the task). diff --git a/src/decks/gambit-bot/policy/README.md b/src/decks/gambit-bot/policy/README.md new file mode 100644 index 00000000..c51b1d6e --- /dev/null +++ b/src/decks/gambit-bot/policy/README.md @@ -0,0 +1,26 @@ +# Gambit Bot Policy Guide + +Use this folder as the policy source of truth for Gambit Bot. + +## Quick explainer + +- [`core-invariants.md`](./core-invariants.md): Non-negotiable guardrails + (local-first, Deck Format v1.0, bot-root boundaries, canonical `PROMPT.md` + entrypoint). +- [`interaction.md`](./interaction.md): Conversation and workflow behavior + expectations (minimal questions, scenario wording, starter scenario + grader + creation). +- [`safety-reliability.md`](./safety-reliability.md): Safety checks and fallback + behavior when workflows may break or model/runtime setup is invalid. +- [`frontmatter-guardrails.md`](./frontmatter-guardrails.md): Rules and + checklist for safe frontmatter and schema editing. +- [`deck-format-1.0.md`](./deck-format-1.0.md): Full Deck Format v1.0 + specification and folder contract. + +## Usage + +- Root decks should call `policy_search` with a short change summary. +- `policy_search` reads relevant policy docs internally and returns a usable + `summaries` array with scoped guidance. +- Root decks should use those summaries and should not read policy files + directly. diff --git a/src/decks/gambit-bot/policy/core-invariants.md b/src/decks/gambit-bot/policy/core-invariants.md new file mode 100644 index 00000000..c4ce95ed --- /dev/null +++ b/src/decks/gambit-bot/policy/core-invariants.md @@ -0,0 +1,8 @@ +# Core Invariants + +- Stay local-first: do not introduce remote dependencies without explicit opt-in + and a clear explanation of implications. +- Keep `PROMPT.md` as the canonical deck entrypoint. +- Use [Deck Format v1.0](./deck-format-1.0.md) (TOML frontmatter) with + `[modelParams]` populated. +- Do not write outside the bot root; use the bot file tools. diff --git a/src/decks/gambit-bot/notes/deck-format-1.0.md b/src/decks/gambit-bot/policy/deck-format-1.0.md similarity index 97% rename from src/decks/gambit-bot/notes/deck-format-1.0.md rename to src/decks/gambit-bot/policy/deck-format-1.0.md index 75db6f18..b7a382bc 100644 --- a/src/decks/gambit-bot/notes/deck-format-1.0.md +++ b/src/decks/gambit-bot/policy/deck-format-1.0.md @@ -158,24 +158,23 @@ Every deck folder MUST include: Deck folders SHOULD include: - `INTENT.md` -- `POLICY.md` +- `policy/` Notes (recommended behavior): -- Gambit tooling looks for `INTENT.md` and `POLICY.md` and MAY scaffold them if - missing. +- Gambit tooling looks for `INTENT.md` and MAY scaffold it if missing. - `INTENT.md` SHOULD follow the canonical intent headings from `policy/templates/INTENT.md`. - `INTENT.md` explains **what** the deck should accomplish and why: goals, non-goals, constraints, tradeoffs, and escalation conditions. It is the source of truth for human alignment and for Gambit Bot decisions about what to build. -- `POLICY.md` explains **what must not happen** or what must always hold: +- `policy/*.md` explains **what must not happen** or what must always hold: guardrails, invariants, and lightweight acceptance tests. It is non- programmatic and keeps the bot and humans aligned on safe behavior. -- Neither `INTENT.md` nor `POLICY.md` are executable; do not treat them as a +- Neither `INTENT.md` nor policy docs are executable; do not treat them as a second prompt surface or as model instructions. -- Keep both files short and scannable (headings plus bullets). If it gets long, - move deeper background into `README.md` or `policies/`. +- Keep these files short and scannable (headings plus bullets). If they get + long, move deeper background into `README.md` or split across `policy/*.md`. ### Optional files/folders @@ -184,7 +183,7 @@ Deck folders MAY include: - `README.md` (recommended) - `samples/` (recommended) - `snippets/` (recommended) -- `policies/` (optional additional policy docs; `POLICY.md` remains canonical) +- `policy/` (optional policy docs) - `reviews/` (optional AARs / retros) - `actions/`, `scenarios/`, `graders/` (recommended organization only) diff --git a/src/decks/gambit-bot/POLICY.md b/src/decks/gambit-bot/policy/frontmatter-guardrails.md similarity index 53% rename from src/decks/gambit-bot/POLICY.md rename to src/decks/gambit-bot/policy/frontmatter-guardrails.md index 6b3ed7f2..b2f9de7f 100644 --- a/src/decks/gambit-bot/POLICY.md +++ b/src/decks/gambit-bot/policy/frontmatter-guardrails.md @@ -1,32 +1,13 @@ -# Gambit Bot Deck Policy +# Frontmatter Guardrails -## Non-negotiables +See the full spec: [Deck Format v1.0](./deck-format-1.0.md). -- Stay local-first: do not introduce remote dependencies without explicit opt-in - and a clear explanation of implications. -- Keep `PROMPT.md` as the canonical deck entrypoint. -- Use Deck Format v1.0 (TOML frontmatter) with `[modelParams]` populated. -- Do not write outside the bot root; use the bot file tools. - -## Behavior expectations - -- Ask the minimum number of questions needed to produce a runnable deck. -- Prefer “scenario” language over “test” in user-facing text. -- Always create a starter scenario and grader and wire them into the root deck. - -## Safety & reliability - -- If a change would break Build/Test/Grade workflows, stop and ask for - confirmation. -- If a deck cannot run with the current model setup, highlight the issue and - offer a fallback. - -## Frontmatter editing guardrails +## Editing Rules - Treat frontmatter as strict Deck Format v1.0; do not invent ad-hoc keys or alternate shapes. - If you're unsure about frontmatter shape or schema wiring, stop and consult - `notes/deck-format-1.0.md` before writing changes. + `policy/deck-format-1.0.md` before writing changes. - For Markdown decks, `contextSchema` and `responseSchema` must reference a schema module path string (for example `contextSchema = "./schemas/input.zod.ts"`), not inline TOML objects. @@ -38,7 +19,7 @@ - When editing frontmatter, preserve existing keys and ordering where practical and make the smallest valid change. -## Frontmatter validation checklist +## Validation Checklist - Confirm all referenced `path` values resolve inside the workspace. - Confirm `[[scenarios]]` and `[[graders]]` point to `PROMPT.md` files. diff --git a/src/decks/gambit-bot/policy/interaction.md b/src/decks/gambit-bot/policy/interaction.md new file mode 100644 index 00000000..942367a0 --- /dev/null +++ b/src/decks/gambit-bot/policy/interaction.md @@ -0,0 +1,9 @@ +# Interaction Policy + +- Ask the minimum number of questions needed to produce a runnable deck. +- Prefer "scenario" language over "test" in user-facing text. +- Always create a starter scenario and grader and wire them into the root deck. +- If an existing root deck is the default scaffold echo bot (for example it + contains `Welcome to Gambit! What should we build?` and `Echo: {input}`), + overwrite it by default when implementing the user's requested bot unless the + user asks to preserve it. diff --git a/src/decks/gambit-bot/policy/safety-reliability.md b/src/decks/gambit-bot/policy/safety-reliability.md new file mode 100644 index 00000000..b42ba2ad --- /dev/null +++ b/src/decks/gambit-bot/policy/safety-reliability.md @@ -0,0 +1,6 @@ +# Safety And Reliability Policy + +- If a change would break Build/Test/Grade workflows, stop and ask for + confirmation. +- If a deck cannot run with the current model setup, highlight the issue and + offer a fallback. diff --git a/src/decks/gambit-init.deck.md b/src/decks/gambit-init.deck.md index db058fd6..3c59ebfd 100644 --- a/src/decks/gambit-init.deck.md +++ b/src/decks/gambit-init.deck.md @@ -28,7 +28,7 @@ Process: 1. Ask for the bot's purpose and 2-3 example user prompts. 2. Draft a Deck Format 1.0 root deck in the project root with `PROMPT.md` (and - optional `INTENT.md` + `POLICY.md` if helpful). + optional `INTENT.md` + `policy/*.md` if helpful). 3. Create a starter scenario deck at `scenarios/default/PROMPT.md` that exercises the primary intent and uses the default plain chat schemas. 4. Create a starter grader deck at `graders/default/PROMPT.md` that checks the diff --git a/src/decks/guides/gambit-bot-review.md b/src/decks/guides/gambit-bot-review.md index 5087a1a2..eff1bf5a 100644 --- a/src/decks/guides/gambit-bot-review.md +++ b/src/decks/guides/gambit-bot-review.md @@ -10,7 +10,10 @@ Required behavior - Ask for the minimum kickoff inputs needed to complete intent: purpose, 2-3 example user prompts, success criteria, and data sources. - Use Deck Format v1.0 by default: `PROMPT.md` as the single entrypoint with - optional `INTENT.md` and `POLICY.md` as non-programmatic guidance. + optional `INTENT.md` and `policy/*.md` as non-programmatic guidance. +- If the existing root deck is the default scaffold echo bot, overwrite it by + default when implementing the user's requested bot unless the user says to + keep it. - Use “scenario” language (not “test”) in new user-facing text. - Use the bot file tools to read/write within the bot root; do not suggest manual file edits when tool usage is available.