Skip to content

Commit b664f7a

Browse files
committed
feat: make Boatstack explicitly engaged
1 parent ccbd523 commit b664f7a

37 files changed

Lines changed: 934 additions & 247 deletions

.github/tests/test_detached_supervision.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def test_bootstrap_oracle_is_credential_free_and_executes_exact_output(self) ->
190190
}
191191
for host, event in events.items():
192192
admitted = self.run_helper(
193-
"ambient-safety-hook", "--host", host, "--repo", ".", stdin=json.dumps(event)
193+
"engagement-probe", "--host", host, "--repo", ".", stdin=json.dumps(event)
194194
)
195195
self.assertNotIn("deny", admitted.stdout.lower(), host)
196196

@@ -229,28 +229,30 @@ def test_activate_installs_guard_preserving_user_hooks(self) -> None:
229229

230230
text = claude_config.read_text()
231231
self.assertIn("my-own.sh", text)
232-
self.assertIn("ambient-safety-hook", text)
232+
self.assertIn("engagement-probe", text)
233+
self.assertIn("engagement.json", text)
234+
self.assertIn("commandWindows", text)
233235
self.assertIn("theme", text)
234236

235237
# Idempotent: re-activating changes nothing.
236238
again = self.helper_json("activate", "--repo", ".", "--host", "claude")
237239
self.assertTrue(all(host["action"] == "unchanged" for host in again["hosts"]))
238240

239-
# Deactivate removes only the ambient guard.
241+
# Deactivate removes only the engagement probe.
240242
self.run_helper("deactivate", "--repo", ".", "--host", "claude")
241243
after = claude_config.read_text()
242-
self.assertNotIn("ambient-safety-hook", after)
244+
self.assertNotIn("engagement-probe", after)
243245
self.assertIn("my-own.sh", after)
244246

245-
def test_ambient_guard_enforces_managed_and_noops_unmanaged(self) -> None:
246-
# Unattached: the developer-level guard must not control this repository.
247-
unmanaged = self.run_helper("ambient-safety-hook", "--host", "claude", "--repo", ".", stdin=DESTRUCTIVE_EVENT)
248-
self.assertNotIn('"permissionDecision":"deny"', unmanaged.stdout)
247+
def test_engagement_probe_is_inert_before_and_after_attachment(self) -> None:
248+
# Unattached: the developer-level probe must not control this repository.
249+
unmanaged = self.run_helper("engagement-probe", "--host", "claude", "--repo", ".", stdin=DESTRUCTIVE_EVENT)
250+
self.assertEqual(unmanaged.stdout, "")
249251

250-
# Attached: the same destructive command is denied by the same engine.
252+
# Attachment is configuration, not workflow authority.
251253
self.run_helper("attach", "--repo", ".", "--mode", "detached")
252-
managed = self.run_helper("ambient-safety-hook", "--host", "claude", "--repo", ".", stdin=DESTRUCTIVE_EVENT)
253-
self.assertIn('"permissionDecision":"deny"', managed.stdout)
254+
attached = self.run_helper("engagement-probe", "--host", "claude", "--repo", ".", stdin=DESTRUCTIVE_EVENT)
255+
self.assertEqual(attached.stdout, "")
254256

255257
def test_detached_work_keeps_repo_product_only(self) -> None:
256258
self.run_helper("attach", "--repo", ".", "--mode", "detached")

boatstack/SKILL.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
---
22
name: boatstack
3-
description: Use when the user explicitly asks for Boatstack, asks what is next in Boatstack, or works on an active or current-branch published Boatstack delivery. Do not activate from installation, attachment, saved or approved drafts, or repository presence alone.
3+
description: Use only when the user explicitly asks for Boatstack, asks what is next in Boatstack, or works on a verified active pre-publication Boatstack delivery in the current worktree and branch. Do not activate from installation, attachment, saved or approved drafts, published work, repository presence, or repository administration.
44
---
55

66
# Boatstack
77

88
Build the smallest complete product slice that can be independently verified. Implementation methods remain open: project facts, approval, and gate evidence are canonical; host-specific prompts are adapters. You are free in how you build. Only claims of completion require evidence.
99

