Skip to content

Commit cf1c00d

Browse files
committed
Clarify README messaging for BEAR
1 parent 3c8e524 commit cf1c00d

7 files changed

Lines changed: 162 additions & 33 deletions

File tree

README.md

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
1-
# BEAR (bear-cli)
1+
# BEAR
2+
3+
Block Enforceable Architectural Representation
24

35
<p align="center">
46
<img src="assets/logo/bear-header-1400x320-clean.png" alt="BEAR logo" width="100%" />
57
</p>
68

7-
BEAR is a deterministic governance CLI and CI gate for agentic backend development.
9+
Agents can generate large amounts of code very quickly.
10+
The dangerous changes are often structural: new dependencies, widened boundaries, and new authority surfaces.
11+
12+
BEAR makes those architectural changes explicit and visible in CI.
13+
14+
BEAR is a deterministic governance CLI and CI gate for agent-driven backend development.
15+
16+
Demo repo: [bear-account-demo](https://github.com/rore/bear-account-demo)
817

9-
You edit code plus BEAR IR, then BEAR reports stable, machine-parseable signals: either green, or a precise failure with a remediation hint.
18+
When boundary authority changes, the agent updates BEAR IR first, BEAR compiles deterministic structural constraints, and then implementation code fits inside those constraints.
19+
The result is a stable, machine-parseable governance signal: either green, or a precise failure with a remediation hint.
1020

1121
```mermaid
1222
%% id: bear-workflow-v1
1323
flowchart LR
14-
A[Agent / Dev edits code]:::actor --> B[Edit BEAR IR file]:::ir
24+
A[Agent / Dev identifies boundary change]:::actor --> B[Update BEAR IR]:::ir
1525
B --> C[bear compile]:::cmd
16-
C --> D[Generate boundary glue]:::gen
17-
D --> E[bear check]:::cmd
18-
E --> F{CI green?}:::gate
19-
F -- yes --> G[Merge]:::ok
20-
F -- no --> H[Fix code or IR]:::bad
26+
C --> D[Generate structural constraints]:::gen
27+
D --> E[Agent / Dev implements inside constraints]:::actor
28+
E --> F[bear check]:::cmd
29+
F --> G{CI green?}:::gate
30+
G -- yes --> H[Merge]:::ok
31+
G -- no --> I[Fix code or IR]:::bad
2132
22-
I[bear pr-check]:::cmd --> J{Boundary delta in PR?}:::gate
23-
J -- none --> F
24-
J -- expansion/bypass --> H
33+
J[bear pr-check]:::cmd --> K{Boundary delta in PR?}:::gate
34+
K -- none --> G
35+
K -- expansion/bypass --> I
2536
26-
E -. emits .-> S1[[CI contract output:<br/>exit code + CODE/PATH/REMEDIATION]]:::signal
27-
I -. emits .-> S2[[PR output:<br/>pr-delta + verdict + footer]]:::signal
37+
F -. emits .-> S1[[CI contract output:<br/>exit code + CODE/PATH/REMEDIATION]]:::signal
38+
J -. emits .-> S2[[PR output:<br/>pr-delta + verdict + footer]]:::signal
2839
2940
classDef actor fill:#EEF2FF,stroke:#6366F1,color:#0B1220;
3041
classDef ir fill:#FFFBEB,stroke:#F59E0B,color:#0B1220;
@@ -39,11 +50,11 @@ flowchart LR
3950

4051
## What BEAR does (plain terms)
4152

42-
- An agent updates code and (when needed) a small YAML IR contract (BEAR IR).
53+
- When boundary authority must change, the agent updates a small YAML IR contract (BEAR IR) first.
4354
- A block is a governed backend unit; its operations, allowed effects, and ports are declared in BEAR IR.
44-
- BEAR generates deterministic guardrails (wrappers/ports) from that declaration.
55+
- BEAR compiles that declaration into deterministic guardrails (wrappers, ports, manifests).
56+
- The agent then implements code inside those guardrails instead of inventing the boundary shape ad hoc.
4557
- Blocks interact only through declared ports; cross-boundary access outside a declared port is flagged as a violation (or PR signal).
46-
- Implementation can evolve freely inside those guardrails.
4758
- CI gets deterministic governance signals from `check` and `pr-check`.
4859

4960
## What you get
@@ -157,3 +168,7 @@ The demo currently showcases three PR outcomes:
157168
- Primary containment enforcement path is Java plus Gradle wrapper when `impl.allowedDeps` is declared.
158169

159170
This project uses [Minimap](https://github.com/rore/minimap) for repo-local roadmap and feature planning.
171+
172+
173+
174+

docs/context/state.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,6 @@ The packaged downstream CI integration is complete and stable, and `main` now al
2929
- Imported the parked Node discovery work into minimap and kept the recommendation intentionally narrow: do not pursue Node unless the product explicitly accepts the `node-ts-pnpm-single-package-v1` profile.
3030
- Added parked .NET discovery docs as a stronger-fit second-target candidate, focused on a narrow C# SDK-style profile with deterministic `dotnet` verification and project/package governance.
3131
- Archived or removed stale process docs that no longer earn their keep in a public repo, including the old simulation, grading, checkpoint, and duplicate board docs.
32-
- Verification: `./gradlew.bat --no-daemon :kernel:test`, `./gradlew.bat --no-daemon :app:test`, `./gradlew.bat --no-daemon :app:test :kernel:test`, `./gradlew.bat --no-daemon :app:test --tests com.bear.app.ContextDocsConsistencyTest`, `./gradlew.bat :app:compileJava :app:compileTestJava :kernel:compileJava :kernel:compileTestJava`.
32+
- Tightened README and public docs wording so the intended agent loop is explicit: boundary changes update IR first, BEAR compiles constraints, then implementation happens inside those constraints.
33+
- Verification: ./gradlew.bat --no-daemon :kernel:test, ./gradlew.bat --no-daemon :app:test, ./gradlew.bat --no-daemon :app:test :kernel:test, ./gradlew.bat --no-daemon :app:test --tests com.bear.app.ContextDocsConsistencyTest, ./gradlew.bat :app:compileJava :app:compileTestJava :kernel:compileJava :kernel:compileTestJava.
34+

docs/public/DEMO.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
BEAR is a deterministic governance CLI and CI gate for agentic backend development.
44

55
In plain terms:
6-
- an agent updates code and BEAR IR
7-
- `bear compile` generates deterministic boundary glue
6+
- when boundary authority changes, the agent updates BEAR IR first
7+
- `bear compile` generates deterministic structural constraints from that IR
8+
- the agent implements code inside those constraints
89
- `bear check` verifies repo consistency and covered bypasses
910
- `bear pr-check` tells you whether a pull request widened governed boundary authority
1011

@@ -115,3 +116,4 @@ If you want the packaged CI and PR-review model used by the demo, continue with:
115116

116117
- [CI_INTEGRATION.md](CI_INTEGRATION.md)
117118
- [PR_REVIEW.md](PR_REVIEW.md)
119+

docs/public/FOUNDATIONS.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ BEAR exists to make boundary authority changes explicit, enforceable, and CI-vis
1919
## Intended Workflow Loop
2020

2121
Agent loop:
22-
1. Update implementation + IR from domain intent.
22+
1. Update IR first when domain intent changes boundary authority.
2323
2. Run `bear validate`.
24-
3. Run `bear compile` or `bear fix`.
25-
4. Run `bear check --collect=all --agent` until `status=ok`.
26-
5. Run `bear pr-check --base <ref> --collect=all --agent` for governance classification.
24+
3. Run `bear compile` or `bear fix` to materialize the governed structural constraints.
25+
4. Update implementation inside those constraints.
26+
5. Run `bear check --collect=all --agent` until `status=ok`.
27+
6. Run `bear pr-check --base <ref> --collect=all --agent` for governance classification.
2728

2829
Developer role:
2930
- review explicit boundary signals in PR/CI
@@ -60,3 +61,4 @@ It is intentionally not full behavioral verification or runtime policy enforceme
6061
- [ENFORCEMENT.md](ENFORCEMENT.md)
6162
- [PR_REVIEW.md](PR_REVIEW.md)
6263
- [CONTRACTS.md](CONTRACTS.md)
64+

docs/public/OVERVIEW.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ The goal is to move trust from intent to machine-checkable gates and explicit go
88

99
## What BEAR does
1010

11-
- **Agent updates** code and IR when boundary authority must change.
12-
- **BEAR compiles** deterministic wrappers/ports/manifests from IR.
11+
- **Agent updates IR first** when boundary authority must change.
12+
- **BEAR compiles** deterministic wrappers, ports, and manifests from that IR.
13+
- **Agent updates code inside those constraints** instead of widening structure implicitly.
1314
- **BEAR checks** repo state for drift and covered boundary bypasses.
1415
- **BEAR governs PR deltas** with explicit boundary-expansion classification.
1516

@@ -38,3 +39,4 @@ The agent updates IR as needed; developers review resulting governance signals.
3839
- [PR_REVIEW.md](PR_REVIEW.md)
3940
- [CI_INTEGRATION.md](CI_INTEGRATION.md) for the packaged downstream CI pattern and GitHub Actions usage
4041
- [FOUNDATIONS.md](FOUNDATIONS.md) for full mechanics
42+

docs/public/QUICKSTART.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ Set-Location ..\bear-account-demo
2222
.\.bear\tools\bear-cli\bin\bear.bat --help
2323
```
2424

25-
3. Let your agent implement the spec.
25+
3. Let your agent update the IR if boundary authority changes, then implement the code inside the generated constraints.
2626

2727
```text
28-
Implement the specs.
28+
Implement the specs. Update BEAR IR first if the boundary must change.
2929
```
3030

3131
4. Compile deterministic generated artifacts.
@@ -107,3 +107,4 @@ If something fails, go to [troubleshooting.md](troubleshooting.md).
107107
- [ENFORCEMENT.md](ENFORCEMENT.md)
108108
- [CONTRACTS.md](CONTRACTS.md)
109109
- [CI_INTEGRATION.md](CI_INTEGRATION.md)
110+

tools/minimap/ui/app.js

Lines changed: 110 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const SCOPE_WIDTH_STORAGE_KEY = "roadmap-ui.scope-width";
44
const DEFAULT_SCOPE_WIDTH = 272;
55
const MIN_SCOPE_WIDTH = 240;
66
const MAX_SCOPE_WIDTH = 440;
7+
const EDITOR_MODES = new Set(["preview", "structured", "raw"]);
78

89
const state = {
910
workspace: null,
@@ -271,6 +272,50 @@ function updateWorkspaceSummary() {
271272
workspaceSummaryElement.textContent = state.workspace ? `${items} items / ${groups} groups` : "Unavailable";
272273
}
273274

275+
function normalizeEditorMode(mode) {
276+
return EDITOR_MODES.has(mode) ? mode : "preview";
277+
}
278+
279+
function readRouteState() {
280+
const rawHash = window.location.hash.startsWith("#") ? window.location.hash.slice(1) : "";
281+
const params = new URLSearchParams(rawHash);
282+
return {
283+
itemId: params.get("item") || "",
284+
mode: normalizeEditorMode(params.get("mode") || "preview"),
285+
};
286+
}
287+
288+
function buildRouteHash(itemId = state.selectedItemId, mode = state.editorMode) {
289+
const params = new URLSearchParams();
290+
291+
if (itemId) {
292+
params.set("item", itemId);
293+
}
294+
295+
const normalizedMode = normalizeEditorMode(mode);
296+
if (normalizedMode !== "preview") {
297+
params.set("mode", normalizedMode);
298+
}
299+
300+
const serialized = params.toString();
301+
return serialized ? `#${serialized}` : "";
302+
}
303+
304+
function syncRouteState({ replace = false } = {}) {
305+
const nextHash = buildRouteHash();
306+
if (window.location.hash === nextHash) {
307+
return;
308+
}
309+
310+
const nextUrl = `${window.location.pathname}${window.location.search}${nextHash}`;
311+
if (replace) {
312+
window.history.replaceState(null, "", nextUrl);
313+
return;
314+
}
315+
316+
window.history.pushState(null, "", nextUrl);
317+
}
318+
274319
function isStackedLayout() {
275320
return stackedLayoutMedia.matches;
276321
}
@@ -954,11 +999,40 @@ function resetAncillaryEditModes() {
954999
state.scopeDirty = false;
9551000
}
9561001

957-
async function loadWorkspace(preferredItemId = state.selectedItemId) {
1002+
async function applyRouteStateFromLocation() {
1003+
const route = readRouteState();
1004+
const routeItemId = route.itemId || "";
1005+
const currentItemId = state.selectedItemId || "";
1006+
1007+
if (routeItemId && routeItemId !== currentItemId) {
1008+
await loadWorkspace(routeItemId, {
1009+
preferredMode: route.mode,
1010+
syncRoute: false,
1011+
});
1012+
return;
1013+
}
1014+
1015+
if (!routeItemId && currentItemId) {
1016+
await loadWorkspace(undefined, {
1017+
preferredMode: route.mode,
1018+
syncRoute: false,
1019+
});
1020+
return;
1021+
}
1022+
1023+
const nextMode = normalizeEditorMode(route.mode);
1024+
if (nextMode !== state.editorMode) {
1025+
state.editorMode = nextMode;
1026+
applyEditorMode();
1027+
}
1028+
}
1029+
1030+
async function loadWorkspace(preferredItemId = state.selectedItemId, options = {}) {
9581031
try {
9591032
const workspace = await fetchJson("/api/workspace");
9601033
resetAncillaryEditModes();
9611034
state.workspace = workspace;
1035+
state.editorMode = normalizeEditorMode(options.preferredMode ?? state.editorMode);
9621036
roadmapPathElement.textContent = workspace.roadmapPath;
9631037
syncWorkspaceChrome();
9641038
renderBoard();
@@ -967,9 +1041,15 @@ async function loadWorkspace(preferredItemId = state.selectedItemId) {
9671041

9681042
const itemIdToLoad = preferredItemId && workspace.items?.[preferredItemId] ? preferredItemId : getFirstBoardItemId(workspace);
9691043
if (itemIdToLoad) {
970-
await loadItem(itemIdToLoad, false);
1044+
await loadItem(itemIdToLoad, false, {
1045+
syncRoute: options.syncRoute,
1046+
replaceRoute: options.replaceRoute,
1047+
});
9711048
} else {
9721049
resetEditor();
1050+
if (options.syncRoute !== false) {
1051+
syncRouteState({ replace: options.replaceRoute !== false });
1052+
}
9731053
}
9741054
} catch (error) {
9751055
state.workspace = null;
@@ -984,7 +1064,7 @@ async function loadWorkspace(preferredItemId = state.selectedItemId) {
9841064
}
9851065
}
9861066

987-
async function loadItem(itemId, rerenderBoard = true) {
1067+
async function loadItem(itemId, rerenderBoard = true, options = {}) {
9881068
try {
9891069
const item = await fetchJson(`/api/items/${encodeURIComponent(itemId)}`);
9901070
state.selectedItemId = itemId;
@@ -993,6 +1073,9 @@ async function loadItem(itemId, rerenderBoard = true) {
9931073
if (rerenderBoard) {
9941074
renderBoard();
9951075
}
1076+
if (options.syncRoute !== false) {
1077+
syncRouteState({ replace: options.replaceRoute === true });
1078+
}
9961079
setBanner("");
9971080
} catch (error) {
9981081
setBanner(error.message, "error");
@@ -1050,7 +1133,7 @@ function applyEditorMode() {
10501133
}
10511134
}
10521135

1053-
function switchEditorMode(nextMode) {
1136+
function switchEditorMode(nextMode, options = {}) {
10541137
if (nextMode === state.editorMode) {
10551138
return;
10561139
}
@@ -1075,6 +1158,10 @@ function switchEditorMode(nextMode) {
10751158

10761159
state.editorMode = nextMode;
10771160
applyEditorMode();
1161+
1162+
if (options.syncRoute !== false) {
1163+
syncRouteState({ replace: options.replaceRoute !== false });
1164+
}
10781165
}
10791166

10801167
async function saveCurrentItem() {
@@ -1229,6 +1316,10 @@ for (const button of modeButtons) {
12291316
});
12301317
}
12311318

1319+
window.addEventListener("hashchange", () => {
1320+
void applyRouteStateFromLocation();
1321+
});
1322+
12321323
desktopScopeLayoutMedia.addEventListener("change", () => {
12331324
renderScopeChrome();
12341325
});
@@ -1239,6 +1330,20 @@ stackedLayoutMedia.addEventListener("change", () => {
12391330
});
12401331

12411332
resetEditor();
1333+
const initialRoute = readRouteState();
1334+
state.editorMode = initialRoute.mode;
12421335
renderScopeChrome();
12431336
applyEditorMode();
1244-
void loadWorkspace();
1337+
void loadWorkspace(initialRoute.itemId || state.selectedItemId, {
1338+
preferredMode: initialRoute.mode,
1339+
syncRoute: false,
1340+
}).then(() => {
1341+
if (initialRoute.itemId || initialRoute.mode !== "preview") {
1342+
void applyRouteStateFromLocation();
1343+
return;
1344+
}
1345+
1346+
if (state.selectedItemId) {
1347+
syncRouteState({ replace: true });
1348+
}
1349+
});

0 commit comments

Comments
 (0)