Repository navigation
feat(mbse): vendor requirements semantic model from kr0ki-core (M1) - #28
Merged
Merged
Conversation
Moves kr0ki-core's backend-neutral ReqIF/Flexo requirements model (RequirementGraph, five induced viewpoints, asserted/inferred/proposed relation authority with explicit promotion) into mbse::requirements as the shared canonical contract, per HANDOFF-2026-09-19-reqif-flexo.md lead-developer action #1. kr0ki-core re-exports it rather than keeping a local copy — single source of truth, zero drift. Version bump to 0.15.0 (additive public API, pre-1.0 minor per this crate's own stability policy). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJ5M1bGQJB1VS8Epr7AGLa
3 tasks done
elasticdotventures
added a commit
to PromptExecution/kr0ki
that referenced
this pull request
Sep 19, 2026
… ufo-types) (#36) * feat: storyb00k projects — planning stage, refinement questions, full transparency Cherry of 249837b onto post-#34 main: - project_store.py: per-thread project (title/goal/requirements/locked, verbatim prompt log, LLM thinking log, QA history) persisted beside charts; endpoints GET /projects[/{id}], POST /projects/rename - ask_user tool: multiple-choice refinement questions as AG-UI interrupts (options ride responseSchema defaults); answers recorded as QA, run continues - system prompt workflow: THINK → ASK → 'Locked in:' → RENDER; server-side lock detection - THINKING_* events: reasoning_content as 💭 thinking blocks, captured server-side - UI: project banner (editable title, locked badge, QA, expandable prompt+thinking log) - live E2E verified: 2 refinement rounds -> locked in -> k8s panel rendered - tests: 38 python, 15 vitest * fix: emit full TOOL_CALL lifecycle before ask_user/propose interrupts The client's state machine rejects TOOL_CALL_END/RESULT without a prior TOOL_CALL_START ('No active tool call found'), aborting the run before the interrupt reached the UI. ask_user now emits START → ARGS → END → RESULT; propose_draft_change (which emitted no tool-call events at all) gets the same lifecycle. Validated 6/6 against the @ag-ui/core event union; live verified: question interrupt now reaches the browser and answers flow. * fix(storyb00k): inline answer UI, no auto-resume collision, dark-theme inputs - autoResumeInterrupts: false — the client's auto-resume fired resume() the moment an interrupt was answered, colliding with our explicit chat.send() ('A run is already in progress'); continuation is now driven solely by submitAnswer() - question + options render immediately (no 'Answer question' gate click); submitAnswer targets the interrupt by id - dark theme: composer/prompt-editor/freetext/project-title inputs got UA white defaults on the dark app — now #091127 bg + #edf5ff text; message bubbles, interrupt cards, error/lock/requirement chips re-themed to match the app's palette * fix(playbook): tab renamed storyb00k -> Agent; editor hero copy cut to one line 'storyb00k' is an internal codename and stays out of the UI nav; the editor view's header paragraph was a wall of text — now one sentence. * fix(storyb00k): resume() instead of send() after answering; sidebar copy trimmed - answering an ask_user interrupt now calls chat.resume(), which replays the interrupted run with the recorded response — chat.send() started a fresh run and the agent rejected it ('Thread has N pending interrupt(s) not addressed by resume') - sidebar copy: 'Example fixtures for every supported format — or clear the source and render your own.' (internal jargon out) * fix(storyb00k): project memory prevents re-asking answered questions The client replays identical messages on resume, so the LLM never saw the answer and re-asked. Each run now injects answered QA (and any locked-in requirements) into the system prompt as PROJECT MEMORY — 'never ask the same or an equivalent question again' — and appends unanswered QA as explicit user turns. 39/39 python (new regression test captures the second run's LLM messages and asserts the memory + answer turn are present). * docs: PLAN-KR0KI-005 — gallery catalog & type-discovery agent spec Intent-first ergonomics: users don't know the diagram type they need. Gallery browse-by-use-case (filter defaults to All, distinct addressible typeIds, per-card Agent button pre-filling a typed sample prompt); agent 'discover' question series (audience -> intent shape -> fidelity -> recommend 1+1 -> confirm, with visual 'show me both') parallel to requirement refinement; type lock-in into PROJECT MEMORY; per-syntax skills loaded only when the type is locked. * feat: Plan 005 — gallery catalog, type-discovery agent, per-type skills Step 1 catalog: kr0ki-core/src/catalog.rs — 24 addressible diagram types with intent tags from a controlled vocabulary, sample prompts naming the type, discovery guide; /api/catalog route (+http test); 6 unit tests. Step 2 gallery: intent filter bar (defaults to All, auto-resets), type cards with Test/Edit/Agent buttons; Agent handoff prefills the Agent composer with the type's sample prompt (never auto-sent) via forwardedProps-ready prop. Step 3 discover mode: recommend_diagram_type tool — agent must commit to 1–2 type recommendations with rationales after ≤3 intent questions; confirm interrupt locks lockedType into the project; REFINE vs DISCOVER mode rules in the system prompt; project memory carries 'Type chosen: …'. Step 4 skills: skills/types/{sequence,activity,erd,component}.md loaded ONLY when the type is locked (replaces generic dump). Gates: 40/40 python, 15/15 vitest, 19/19 cargo suites, just check clean. Live acceptance: alert→resolution prompt with no syntax named → 2 discovery questions → recommend interrupt (State diagram | Flowchart | Show me both) → confirm locks type → next run is refine-mode with Locked in: summary. * fix(storyb00k): rec-* interrupts render the answer UI; approval payloads tolerated A recommend_diagram_type interrupt (rec-*) fell into the generic Approve-draft branch because isQuestionInterrupt only matched ask-* — posting {approved: true} to a question endpoint 400s. rec-* now renders the multiple-choice UI like ask-*; and the server tolerates approval-style payloads on question interrupts by choosing the primary option. 41/41 python. * style(gallery): filter bar redesign Pill-tab strip in a bordered tray: 'I want to show' label, hover/focus states, gradient active pill with glow, per-tag type counts, aria-pressed, and an empty-state when a filter matches nothing. * fix(gallery): type-card renders are card-scoped, not example-scoped; headline trimmed Ten PlantUML types share one fixture, so keying Test artifacts by example id lit up every PlantUML card at once. Type cards now use their own typeStatus/typeArtifacts/typeErrors maps keyed by typeId. Hero headline cut to 'Diagram-as-code, rendered.' * feat(storyb00k): fast-track 'Diagram now' + generation spinner - After 2 answered questions the project banner offers '⚡ Diagram now': arms fast-track server-side (POST /projects/fasttrack) and sends a best-judgement instruction. Fast-track overrides the question-mode rules entirely (FAST-TRACK MODE: asking is a contract violation); the agent states 'Best judgement:' choices and renders in the same run. - Dashboard shows a spinner + 'Generating diagram…' while a run streams, next to the panel count. - Live-verified: fast-track armed -> no questions, best-judgement lock-in, immediate render. 42/42 python, 15/15 vitest. * checkpoint: requirements and playbook progress * feat: harden requirements viewpoints * docs: add ReqIF Flexo delivery handoff * refactor(requirements): consume vendored ufo-types::mbse::requirements (M1) kr0ki-core no longer owns the requirements semantic model — it now re-exports ufo_types::mbse::requirements (released as ufo-types v0.15.0, PromptExecution/ufo-types#28) as kr0ki_core::requirements. Deletes the 873-line local copy; requirements_render.rs and kr0ki-server's HTTP routes are unchanged, since they resolve through the re-export. Zero duplication, zero drift: the semantic model has one home now. Verified: cargo build --workspace, clippy -D warnings, and the full kr0ki-core/kr0ki-server test suite (148 + 44 tests) all pass against the released tag. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJ5M1bGQJB1VS8Epr7AGLa * fix(d2): quote/escape labels so arbitrary text can't alter D2 structure Addresses PR #36 review, P1 findings 1 and 2. - crates/kr0ki-core/src/b00t_graph.rs: d2_escape_label only neutralized newlines, leaving D2's structural characters ({, }, :, ...) live in label position. A ReqIF requirement title like "normal requirement {" emits invalid D2 ("maps must be terminated with }") or, worse, a title like "{shape: circle}" gets interpreted as D2 structure instead of label text. Fixed at the shared helper (used by requirements_render, b00t_graph's own D2Emitter, and sysml_render — all three had the identical defect), so labels are now quoted/escaped the same way d2_quote already handles ids. Added adversarial-title coverage in all three call sites' test modules; updated the two existing tests that had encoded the old unquoted behavior as expected output. - .gitmodules: vendor/assistant-ui had only `branch`, no `path`/`url`, so `actions/checkout` with `submodules: recursive` fails before any test runs — blocking every CI check regardless of this PR's content. Added the missing path/url (https://github.com/elasticdotventures/ assistant-ui.git, matching the already-checked-out working tree's own remote and the pinned gitlink commit). Verified: `git ls-remote` resolves the pinned commit on that url/branch unauthenticated, and `git submodule init && git submodule sync` succeeds locally. Verified: cargo build --workspace, cargo clippy --workspace -- -D warnings, cargo test -p kr0ki-core -p kr0ki-server (150 + 44 passing). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJ5M1bGQJB1VS8Epr7AGLa * style: cargo fmt the adversarial-label test CI's cargo fmt --all -- --check caught a multi-line assert_eq! rustfmt collapses onto one line; missed locally in the prior commit since I verified build/clippy/test there but not fmt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CJ5M1bGQJB1VS8Epr7AGLa --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RequirementGraph, five induced viewpoints, asserted/inferred/proposed relation authority + explicit promotion) intombse::requirementsas the canonical shared contract.ufo_types::mbse::requirementsaskr0ki_core::requirementsrather than keeping a local copy — single source of truth, zero drift, zero duplication.PromptExecution/kr0kidocs/HANDOFF-2026-09-19-reqif-flexo.md, lead-developer action ci: add standalone ufo-types quality gate #1.Test plan
cargo test --all-features— 261 passedcargo clippy --all-targets --all-features -- -D warnings— cleancargo fmt --check— clean