Commit graph

277 commits

Author SHA1 Message Date
Parfii-bot
c3537f9dd4 docs(schema): REVOKE both schema locks — calendar weeks ≠ actual velocity
Both atom substrate (6-week lock) and agent substrate (3-week lock) were
calibrated for calendar windows that were 30-100× slower than actual
execution. Phases shipped in hours, not weeks. Keeping calendar locks
delays breaking consolidations that can safely ship now.

Unlocks: verb templates, schema fragments, PatternGate, CommandVerify,
role expression, DNA identity — all can ship as breaking changes with
standard review gate (audit + integration tests).

No more calendar-week locks. Future locks: agent-hours or
"until declared phases land."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 04:31:20 +08:00
Parfii-bot
4658297232 Merge feat/convergence-u3-provision — unify hetzner+vultr into Rust crate 2026-04-23 03:43:51 +08:00
Parfii-bot
e557b23809 Merge feat/convergence-u2-renames — capability renames + back-compat aliases 2026-04-23 03:43:51 +08:00
Parfii-bot
bf3e08b891 Merge feat/convergence-u1-blocks — shared blocks + 3 deprecations + /animate 2026-04-23 03:43:51 +08:00
Parfii-bot
64ffe39e01 feat(convergence/u3): kei-provision Rust crate — unify hetzner+vultr provisioners
Pre-unlock wave U3 (highest-ROI). Task 7 from CONVERGENCE-PLAN —
consolidate 2 provision-*.sh scripts into Rust via Backend trait.

Old shells (provision-hetzner.sh, provision-vultr.sh) had identical
6-subcommand surface (create|status|destroy|list), log/die/check_deps
helpers, idempotency contract. Sole delta: hcloud vs vultr-cli. RULE 0.2
says Rust-first when >50 LOC + growth expected.

New crate _primitives/_rust/kei-provision/:
- src/backend.rs (58 LOC) — Backend trait: create/status/destroy/list;
  CreateOpts and ServerInfo structs
- src/backends/hetzner.rs (143 LOC) — shells to `hcloud server ...`
  --output=json, parses JSON response, honors HCLOUD_TOKEN env (RULE 0.8)
- src/backends/vultr.rs (189 LOC) — same pattern, `vultr-cli instance`,
  honors VULTR_API_KEY env
- src/exec.rs (100 LOC) — Command runner + PATH-aware env preservation
- src/b64.rs (49 LOC) — minimal user-data base64 encoder; zero
  transitive deps
- src/main.rs (141 LOC) — clap CLI `kei-provision <backend> <cmd>`
- tests/backend_smoke.rs (184 LOC) — tempdir PATH-inject fake hcloud +
  fake vultr-cli, no real cloud. Mutex-serialized (Rust test parallelism).

Tests: 11/11 (3 b64 unit + 8 backend_smoke integration). Coverage:
hetzner status present/absent/list, vultr status found/absent/destroy
idempotent, unknown-backend error, CreateOpts default.

Old shells kept with superseded-v0.17 header — install.sh still copies
them, legacy scripts still work. New users get kei-provision binary.
harden-base.sh untouched (different lifecycle — runs on target VPS).

Backend trait factored to accept aws/doctl/linode follow-ups without
re-architecture.

Workspace Cargo.toml: +kei-provision member (1 line).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:43:40 +08:00
Parfii-bot
e4b64418fc feat(convergence/u2): capability renames + back-compat aliases
Pre-unlock wave U2. Task 3 from CONVERGENCE-PLAN — rename misleading
capability names, keep old names as deprecated aliases.

Renames:
- tools::read-only → tools::deny-tools (mechanism is tool-name denial,
  not "read-only" metaphor)
- tools::cargo-only-bash → tools::bash-allowlist (mechanism is Bash
  pattern allow-list; cargo-only is one config value)

Back-compat via registry.resolve_alias():
- Old dir _capabilities/tools/{read-only,cargo-only-bash}/ retained with
  capability.toml-only stub: `alias = "<new-name>"` + `deprecated` field
- registry.rs loads alias stubs, redirects lookup before dispatch
- warn_deprecated_once() emits single-shot stderr per alias per process
  via OnceLock<Mutex<HashSet>>
- Zero breaking change to existing manifests / task.toml referencing
  old names

Rust impl files renamed in place:
- gates/tools_read_only.rs → gates/tools_deny_tools.rs (struct
  DenyTools)
- gates/tools_cargo_only_bash.rs → gates/tools_bash_allowlist.rs
  (struct BashAllowlist)
- gates/mod.rs + registry.rs + gate_smoke.rs updated

Roles updated (3): read-only.toml, explorer.toml, edit-local.toml —
reference new names directly.

