Parfii-bot
2d2c9881de
feat(entity-store/b5): EdgeKeyKind::TextPair + archive verb — unblock kei-sage + kei-chat-store migration
...
schema.rs: EdgeKeyKind enum (IntegerPair default, TextPair) + archived_field:
Option<&'static str> on EntitySchema. Backward-compat via Default impl.
engine.rs: ddl_edge_table_for() dispatches integer vs text edge DDL.
Existing ddl_edge_table() untouched; new ddl_edge_table_text() adds
src_path/dst_path TEXT columns.
verbs/link.rs (rewrite): dispatches on edge_key_kind. Input JSON
{from:int, to:int} for IntegerPair OR {from:str, to:str} for TextPair.
verbs/rank.rs (rewrite): generic pagerank<K: Hash + Eq + Clone> over
node key type. Same algorithm, polymorphic in key.
verbs/archive.rs (new, 64 LOC): soft-delete via UPDATE <tbl> SET
<archived_field>=1 + optional <archived_field>_at=now(). Schema
without archived_field declared returns VerbError.
Tests: 20/20 kei-entity-store (was 10, +10: 5 text_pair + 5 archive).
kei-task 9/9 preserved (IntegerPair still default, backward-compat
verified).
Enables: kei-sage migration (TextPair edges) + kei-chat-store
migration (archive).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 05:30:33 +08:00
Parfii-bot
324ad5d53e
fix(p1-integration): validate.rs allows _schemas/fragments $ref + drop additionalProperties on fragment-composed atom schemas
...
Two P1↔E1-audit-wave integration regressions caught by kei-runtime
invoke_real_atom test.
1. LocalFileResolver (E1 SSRF hardening) rejected $ref to
_schemas/fragments/ because the dir is OUTSIDE atom's schema parent.
Fix: extend LocalFileResolver with `find_fragments_root()` — walks up
from schema root looking for `_schemas/fragments/`. If found, allow
$ref under EITHER schema root OR fragments root. Still rejects
arbitrary filesystem $ref.
2. jsonschema injection of absolute $id now ALSO applied to fragment
schemas loaded via LocalFileResolver.resolve(). Without this, a
fragment declaring `$id: "_schemas/fragments/titled.json"` (relative)
was resolved against parent schema's absolute $id, producing double
prefix `_schemas/fragments/_schemas/fragments/titled.json`.
3. create-input.json + create-output.json had `additionalProperties:
false` alongside `allOf: [$ref <fragment>]`. Draft-07 gotcha:
additionalProperties at this level does NOT see properties inherited
from $ref-ed fragment — caused 'title' unexpected rejection. Dropped
the constraint on 2 fragment-composed schemas; kept on 4 standalone
ones (search-input/output + add-dependency-input/output).
Tests: kei-runtime 5/5 green; integration test passes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 04:53:26 +08:00
Parfii-bot
793b91bc43
feat(convergence/p1): kei-entity-store engine + schema fragments + kei-task pilot
...
Layer A + B of convergence wave. Extract common SQLite-CRUD + graph
logic into kei-entity-store engine; introduce JSON Schema fragments;
pilot-migrate kei-task to verify parity.
New crate _primitives/_rust/kei-entity-store/ (1151 LOC):
- src/schema.rs — EntitySchema + FieldDef + enabled_verbs + fts_columns
+ edge_table + custom_migrations
- src/engine.rs — Store::open with WAL pragma + migration runner
- src/verbs/ — 8 data-driven verb modules (create/get/list/search/
update/delete/link/rank) uniform JSON-in/JSON-out signature
- src/error.rs — typed VerbError enum
- tests/verb_smoke.rs — 10/10 green
New _schemas/fragments/ (83 LOC JSON):
- entity-base.json, titled.json, titled-content.json, edge.json
kei-task pilot migration:
- TASK_SCHEMA: EntitySchema static (67 LOC, was 58)
- store.rs becomes thin shim over engine::Store
- atoms/create.rs + atoms/search.rs delegate to engine verbs
- atoms/schemas/*.json use $ref to _schemas/fragments/ (DRY)
- Task-specific secondary tables (milestones, task_deps) stay via
schema.custom_migrations; cycle-detection in deps.rs stays
hand-rolled (domain logic, not generic CRUD)
- 9/9 tests green — full behavioural parity
Convergence delta:
- kei-task touched files: 342 → 389 LOC (+47 for JSON marshalling
boundary; net wash on pilot)
- BUT each remaining 5 sibling crate can shrink ~400-500 LOC on migration
- Expected total reduction when all 6 migrated: ~2500 LOC across the cluster
Follow-ups declared:
- Migrate kei-chat-store, kei-content-store, kei-social-store to engine
- Migrate kei-sage (needs string-id edge variant; currently generic
link/rank assume int ids)
- Migrate kei-crossdomain
- Expose list/delete atoms in kei-task (engine supports, atoms not yet)
- Fold kei-curator as engine::hygiene module (per P4 audit)
- Fold kei-search-core entities, keep workflow as thin kei-search-pipeline
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 04:46:47 +08:00
Parfii-bot
8626e23c22
feat(stream-e): invoke wire — kei-runtime subprocess → real atoms
...
Replace NotImplemented stub with real atom execution per schema
§Runtime invocation contract.
Convention: JSON-in/JSON-out over subprocess. Every refactored crate
exposes `<crate> run-atom <verb>` that reads JSON from stdin (or
--input), dispatches to atoms::<verb>::run, emits Output JSON on
stdout, exits per atom-error class.
Runtime side (kei-runtime):
- InvokeError: +AtomFailed{atom,code,stderr} +SubprocessError
+OutputParse +BinaryNotFound{crate_name}. NotImplemented kept as
legacy escape for atoms opting out of run-atom protocol.
- Output: now {atom: String, result: Value} — carries atom's actual
return value.
- invoke_exit_code: AtomFailed passes through child exit (0..=255),
Subprocess/OutputParse → 1, BinaryNotFound → 127, NotImplemented → 64.
- Binary resolution: KEI_RUNTIME_BIN_DIR env → PATH fallback.
kei-task side:
- New `pub mod run_atom` in lib.rs
- atoms/mod.rs: VERBS const + DispatchError enum wrapping per-atom errors
- src/run_atom.rs: read_input (stdin/@path/literal), dispatch, exit mapping
- main.rs: Cmd::RunAtom{verb, input} subcommand; collapsed three
classify_*_error helpers into single classify_dispatch. Legacy
create/search/add-dependency CLIs preserved.
Tests: 5/5 runtime (+1 invoke_real_atom integration), 9/9 kei-task
(+1 atoms::tests::verbs_list_matches_submodules).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 01:21:00 +08:00
Parfii-bot
1bc6fbf4e3
fix(substrate): E3 — CLI contract compliance (exit codes + invoke Err)
...
Four audit findings on CLI contract violations per locked §Runtime schema:
- crit#7: invoke returned Ok with error payload — now returns
Err(InvokeError::NotImplemented) → exit 64
- crit#5: typed errors collapsed via anyhow::anyhow!("{e}") in kei-task —
replaced with CliError { code, msg } + classify_*_error helpers;
validation errors exit 2, storage errors exit 1 (spec-compliant)
- crit#8: lint.rs wikilink parser accepted [[[foo]] — strict parse_wikilink
from kei-atom-discovery used; emits finding for malformed entries
- crit#15: draft-07 detection was substring match — is_draft07_uri exact
match against canonical URIs only
Tests: 4/4 kei-runtime (was 2; +2 invoke exit-code tests) + 8/8 kei-task
(was 7; +1 empty-title exit-2 test) = 12/12 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:49:49 +08:00
Parfii-bot
ae82bc6242
feat(stream-b): kei-task pilot — 3 atoms (create/search/add-dependency)
...
Pilot refactor per locked substrate schema. kei-task migrated to atom
layout:
- atoms/<verb>.md — YAML frontmatter + human body for 3 verbs
- atoms/schemas/<verb>-{input,output}.json — JSON Schema draft-07
- src/atoms/<verb>.rs — typed Input/Output/Error + pub fn run()
- src/atoms/mod.rs — module registry
- Cargo.toml [package.metadata.keisei] — crate-level substrate data
- src/main.rs — dispatcher for 3 pilot commands via atoms::
Zero behaviour change: 7/7 integration tests pass before and after
(create_and_get, update_persists, cycle_detected, milestone_linking,
dependency_chain_traversal, task_graph_edges, search_finds_task).
main.rs still has 5 non-migrated subcommands (update, graph,
dependency-chain, milestone, link-milestone) — scope discipline, they
migrate in later passes. main.rs 120 → 132 LOC.
Stream B pilot reference — other crates follow this pattern in v0.24+.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:09:55 +08:00
Parfii-bot
81462a03ef
chore(rust): misc schema/main refactor in 8 crates (assorted CP splits)
...
kei-chat-store, kei-content-store, kei-crossdomain, kei-curator, kei-router, kei-sage, kei-search-core, kei-social-store, kei-task — small schema + main refactors for test pass parity (167 Rust tests, 20 assembler).
2026-04-22 13:36:17 +08:00
Parfii-bot
adc007b7b0
feat(primitives): 10 Rust crates extracted from LBM (Genesis-scrubbed)
...
- kei-router — keyword-dispatch meta-tool (CfC ML fallback removed)
- kei-sage — Obsidian-style knowledge graph, FTS5 + BFS + PageRank
- kei-task — task DAG with deps, milestones, dependency-chain queries
- kei-chat-store — Claude conversation session persistence + FTS search
- kei-crossdomain — typed-edge store + BFS cross-domain glue
- kei-search-core — 3-wave deep research with microcent budget cap
- kei-content-store — asset + prompt + campaign registry
- kei-social-store — people + interactions CRM (lite)
- kei-curator — edge-decay graph hygiene utility
- kei-auth — multi-tenant session tokens (replaces single-bearer)
Genesis-scan pre-import pass: skipped pkg/mxl1/*, pkg/inference/*, pkg/trainer/*,
pkg/nc01/*, internal/ml/* (all Genesis/CfC adjacent, sensitive IP).
Security: skipped tools_threat/radio/protocol/med/mlreg (offensive/banned).
Domain verticals skipped: hr/legal/infra/ops/api/osint/edu/geo/hw/finance.
New 'mcp' profile in MANIFEST.toml bundles all 10 for MCP server deployment.
Workspace now 24 crates, cargo check --workspace clean, 94 workspace tests pass.
2026-04-22 12:48:56 +08:00