chore: seed prolog knowledge base and track kb.pl

AGENTS.md tells agents to load the `kb` Prolog session at session start,
but prolog-sessions/ was fully gitignored, so the KB could never survive a
fresh clone -- every session started from an empty knowledge base.

Narrow the ignore to prolog-sessions/* with an exception for kb.pl, and
check in a seed KB built from context/repo-map.md and
context/design-principles.md: crate/layer/coupling rules, the
"where do I change X" location table, the Cmd -> Effect pipeline,
the load-bearing invariants, testing doctrine, and the beads workflow.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V69PGQfMJuGRmtSWpfVAqn
This commit is contained in:
Edward Langley
2026-08-29 10:25:01 -07:00
parent 605d412225
commit aabee3a460
2 changed files with 87 additions and 1 deletions
+3 -1
View File
@@ -30,4 +30,6 @@ proptest-regressions/
/roadmap.html
# prolog-mcp session files (server writes ./prolog-sessions relative to cwd)
prolog-sessions/
# ...except the checked-in seed knowledge base, which agents load at session start.
prolog-sessions/*
!prolog-sessions/kb.pl
+84
View File
@@ -0,0 +1,84 @@
sleep(A) :-
wasm_generic:host_rpc(sleep(A)).
delay(A) :-
wasm_generic:host_rpc(delay(A)).
console_log(A) :-
wasm_generic:host_rpc(console_log(A)).
js_eval(A,B) :-
wasm_generic:host_rpc(js_eval(A,B)).
js_eval_json(A,B) :-
wasm_generic:host_rpc(js_eval_json(A,B)).
future(A,B) :-
wasm_generic:host_rpc(future(A,B)).
await_any(A,B,C) :-
wasm_generic:host_rpc(await_any(A,B,C)).
future_cancel(A) :-
wasm_generic:host_rpc(future_cancel(A)).
crate(improvise_core,'crates/improvise-core','Model, View, Workbook, formatting; no UI/IO').
crate(improvise_formula,'crates/improvise-formula','formula parser, AST, parse_formula').
crate(improvise_io,'crates/improvise-io','improv save/load, CSV/JSON import; no UI/commands').
crate(improvise_command,'crates/improvise-command','command/effect layer + semantic App state; no ratatui').
crate(improvise_main,src,'ratatui TUI rendering, draw loop, clap CLI').
layer(model,improvise_core).
layer(view,improvise_core).
layer(formula,improvise_formula).
layer(io,improvise_io).
layer(command,improvise_command).
layer(rendering,improvise_main).
forbidden(improvise_core,ui).
forbidden(improvise_core,io).
forbidden(improvise_io,ui).
forbidden(improvise_io,commands).
forbidden(improvise_command,ratatui).
forbidden(improvise_command,crossterm).
location(add_keybinding,'crates/improvise-command/src/command/keymap.rs','default_keymaps()').
location(add_command,'crates/improvise-command/src/command/cmd/registry.rs','default_registry()').
location(add_effect,'crates/improvise-command/src/ui/effect.rs','impl Effect').
location(formula_eval,'crates/improvise-core/src/model/types.rs','eval_formula / eval_expr').
location(cell_storage,'crates/improvise-core/src/model/cell.rs','DataStore').
location(category_behavior,'crates/improvise-core/src/model/category.rs','Category').
location(view_axis_logic,'crates/improvise-core/src/view/types.rs','View').
location(grid_layout,'crates/improvise-core/src/view/layout.rs','GridLayout').
location(improv_format,'crates/improvise-io/src/persistence/improv.pest','PEG grammar, source of truth').
location(number_display,'crates/improvise-core/src/format.rs',format_f64).
location(cli_args,'src/main.rs',clap).
location(import_logic,'crates/improvise-io/src/import/wizard.rs','ImportPipeline').
location(frame_layout,'src/draw.rs','draw()').
location(app_state_modes,'crates/improvise-command/src/ui/app.rs','App, AppMode').
pipeline_step(1,keypress,keymap_lookup).
pipeline_step(2,keymap_lookup,cmd_execute).
pipeline_step(3,cmd_execute,effect_list).
pipeline_step(4,effect_list,effect_apply).
pure(cmd_execute).
mutating(effect_apply).
only_mutation_site('Effect::apply(&mut App)').
invariant(cellkey_sorted,'CellKey coords always sorted by category; build via CellKey::new/with/without').
invariant(display_rounding,'format_f64 is render-only; never feed rounded values back into eval').
invariant(fixedpoint_eval,'recompute_formulas iterates to stability; circular -> CellValue::Error(\"circular\")').
invariant(indexmap_order,'IndexMap insertion order is load-bearing for persistence').
invariant(no_model_add_item,'No Model::add_item; use Workbook facade or category_mut().add_item()').
invariant(stale_layout,'app.layout rebuilds only after a whole effect batch; prepend RebuildLayout when needed').
invariant(minibuffer_spine,'Seven text-entry modes built by TextEntry builder in keymap.rs; SearchMode hand-written').
doctrine(bug_first,'write a failing test demonstrating the bug before fixing it').
doctrine(unit_over_e2e,'prefer small unit tests over integration/e2e').
doctrine(suite_speed,'workspace suite must stay under 2 seconds').
doctrine(coverage,'aim ~80% line/branch on logic; skip ratatui render paths').
doctrine(test_contract,'test the observable contract, not the internal storage').
doctrine(proptest_cases,'keep proptest at default 256 cases; constrain strategies instead of brute force').
tracker(beads,bd,'bd ready / bd show / bd update --claim / bd close; no TodoWrite or markdown TODOs').
session_close(1,'file issues for remaining work').
session_close(2,'run quality gates if code changed').
session_close(3,'update issue status').
session_close(4,'git merge origin/main, bd dolt push, git push').
session_close(5,'clean up stashes and pruned branches').
session_close(6,'verify committed AND pushed').
session_close(7,'hand off context').
crate_of_layer(A,B) :-
layer(A,B).
may_depend_on(A,B) :-
crate(A,C,D), \+forbidden(A,B).
where(A,B,C) :-
location(A,B,C).
before_fixing(A,B) :-
A=C,doctrine(bug_first,B).