Tests: kei-agent-runtime 41/41 (was 40, +1 deprecated_aliases_resolve
_to_new_names), _assembler 40/40 unchanged (substrate role expansion
follows new paths).

Docs updated: AGENT-ROLES.md, AGENT-SUBSTRATE-SCHEMA.md, 4 _manifests
referencing the old names (comment-only annotations).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:43:40 +08:00
Parfii-bot
1afb4bafa3 feat(convergence/u1): shared blocks + 3 skill deprecations + /animate gateway
Pre-unlock wave U1. Non-breaking DRY refactor per CONVERGENCE-PLAN tasks 1/2/4/5/6.

Created (5 files):
- _blocks/pipeline-5phase-template.md (54 LOC) — shared preamble for
  ci-scaffold / auth-setup / observability-setup / docs-scaffold /
  schema-design
- _blocks/rule-pure-click-contract.md (42 LOC) — AskUserQuestion
  contract referenced across 5+ skills
- skills/animate/SKILL.md (67 LOC) — gateway router; AskUserQuestion
  picks scroll / motion / web-effects / ai-animation, hands off to
  picked skill
- skills/competitor-analysis/SKILL.md (35 LOC) — redirect stub to
  /research --angle=competitors (did not exist; stub documents the
  preset path per RULE -1 Constructive)
- skills/design-inspiration/SKILL.md (38 LOC) — same pattern,
  --angle=design-refs

Deprecation headers added (3 skills):
- skills/site-builder/SKILL.md → "use /site-create" (subset)
- skills/competitor-analysis/SKILL.md → preset stub
- skills/design-inspiration/SKILL.md → preset stub

Reference blocks added (5 pipeline skills):
- skills/ci-scaffold, auth-setup, observability-setup, docs-scaffold,
  schema-design — each +4 LOC pointer to pipeline-5phase-template.md
- skills/research — +18 LOC --angle presets table

LOC saved via shared blocks: ~96

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:43:40 +08:00
Parfii-bot
9732060788 Merge feat/convergence-plan — 75→52 consolidation roadmap 2026-04-23 03:28:39 +08:00
Parfii-bot
0b47616b06 docs(convergence): synthesis of 2 audit waves — 75 → ~52 primitives plan
User hypothesis: "if substrate is right, primitives converge, not expand".
Directional yes, magnitude calibrated below initial guess (75→35).
Reality: 75 → ~52 (−31%) across atoms + capabilities + skills.

Atoms (25 → 15-17):
- 6 SQLite-CRUD → 1 kei-entity-store + 6 plugins (piggyback Stream B)
- 3 provisioners → 1 kei-provision <backend> (harden-base stays)
- 4 frontend → meta-dispatcher shim

Capabilities (11 → 7):
- scope::files-{whitelist,denylist} → scope::path-filter (post-unlock)
- quality::cargo-{check,tests}-green → quality::cargo-green (post-unlock)
- Kept separate (justified): output::*, tools::*, policy::*
- Rename cargo-only-bash → bash-allowlist (pre-unlock, non-breaking)

Skills (39 → ~28):
- /audit <target> + checklists registry (6 skills → 1 + 6 data files)
- Deprecate /site-builder, /competitor-analysis, /design-inspiration
- Add /animate gateway (keep 4 motion-family skills underneath)
- Setup pipelines (ci/auth/obs/docs/schema) stay separate — domain-disjoint

Three techniques catalogued:
1. Verb parameterization (>50% LOC overlap)
2. Block extraction (shared preamble, different body)
3. Subset deprecation (one is proper subset of another)

Execution 3-phase:
- Pre-unlock (ship NOW): 7 tasks, ~3 days parallel — block extraction +
  renames + deprecations + provisioner unification
- Mid-cycle (parallel Stream B): 2-3 days — entity-store engine
- Post-unlock (after 2026-06-03): 4 tasks, ~5-6 days — schema amendments