10-
Boatstack starts only from an explicit user request or a managed delivery bound to the current worktree and branch. A saved, approved, policy-ready, ambiguous, stale, or invalid draft is repository evidence, not ambient workflow authority. Before explicit use, only the irreversible-operation safety floor and Boatstack-owned state boundaries apply.
10+
Boatstack starts only from an explicit user request or a verified active pre-publication delivery bound to the current worktree and branch. A saved, approved, policy-ready, ambiguous, stale, invalid, or published delivery is repository evidence, not ambient workflow authority. Outside engagement, Boatstack applies no workflow, state, publication, or irreversible-operation policy.
1111

1212
## Start by selecting the operation
1313

@@ -44,17 +44,17 @@ After preflight, repeatedly run `next-status --repo . --feature <slug> --json`,
4444

4545
When `delivery.terminal` is `merged`, follow the post-publish prescriptions exactly. After publication, run `flow next` (or `next-status`). When it prescribes `flow watch`, run the watch and re-resolve when it exits. When checks fail, it prescribes `record-change --source-stage ci`; derive the exact message, classification, evidence, and changed repair mechanism from the failing check logs, never from memory, then repair, re-gate, and republish with `publish-pr --action update`. When the PR is observed merge-eligible, it prescribes the exact `gh pr merge` command; run it only as rendered, under the host's own permissions — Boatstack never merges, and you never merge without the prescription. A required review approval, a changes-requested verdict, a closed PR, or an unverifiable PR position always ends your turn at the operator frontier.
4646

47-
## Enforce the irreversible-operation boundary
47+
## Enforce the irreversible-operation boundary during engagement
4848

49-
Read [irreversible-operation-boundary.md](references/irreversible-operation-boundary.md). Project hooks hard-deny high-confidence destructive shell and MCP operations on every supported agent call. Never request or invent an in-session bypass. After an external-write failure, preserve state, use read-only diagnosis, retain the immutable target boundary, and choose only proven transactional retry or fix-forward recovery. Source edits may be reviewed, but an executable destructive capability blocks activation and every later gate.
49+
Read [irreversible-operation-boundary.md](references/irreversible-operation-boundary.md). During an explicit Boatstack command or verified active delivery, project hooks hard-deny high-confidence destructive shell and MCP operations. Outside engagement, Boatstack is inert; the host, operator, and external platform own safety. Never request or invent an in-session bypass while engaged. After an engaged external-write failure, preserve state, use read-only diagnosis, retain the immutable target boundary, and choose only proven transactional retry or fix-forward recovery.
5050

5151
This enforcement is defense in depth, not a complete sandbox. Keep least-privilege service credentials and service-side destructive approval in place. Read `authority_status` from `run-preflight`: `HOOK_GUARDED` never proves ambient cloud authority absent, while `CREDENTIAL_ENFORCED` means a trusted external attestor supplied a current repository-only receipt. Never strengthen the former into the latter in prose.
5252

5353
## Keep repository administration outside delivery
5454

55-
Branch synchronization, status, switching, worktree maintenance, and requests to discard local changes are repository administration, not product intent. Never route them to `auto-plan` or `repair` unless the exact target branch belongs to an active managed delivery. For an explicit branch and remote ref, use the project-local `workspace-sync` helper. It fetches the exact source, checkpoints branch and dirty-worktree state, aligns the branch in its owning worktree, and returns verified recovery refs.
55+
Branch synchronization, status, switching, worktree maintenance, and requests to discard local changes are repository administration, not Boatstack intent. Never activate Boatstack or route them to `auto-plan`, `repair`, or `workspace-sync`. If the user explicitly asks Boatstack to manage repository alignment during an active delivery, the named command remains available.
5656

57-
For requests such as “ensure main is same as origin/main remove any current changes,” inspect only the named refs and worktree, then invoke `.product-loop/boatstack workspace-sync --repo . --branch main --source origin/main`. If the guard denies a raw hard reset or clean, report the denial and this single recovery action immediately. Do not inspect feature plans, scan the repository, search for the helper, or retry destructive Git.
57+
For requests such as “ensure main is same as origin/main remove any current changes,” use ordinary repository administration. Do not inspect feature plans, invoke Boatstack, or render a Boatstack response unless the user explicitly asks Boatstack to perform that operation.
5858

5959
## Bound the outcome
6060

0 commit comments

Comments
 (0)