Honest gaps from both audits:
- 4 of 10 LBM-port crates not enumerated (follow-up)
- _capabilities/*.md not directly read by critic (manifest-inferred)
- LOC estimates ±20%
- Both audits E2-E4, not E1 (which requires running the consolidation)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:28:39 +08:00
Parfii-bot
6d6191fd13 Merge feat/orchestrator-wrapper — prepare CLI for ergonomic Agent spawn 2026-04-23 03:25:14 +08:00
Parfii-bot
d72ae51f16 feat(agent-substrate/wrapper): kei-agent-runtime prepare — orchestrator ergonomics
Single-command "prepare spawn" that emits everything orchestrator needs
to invoke the Agent tool: composed prompt, subagent_type (from role's
new claude-subagent-type field), isolation mode, verify command,
ledger row.

Before this: orchestrator ran compose + read prompt + manually
constructed Agent tool call + manually built verify command. 4 steps.

After: `kei-agent-runtime prepare <task.toml> --format=human` outputs
a single copy-paste-ready block. Orchestrator pastes into Agent tool
and records the verify command for return.

Files:
- src/prepare.rs (170 LOC) — prepare() returns AgentInvocation struct
  (agent_id, prompt, subagent_type, isolation, description,
  verify_command, ledger_row)
- src/main.rs (+39 LOC) — Prepare subcommand with --format=human|json|toml
- src/lib.rs (+2 LOC — pub mod prepare)
- _roles/*.toml (5 files) — new optional claude-subagent-type field:
  - edit-local / edit-shared → "code-implementer"
  - read-only → "critic" (default; "architect" override possible)
  - explorer → "Explore"
  - git-ops → "NOT-SPAWNABLE" (refused by prepare with RULE 0.13)
- tests/prepare_smoke.rs (3 tests) — happy path, unknown role, non-spawnable refusal
- docs/AGENT-SUBSTRATE-SCHEMA.md (+ ## Orchestrator ergonomics section)

Tests: 40/40 (was 37, +3 prepare_smoke). Same path exercised in tempfile
fixtures that the real CLI would hit end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:25:14 +08:00
Parfii-bot
abf2bcb30d Merge feat/phase-5-agent-migration — substrate v1 FULL (5 agents migrated) 2026-04-23 03:07:18 +08:00
Parfii-bot
329d7e2a4d feat(agent-substrate/phase-5): migrate 5 kit agents to role+task-spec — substrate v1 FULL
Final phase of agent substrate v1. 5 shipped agents now declare role at
manifest level; assembler expands role's capability text fragments into
the generated .md at a new `# AGENT SUBSTRATE — role <name>` section.
Non-migrated agents byte-identical (golden snapshots green).

Migrated agents:
- kei-code-implementer → edit-local (8 caps: no-git-ops + scope/* +
  quality/* + safety::no-dep-bump + report-format)
- kei-critic → read-only (tools::read-only + output::report-format +
  output::severity-grade)
- kei-architect → read-only
- kei-security-auditor → read-only
- kei-validator → read-only

_assembler/ extensions:
- manifest.rs: substrate_role: Option<String>
- assembler.rs: write_substrate() before blocks (backward-compat; no
  role = no substrate section)
- substrate.rs (new, 102 LOC): loads _roles/<name>.toml, iterates
  capabilities.required, reads _capabilities/<cat>/<slug>/text.md,
  joins with \n\n---\n\n separator
- validator.rs: substrate role existence + cap-text presence check
- tests/substrate_role.rs (4 tests): happy path, unknown role, missing
  capability text, byte-parity on non-migrated
- tests/regenerate_migrated.rs (ignored by default): regeneration gate

_templates/task-examples/ — 5 example task.toml per migrated agent
showing orchestrator the valid invocation shape.

docs/AGENT-SUBSTRATE-SCHEMA.md: Phase 5 row ticked ✓ + Migrated agents
subsection listing 5 agents with roles + pointer to examples.

tests/substrate_integration.sh: +8 Phase-5 assertions
- All 5 migrated .md files contain "# AGENT SUBSTRATE — role"
- kei-code-implementer.md contains "MUST NOT invoke git" (policy::no-git-ops)
- Every _templates/task-examples/*.toml parses as valid TOML
- cargo check --workspace still passes post-migration
- kei-agent-runtime compose works on edit-local-forge.toml example

Tests: assembler 40/40 (was 30, +4 substrate_role + +1 ignored regen),
kei-agent-runtime + kei-capability 37/37 preserved.

Deferred: remaining 7 non-core agents (cost-guardian, modal-runner,
fal-ai-runner, infra/ml-implementer, ml-researcher, researcher) migrate
in v0.24 wave.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 03:07:18 +08:00
Parfii-bot
bd32b48a54 Merge feat/phase-4-hook-wiring — PreToolUse glue for kei-capability 2026-04-23 02:51:11 +08:00
Parfii-bot
aa8333ccda feat(agent-substrate/phase-4): hook wiring — 3-line glue for kei-capability
PreToolUse hooks route through kei-capability check when orchestrator
registers a capability via KEI_CAPABILITY_NAME env var on agent spawn.

hooks/agent-capability-check.sh (22 LOC):
- Pass-through (exit 0) when KEI_CAPABILITY_NAME unset — no-op by default
- Fail-open (exit 0) when kei-capability binary missing — kit convention
- Sources _lib/gate.sh for KEI_DISABLED_HOOKS / KEI_HOOK_PROFILE respect
- exec kei-capability check "$CAP_NAME" when active

hooks/agent-capability-verify.sh (24 LOC):
- Orchestrator-driven, NOT a Claude Code native hook
- Carries env: AGENT_ID, TASK_TOML, WORKTREE_PATH, MAIN_REPO, RUN_MODE
- exec kei-capability verify "$CAP_NAME"

Registered in hooks/hooks.json + settings-snippet.json under both
PreToolUse:Bash and PreToolUse:Edit|Write matchers. Internal NotApplicable
returns exit 0 so non-matching tool calls cost nothing.

install.sh unchanged — hooks/*.sh glob picks up both new files.

tests/hook_wiring_integration.sh (64 LOC) — 3 contract assertions:
  (1) pass-through on unset KEI_CAPABILITY_NAME
  (2) deny+exit 2 on git-op pattern
  (3) allow+exit 0 on cargo-check pattern

Multi-capability routing (for phase 5): KEI_CAPABILITY_NAME currently
holds ONE name. When a role requires N capabilities, orchestrator will
either iterate or kei-capability gains a compose subcommand. Design
note left for phase 5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 02:51:10 +08:00
Parfii-bot
d1a1a7d499 Merge github/main — readme rewrite lands alongside agent substrate v1 phases 1/2/3 2026-04-23 02:44:18 +08:00
Parfii-bot
28707a9a4a Merge feat/phase-3-kei-agent-runtime — substrate runtime + kei-capability 2026-04-23 02:36:16 +08:00
Parfii-bot
12e5c27b3c Merge feat/phase-2-role-matrix — 5 roles + AGENT-ROLES.md 2026-04-23 02:36:16 +08:00
Parfii-bot
a7b3e39fa8 Merge feat/phase-1-capability-library — 11 capability bundles 2026-04-23 02:36:16 +08:00
Parfii-bot
b82e3b039e feat(agent-substrate/phase-3): kei-agent-runtime + kei-capability binaries
Two new crates implementing the substrate runtime per locked §Runtime
execution contract + §Capability trait contract (Rust) + §Verify
execution worktree→simulated-merge.

kei-agent-runtime — library + CLI binary:
- src/capability.rs — Capability trait (name/check/verify) + GateContext
  + GateDecision + VerifyContext + VerifyResult + RunMode + TaskSpec
- src/registry.rs — &str → &'static dyn Capability dispatch for 14 impls
- src/gates/ — 6 PreToolUse modules (policy::no-git-ops,
  scope::files-{whitelist,denylist}, safety::no-dep-bump,
  tools::read-only, tools::cargo-only-bash)
- src/verifies/ — 8 on-return modules (quality::constructor-pattern,
  quality::cargo-check-green, quality::tests-green, safety::no-dep-bump,
  scope::files-{whitelist,denylist}, output::{report-format,severity-grade})
- src/compose.rs — task.toml + role + capabilities → prompt.md
- src/spawn.rs — ledger fork + prompt write (actual Agent invocation
  remains orchestrator's tool call)
- src/verify.rs — runs all capability verifies per role; collects
  VerifyReport {passed, failed}
- src/simulated_merge.rs — git worktree add test-merge/<id> + apply diff
  + run verify; cleanup on Drop
- src/main.rs — clap CLI: compose | spawn | verify | run

kei-capability — thin CLI adapter crate:
- Depends on kei-agent-runtime path dep
- Subcommand `check <cap-name>` (PreToolUse gate; stdin JSON, exit 0|2)
- Subcommand `verify <cap-name>` (on-return; env-driven, exit 0 or fail)
- Pattern: shell hook = 3-line `exec kei-capability check "$CAP_NAME"`

Workspace Cargo.toml: both crates registered as members (under agent
substrate v1 marker).

cargo check --workspace: PASS
cargo test -p kei-agent-runtime: 37/37 green
  - 6 capability_trait_smoke (registry lookups, unknown name → None)
  - 3 compose_smoke (fixture role + caps → composed prompt)
  - 12 gate_smoke (each gate: happy + deny + bypass)
  - 4 simulated_merge_smoke (git worktree lifecycle)
  - 12 verify_smoke (each verify: pass + fail + edge cases)
cargo test -p kei-capability: 0/0 (CLI binary, tested via lib)

(Agent completion report cut off by rate-limit at 60 tool-uses; code
itself is green — verified by orchestrator post-commit.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 02:35:53 +08:00
Parfii-bot
dc83cb2117 feat(agent-substrate/phase-2): role matrix — 5 roles + AGENT-ROLES.md
5 _roles/*.toml per locked §Initial role inventory:

- read-only     → tools::read-only + output::report-format + severity-grade
- explorer      → read-only caps + tools::cargo-only-bash
- edit-local    → no-git-ops + scope::files-{white,deny}list + quality::*
                  + safety::no-dep-bump + output::report-format
- edit-shared   → edit-local caps + relaxed SSoT whitelist (task-time param)
                  + escalation tightened to orchestrator-notify
- git-ops       → spawnable = false, documentation-only

All 11 capability names referenced match phase-1 deliverable path
_capabilities/<cat>/<slug>/ (cross-ref verified before commit).

docs/AGENT-ROLES.md (223 LOC) — human-readable matrix: per-role sections
+ cross-role capability matrix + explicit non-spawnable-git-ops block.

Drift note for orchestrator integration review: edit-local/edit-shared
use inline bash-patterns-allowed = ['^cargo( |$)', '^mkdir( |$)',
'^rm -rf /tmp/'] instead of composing with tools::cargo-only-bash
capability (extra patterns not in that atom). Agent footnoted —
resolution deferred to post-integration (either parameterize the cap
or introduce tools::cargo-plus-basic-bash variant).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 02:35:52 +08:00
Parfii-bot
c0c3483f02 feat(agent-substrate/phase-1): capability library — 11 declarative bundles
22 files per locked §Initial capability atom inventory:

policy/no-git-ops/               (gate: PreToolUse:Bash, bypass ORCHESTRATOR_META)
scope/files-whitelist/           (gate + verify worktree)
scope/files-denylist/            (gate + verify worktree)
quality/constructor-pattern/     (verify worktree)
quality/cargo-check-green/       (verify both — worktree short-circuit + simulated-merge)
quality/tests-green/             (verify both)
safety/no-dep-bump/              (gate + verify both)
output/report-format/            (verify worktree)
output/severity-grade/           (verify worktree)
tools/read-only/                 (gate: deny Edit/Write)
tools/cargo-only-bash/           (gate: Bash allowlist)

All capability.toml share [capability]/[restricts]/[parameterized]/[text]/
[gate]/[verify] section layout. rust-module paths pre-wired to match
phase-3 file layout. All text.md under 200 words, imperative,
self-contained (composer concatenates with --- separator).

Cross-refs to rule files preserved:
- policy::no-git-ops → RULE 0.13 (orchestrator-branch-first.md)
- quality::constructor-pattern → RULE ZERO (code-style.md)
- output::severity-grade → debugging.md §Security Review
- safety::no-dep-bump → supply-chain rationale

Agent attempted wc -w for word counts — sandbox correctly denied Bash
per RULE 0.13, observable reinforcement of the very policy this
capability encodes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 02:35:52 +08:00
annaglova
c859df8d37 docs(readme): outcome-oriented rewrite — hero + features + hide complexity under the hood
Refocuses README from defensive ("here's what LLMs do wrong, here's how we fence it")
to welcoming ("here's what you get, install is one line, complexity lives under the
hood"). Same factual content, same feature count, reorganized for new visitors.

Key changes:
- Hero opens with user outcome, not LLM failure modes
- Install moved to 2nd block (was buried mid-README)
- Features rewritten as scenarios ("Your AI sleeps at night") not specs
- "Batteries included" frames counts as confidence signal, not overwhelm
- "Under the hood (only if you care)" explicitly optional section for devs
- "About" confident — 4-8 parallel terminals flex, not self-deprecation

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 21:23:23 +03:00
Parfii-bot
b8b9c12913 Merge feat/agent-substrate-schema — agent substrate v1 LOCKED 2026-04-23 02:05:21 +08:00
Parfii-bot
a25c282dca feat(agent-substrate): LOCK schema — 8 decisions resolved, 3-phase parallel window opens
Resolved per user review 2026-04-23:

- Layout: declarative (capability.toml + text.md) + Rust modules in
  kei-agent-runtime (not 3 bash files — user pushed for Rust)
- Gate: Rust via kei-capability binary, shell hook = 3-line exec glue
- Verify: Rust same binary, subcommand verify
- Config: TOML (user asked discount between TOML vs YAML — explained
  type-safety + Cargo-native parsing wins)
- Capability ID: :: separator (confirmed)
- Nested path layout
- 200 words/capability text cap
- Verify: worktree short-circuit → simulated-merge (catches
  E1-jsonschema-class integration regressions before main merge)

Phase 3 revised up from 3-4 days to 5-6 due to Rust gate/verify logic
+ simulated-merge executor. Offset by phase 4 dropping from 1 day to
0.5 (shell hooks now thin glue).

3 phases parallelizable immediately after this lock:
- Phase 1: 20 declarative files (capability.toml + text.md × 10)
- Phase 2: 5 role TOML + docs/AGENT-ROLES.md
- Phase 3: kei-agent-runtime + kei-capability binaries + 14 Rust capability modules

Phase 4 + 5 sequential after.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 02:05:21 +08:00
Parfii-bot
372bbc8320 docs(agent-substrate): v1 schema DRAFT — capability triplet + role + task spec + runtime contract
Sibling SSoT to SUBSTRATE-SCHEMA.md (atom substrate). This one decomposes
agent invocations rather than code primitives.

Core contribution — the capability TRIPLET, not just text:
- text.md      — what agent reads (prompt fragment)
- gate.sh      — PreToolUse hook (runtime enforcement)
- verify.sh    — on-return predicate run from main repo (not worktree)

Motivation from substrate v1 orchestration audit:
- 40% prompt boilerplate across 7 spawns (git-ban + constructor-pattern +
  report format etc. copy-pasted each time)
- Self-reported green tests broke at integration (E1 jsonschema
  regression — agent claimed PASS from worktree but main workspace
  failed; caught only by integration test)
- Scope violations (E1 touched invoke.rs when E3 was supposed to own it;
  surfaced only at merge)

Triplet closes all three gaps: capabilities aren't promises agents make
in prose, they're enforced by gate hooks pre-exec and verified by
predicates on return from main branch clean state.

Schema specifies:
- Capability atom layout: _capabilities/<category>/<slug>/
- capability.toml frontmatter shape
- text.md / gate.sh / verify.sh contracts
- Role = bundle of capabilities (5 roles: read-only, explorer, edit-local,
  edit-shared, git-ops)
- task.toml shape (orchestrator-written per spawn; parameterizes roles)
- kei-agent-runtime crate contract: compose + spawn + verify + run
- Initial 10-capability inventory for phase 1
- 6-question decision log with defaults
- 5-phase parallel build plan (phases 1-4 parallel, ~5-7 days wall time)

Open questions flagged at bottom for review before AGENT-SCHEMA-LOCKED.md.

Once locked: sibling SSoTs (atoms + agents) evolve symmetrically — agents
compose atoms, atoms compose agents (ultimate goal).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 01:39:23 +08:00
Parfii-bot
59fd1a0362 test(substrate): integration now asserts real atom execution via Stream E
Previously expected NotImplemented stub (exit 64). Stream E wired real
subprocess exec to kei-task, so invoke now actually creates tasks.
Updated test:
- Builds kei-task in release + passes KEI_RUNTIME_BIN_DIR + KEI_TASK_DB
- Asserts exit 0 + stdout has 'id' field
- NEW assertion: invoke with empty KEI_RUNTIME_BIN_DIR → exit 127 (BinaryNotFound)
- Bad-input assertion stays (InputInvalid → exit 2)

4 end-to-end assertions now cover the full §Runtime contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 01:23:05 +08:00
Parfii-bot
07b47dba7e Merge feat/stream-g-sage-rules — atoms+rules unified graph 2026-04-23 01:21:12 +08:00
Parfii-bot
7fb562cfc5 Merge feat/stream-f-forge-pure-rust — eliminate shell-out 2026-04-23 01:21:12 +08:00
Parfii-bot
082b4c09e3 Merge feat/stream-e-invoke-wire — kei-runtime subprocess → real atoms 2026-04-23 01:21:12 +08:00
Parfii-bot
15bf40196b feat(stream-g): kei-sage rules integration — atoms + rules unified graph
Unify atoms and rules in kei-sage's graph. Previously [[rules/...]]
wikilinks were filtered (explicit Stream C scope-deferral). Now they
resolve to rule-node units with rule_ref edges.

kei-atom-discovery extension (non-breaking):
- WikilinkTarget enum: Atom(String) | Rule(String) | Other(String)
- classify_wikilink(inner: &str) -> WikilinkTarget — exposed via lib.rs
- parse_wikilink unchanged for backwards-compat; new callers use
  classify for richer semantics

kei-sage additions:
- rule_index.rs (129 LOC) — RuleRecord + discover_rules walking flat
  *.md + extract_h1 for display name + index_rules (unit_type="rule",
  vault_path="rule:<slug>") + index_rule_edges (walks atom.related,
  emits rule_ref edges atom → rule node)
- atom_cli.rs: cmd_rules_discover + default_rules_root
- main.rs: AtomsRulesDiscover subcommand with --rules-root flag
- tests/rules_smoke.rs: 5 tests (discovery, heading extraction,
  slug fallback for headingless files, empty-dir, atom→rule edge
  persistence)

Tests: 12/12 kei-atom-discovery (+3 classify_wikilink),
28/28 kei-sage (+5 rules_smoke + unit tests now counted).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 01:21:00 +08:00
Parfii-bot
e84e9fc1fe feat(stream-f): kei-forge pure-Rust templating — eliminate shell-out
Remove std::process::Command invocation of scripts/new-atom.sh from
kei-forge. Templating moves to pure Rust — eliminates the
sed-metacharacter injection class structurally, on top of the
description whitelist that E2 added as defence-in-depth.

src/generate.rs split into 4 Cubes (Constructor Pattern):
- generate/placeholders.rs — 6-token substitution, longer-first ordering
- generate/paths.rs — TargetPaths::resolve + assert_none_exist
- generate/rollback.rs — Drop-based atomic rollback (Rust idiom for
  shell `trap ERR`)
- generate/atom_tests.rs — 5 tempdir integration tests

generate.rs dropped from 295 → 159 LOC as orchestration thin wrapper.

Behavioural parity with scripts/new-atom.sh maintained: same 6 tokens,
same order, refuse-overwrite, atomic rollback, same file-list
ordering. scripts/new-atom.sh untouched on disk (still usable as
standalone CLI).

Cargo.toml: removed mock-generate feature flag (no longer needed —
pure-Rust tests use tempfile::TempDir), added tempfile dev-dep.

Tests: 44/44 (was 29 with mock-generate; +15 new pure-Rust unit tests
across placeholders/paths/rollback/atom_tests).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 01:21:00 +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
9307f8d26e Merge fix/audit-wave-substrate-v1 — security hardening + CLI contract + integration test 2026-04-23 00:56:41 +08:00
Parfii-bot
f7e4725573 fix(substrate): amendment A-1 (input/output required all kinds) + integration test + jsonschema 0.18 relative-$id bug
Three post-E1/E2/E3-merge items:

1. Schema amendment A-1 (architect P0-a, non-breaking clarification):
   input.schema and output.schema are REQUIRED for all atom kinds. The
   shared kei-atom-discovery parses them as Option<PathBuf> only to allow
   tolerant skip-on-missing (stderr warn), not to permit absent schemas.
   Resolves Stream C / Stream D enforcement asymmetry documented in
   critic finding #6.

2. Cross-stream integration test (architect P0-b): tests/substrate_integration.sh
   builds release binaries, scaffolds a test atom corpus, runs
   schema-lint + list-atoms + atoms-discover + invoke; asserts all four
   streams agree on the same atom corpus and exit codes honour the
   locked §Runtime contract. Previously missing — only manual smoke
   checks existed.

3. Fix regression introduced by E1's jsonschema 0.18 upgrade:
   "relative URL without a base" on compile when schema declared a
   relative $id like "kei-task/atoms/schemas/create-input.json".
   validate.rs now synthesises an absolute file:// $id from the
   canonicalised schema path before compile. Internal $refs still
   resolve relative to the schema file; LocalFileResolver still confines
   to the schema's parent dir. Integration test catches this.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:56:27 +08:00
Parfii-bot
ca0635e0fa Merge fix/e3-contract-compliance — exit codes + invoke Err + strict lint
# Conflicts:
#	_primitives/_rust/kei-runtime/src/invoke.rs
2026-04-23 00:52:54 +08:00
Parfii-bot
4e9a7dddfb Merge fix/e2-kei-forge-hardening — DNS/CSRF/injection + headers 2026-04-23 00:49:59 +08:00
Parfii-bot
f1a6098aa9 Merge fix/e1-atom-discovery — shared crate + SSRF/traversal/YAML fixes 2026-04-23 00:49:59 +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
f7982f0415 fix(substrate): E2 — kei-forge security hardening (DNS rebind + CSRF + injection)
Three HIGH security findings resolved in _primitives/_rust/kei-forge/:

- F-1: DNS rebinding — require_local_host middleware returns 421 on
  non-localhost Host headers
- F-2: CSRF via urlencoded — require_json_content_type middleware
  returns 415 on non-JSON; form HTML now POSTs JSON via fetch()
- crit#1/SA F-7: description sed injection — whitelist validator rejects
  newline/CR/tab/NUL/backtick/$/length>200, blocks the shell-script attack
  at the Rust layer
- crit#11: missing security headers — CSP, X-Frame-Options DENY,
  X-Content-Type-Options nosniff, Referrer-Policy no-referrer on GET /

Zero new deps (axum 0.7 middleware::from_fn + HeaderMap native).
Constructor Pattern compliant — 6 Cube files, largest 231 LOC including tests.

Tests: 29/29 (was 12/12; +17 new). Includes 4 adversarial integration
tests for each defence layer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:49:49 +08:00
Parfii-bot
990f5e3711 fix(substrate): E1 — kei-atom-discovery shared crate + 4 critical security fixes
Extracts authoritative atom discovery + frontmatter parsing into new crate
_primitives/_rust/kei-atom-discovery/. kei-sage and kei-runtime now both
consume the same implementation, eliminating Frontmatter drift.

Resolved findings:
- F-3/crit#3: path traversal via md_dir.join() — safe_join helper rejects
  absolute paths + .. components + post-canonicalise escapes (4 sites)
- crit#6/architect P0-a: Frontmatter drift — single AtomMeta struct
- SA supply-chain: serde_yaml archived — migrated to serde_yaml_ng 0.10
- crit#2: JSON Schema $ref SSRF — jsonschema 0.17→0.18 with resolve-file
  feature only, custom LocalFileResolver denies non-file:// schemes
- F-4: symlink traversal — walkdir follow_links(false) explicit everywhere
- F-5: YAML billion-laughs — 64 KiB pre-parse cap

Tests: 9/9 new crate + 23/23 sage + 2/2 runtime + 7/7 kei-task = 41/41 green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:49:49 +08:00
Parfii-bot
42fe08232e Merge feat/stream-d-kei-runtime — invoke/list-atoms/schema-lint MVP
# Conflicts:
#	_primitives/_rust/Cargo.lock
#	_primitives/_rust/Cargo.toml
2026-04-23 00:13:16 +08:00
Parfii-bot
2361a21d15 Merge feat/stream-c-kei-sage-substrate — kei-sage walks atoms/*.md 2026-04-23 00:10:44 +08:00
Parfii-bot
ef48c9993b Merge feat/stream-b-atoms-kei-task — 3 pilot atoms per locked schema 2026-04-23 00:10:44 +08:00
Parfii-bot
9858662b72 Merge feat/stream-a-kei-forge — local web wizard scaffolding atoms 2026-04-23 00:10:44 +08:00
Parfii-bot
d68fddb59a feat(stream-d): kei-runtime — discover + validate + lint (invoke stub)
New crate _primitives/_rust/kei-runtime/ implementing §Runtime invocation
contract from locked substrate schema.

CLI (clap-derive):
- list-atoms [--root] [--crate] [--kind]   → walk + print
- invoke <atom-id> --input <json|@file>    → discover + validate input (stub exec)
- schema-lint [--root] [--crate]           → 6-check validator
- pipe <dag.toml>                          → "not yet implemented" stub

Modules (≤ 200 LOC each, largest lint.rs @ 171):
- src/discover.rs — walk_atoms walks <root>/*/atoms/*.md, parses frontmatter
- src/validate.rs — JSONSchema draft-07 via jsonschema 0.17.1
- src/invoke.rs — MVP stub: discover → parse → validate_input → boundary ack
- src/lint.rs — 6 checks: required fields, kind enum, side_effects shape,
  schema path existence + draft-07 declaration, wikilink resolution
- src/main.rs — clap CLI, exit 0|1|2 per §Runtime contract

Intentional stub boundary: invoke returns structured JSON ack (exit 0),
wire-up to concrete atom impls deferred to integration pass (needs
Stream B atoms landed first).

Registered kei-runtime in workspace members.

Tests: 2/2 integration smoke (lint_smoke, discover_smoke) green.

Stream D of substrate v1 parallel build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:09:58 +08:00
Parfii-bot
57b9475e50 feat(stream-c): kei-sage substrate — walk atoms/*.md + wikilink graph
Extends kei-sage with substrate-atom indexing layer per locked schema
§Graph / discovery contract.

New modules (all ≤ 200 LOC, Constructor Pattern):
- src/atom_parse.rs — frontmatter splitter, wikilink parser, id splitter
- src/atoms.rs — AtomKind + FromStr, AtomRecord, discover_atoms, resolve_wikilinks
- src/atom_index.rs — persists atoms as Units + atom_related edges into existing Store
- src/atom_cli.rs — 4 subcommand handlers

New CLI subcommands (default root ~/.claude/agents/_primitives/_rust):
- atoms-discover — walks atoms/*.md, prints table
- atoms-rank — PageRank over wikilink edges (composes w/ existing vault)
- atoms-related <atom-id> — BFS from atom
- atoms-search <query> — FTS over frontmatter + body

Tolerant scan: invalid frontmatter → stderr warn + continue (never abort).
[[rules/...]] wikilinks filtered at edge resolution per scope (rules
integration deferred to follow-up).

Tests: 9 unit + 6 integration smoke + 8 pre-existing = 23/23 green.
Zero regression. Single new dep: serde_yaml 0.9.

Stream C of substrate v1 parallel build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:09:57 +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
fd25c3af60 feat(stream-a): kei-forge MVP — local web wizard scaffolding atoms
New crate _primitives/_rust/kei-forge/ exposing POST /forge over axum
on 127.0.0.1:8747. Shell-outs to scripts/new-atom.sh for generation.
5-input inline HTML form, no JS required. 9 unit + 3 integration tests
green via `cargo test --features mock-generate`.

Registered kei-forge in workspace members.

Stream A of substrate v1 parallel build — see docs/SUBSTRATE-SCHEMA.md.
Spec pre-locked; schema immutable until 2026-06-03 or revocation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 00:09:53 +08:00
Parfii-bot
9f6ba0cbfc Merge feat/substrate-schema-v1 — substrate schema v1 locked + template + generator 2026-04-23 00:00:33 +08:00