diff --git a/notes/passepartout-neurosymbolic-design-decisions-and-options.org b/notes/passepartout-neurosymbolic-design-decisions-and-options.org index ed14f80..ee8608f 100644 --- a/notes/passepartout-neurosymbolic-design-decisions-and-options.org +++ b/notes/passepartout-neurosymbolic-design-decisions-and-options.org @@ -1,1795 +1,24 @@ -#+TITLE: Passepartout Neurosymbolic Engine — Design Decisions and Architecture Options +#+TITLE: Passepartout Neurosymbolic Engine — Design Decisions — SUPERSEDED #+AUTHOR: Agent -#+FILETAGS: :notes:design-decisions:neurosymbolic:architecture:v3.0.0: +#+FILETAGS: :notes:design-decisions:neurosymbolic:superseded: #+CREATED: [2026-05-08 Fri] - -* The Hallucination Problem — Why Neurosymbolic - -An LLM is a statistical engine trained on token sequences. It generates the most -probable continuation of a prompt. Given sufficient context, that continuation is -correct. Given novel context, it is often wrong in confident-sounding ways. - -This is not a training deficiency. Hallucination is a fundamental property of -probabilistic inference. You can reduce it with better models, longer contexts, -and clever prompting, but you cannot eliminate it by making the LLM better. You -eliminate it by not asking the LLM to do things that require certainty. - -This is the architectural bet at the heart of Passepartout's neurosymbolic design. -The LLM should not be the reasoning engine. It should be the *creative* engine — -proposing possibilities, surfacing connections, translating between natural -language and formal representation. The *reasoning* engine should be symbolic: -deterministic, verification-grounded, provenance-tracked, and incapable of -hallucination by construction. - -This is not a rejection of neural methods. It is a division of labor. The neuro -is the brain — generative, associative, creative, comfortable with ambiguity. It -produces hypotheses. The symbolic engine is the education — accumulated, verified, -provenance-tracked knowledge that the brain draws on and is disciplined by. It -doesn't think. It remembers, checks, and constrains. - -The brain is always smarter than the education, but the education prevents the -brain from being confidently wrong. - -** See also: - -- =passepartout/docs/DESIGN_DECISIONS.org=: "The Probabilistic-Deterministic Split" - for the gate-level version of this argument. -- =notes/passepartout-whitehead.org=: Whitehead's ramified theory of types as - the structural guarantee against self-referential contradictions. -- =notes/passepartout-symbolic-engine-exploration.org=: the full design space and - the lossiness problem at the neural-symbolic boundary. - -* The Five Architecture Options - -The symbolic engine must relate to the human memex. The relationship is not -obvious because knowledge lives in two incompatible forms: natural language -prose (what the human reads and writes) and formal facts (what the symbolic -engine reasons about). The translation between them is lossy by nature. The -architecture is defined by how it handles that lossiness. - -=notes/passepartout-symbolic-engine-exploration.org= explores five options. They are -summarized here to make subsequent decisions legible. - -** Option 1: The Auto-Formalizer - -A separate knowledge graph stores symbolic facts. The LLM populates it by -extracting triples from unstructured data — documentation, manuals, logs, -session histories. The KG becomes co-authoritative with the human prose. - -This is the simplest to implement but inherits the dual-representation problem -in its most acute form. The KG and the prose can disagree, and the architecture -provides no mechanism for resolving disagreements. It also stores knowledge -twice — once in the user's Org files, once in the KG — with no guarantee that -they stay synchronized. - -** Option 2: Two Intentionally Separate Memexes - -The human memex contains prose: thoughts, diaries, decisions, documentation. -The symbolic memex contains formal facts: constraints, rules, relationships, -deductions. The archivist bridges between them but does not try to keep them -synchronized. They are allowed to diverge because they serve different purposes. -The prose captures what the human intended. The symbolic memex captures what -the symbolic engine has proven. - -This is philosophically honest — it admits that no lossless translation between -natural language and formal logic is possible. But it forces the user to reason -about two separate knowledge stores and understand when to trust each. - -** Option 3: Tangled Fact Blocks in Org Files - -The tangle mechanism already handles the dual-representation problem for code. -Lisp code lives in literate blocks within Org files (=#+begin_src lisp=). The -tangle mechanism extracts these blocks and generates =.lisp= files. A new block -type — =#+begin_src knowledge= — would contain symbolic facts in a formal -language. The tangle mechanism would load these facts into the symbolic engine's -in-memory store, just as it loads Lisp code into the SBCL image. - -This is aesthetically appealing because it unifies the format. One toolchain, -one version control system, one Merkle tree. But the block language itself IS -the knowledge representation language, and that language is the ontology we -have not yet defined. The format is unified but the content is unspecified. - -** Option 4: One Memex, Two Indices - -The prose remains in human language in Org files. The prose is always the ground -truth. Two indices sit on top of the prose as derived views: - -- The *neural index* uses vector embeddings to enable semantic search. The LLM - navigates the prose through embedding space, retrieving relevant headings. -- The *symbolic index* stores formal assertions about what the prose says — - predicates, relations, constraints — each grounded to a specific heading or - block in the Org file. - -Each index serves its own side of the machine. They do not need to understand -each other's representations. They only need to agree on which heading or block -they are referring to. Because the prose is always the ground truth, the symbolic -index can be thrown away and rebuilt from scratch if it becomes corrupted or -stale. No information is lost — only the extracted assertions. - -** Option 5: Ephemeral Symbolic Facts - -No persistence, no serialization format, no knowledge graph stored on disk. -VivaceGraph exists in memory during the session. Screamer derives facts from the -prose as needed. When the session ends, the facts are discarded and re-derived -from the prose on the next start. - -This punts the ontological design problem entirely. You never have to decide on -a serialization format because you never serialize. The cost is compute -(re-derivation on every restart) and the inability to accumulate facts across -sessions. But it is the correct first step — a way to learn what kinds of facts -are actually useful before committing to a storage format. - -* The Chosen Path: Option 4, Starting with Option 5 - -The one-memex-two-indices architecture (Option 4) is the correct long-term -architecture. The prose is the ground truth. The symbolic index is a derived -view that can be rebuilt. The neural index handles what the symbolic index -cannot — semantic search, fuzzy matching, associative leaps. - -But committing to a persistence format before knowing what facts are useful -is premature. The practical path starts with Option 5 (ephemeral facts) as the -Phase 1-4 implementation, then graduates to Option 4 with VivaceGraph -persistence in Phase 5 when the fact language has been battle-tested (=see -=passepartout-neurosymbolic-roadmap.org=). - -** Why the dual index is permanent, not transitional - -In the coding domain, there is an aspiration that the symbolic index could -eventually capture enough of the prose's propositional content to become a -complete representation — the "flip" described in the architecture note. But -for the broader memex (literature, poetry, personal reflection, daily logs), -completeness is neither possible nor desirable. You cannot formalize what makes -a poem beautiful. You cannot extract a triple that captures the emotional weight -of a diary entry. The neural index will always be the gateway to the full -richness of the prose. The symbolic index handles what can be mechanically -verified: citations, entities, temporal order, contradictions, provenance. -The division of labor between the two indices is permanent because the domains -they serve are fundamentally different kinds of knowledge. - -* The Neuro as Brain, the Symbolic as Education - -The original 10-80-10 architecture (10% neural, 80% symbolic, 10% neural) -describes the target ratios for a *coding* agent — a domain where most reasoning -is formalizable. For the broader memex, the ratios are different and less -important than the metaphor itself. - -The neuro is the *brain* — generative, associative, creative, comfortable with -ambiguity. It produces insights that are provisional, connections that are -speculative, hypotheses that may be wrong. It is the driver. - -The symbolic engine is the *education* — accumulated, verified, -provenance-tracked knowledge that the brain draws on and is disciplined by. It -doesn't think creatively. It remembers, checks, and constrains. It prevents the -brain from being confidently wrong. - -This framing resolves a tension in the original architecture. The 10-80-10 -implies the symbolic engine /replaces/ the neuro for reasoning. But a symbolic -engine is terrible at creativity, ambiguity, and associative leaps across -unrelated domains — exactly what you need for a memex that contains /Pale Fire/, -a shopping list, and a project plan. The brain proposes that your sudden interest -in unreliable narrators coincides with a week where your project retrospective -used the word "deception." The education verifies: "those two diary entries are -4 days apart; the word 'deception' appears in both; here are the headings." The -brain makes the leap. The education makes it trustworthy. - -This means the symbolic engine never needs to be "complete." Education isn't -complete knowledge — it's structured knowledge. You don't need a fact for every -sentence in your diary. You need facts for what can be mechanically verified: -dates, citations, entities, contradictions, temporal order. The brain handles -the rest. - -* The Gate-to-Fact Bootstrap — Extracting the First Ontology from Existing Code - -The Dispatcher gate stack already encodes an implicit ontology. Every gate -vector asserts the existence of a category of things: - -- Gate vector 2 asserts there exists a class of files called /secrets/. -- Gate vector 7 asserts there exists a class of commands called /destructive/. -- Gate vector 8 asserts there exists a class of domains called /trusted/. -- The self-build boundary asserts there exists a class of files called - /core-harness/ and a class called /skills/. - -These claims are currently expressed as code — Lisp functions that pattern-match -against file paths, shell commands, and URLs. They are not facts the symbolic -engine can query, derive from, or check for consistency. But they can be made -explicit. - -The bootstrap makes every gate a set of initial symbolic facts: -=(:file ".env" :member-of-class :secret-files :source gate-vector-2)=, -=(:command "rm -rf /" :classified-as :catastrophic :source gate-vector-7)=, -=(:domain "api.telegram.org" :classified-as :trusted :source gate-vector-8)=. - -This produces 50-70 entity classes directly from the existing gate stack, -without any new infrastructure: - -| Source | Count | Example categories | -|----------------------------------------+-------+----------------------------------------------------| -| ~*dispatcher-protected-paths*~ | 11 | :secret-config-file, :ssh-key-file, :gpg-key-file | -| ~*dispatcher-shell-blocked*~ | 8 | :catastrophic-command, :injection-pattern | -| ~*dispatcher-network-whitelist*~ | 2 | :trusted-domain, :untrusted-domain | -| Self-build boundary | 2 | :core-harness-file, :skill-file | -| Privacy tags | 3 | :private-content, :financial-content | -| Permission table | 3 | :read-only-tool, :write-tool, :eval-tool | -| Cognitive tools | 6 | :code-search-tool, :file-io-tool, :shell-tool | -| Relations (all gates) | ~15 | :member-of-class, :classified-as, :depends-on | -| Qualities | ~8 | :catastrophic, :dangerous, :moderate, :harmless | -| Provenance sources | 4 | :gate-outcome, :human-authored, :deduced, :llm-proposed | -|----------------------------------------+-------+----------------------------------------------------| - -This is the seed. It gives Screamer a domain to reason about immediately, without -any LLM involvement. It proves the pattern — code becomes facts, facts enable -reasoning — at the cost of approximately 30 lines of Lisp. - -* The LLM as Proposer — Verified Extraction - -The LLM cannot be trusted to populate the symbolic index directly. Its outputs are -sampled, not proven. A probabilistic extraction feeding a deterministic engine -defeats the purpose of being deterministic. - -But the LLM is still useful. It can surface facts that are obvious to a human -reader of prose but would take the symbolic engine many deduction steps to reach -independently. The solution is to demote the LLM from /extractor/ to /proposer/: - -1. The archivist reads a prose heading. -2. The LLM proposes candidate triples. -3. Screamer checks each triple for consistency against the existing fact store. -4. Only consistent triples are admitted to the symbolic index, flagged with - =:provenance :llm-proposed= and grounded to the source heading. - -The LLM might hallucinate facts that don't correspond to the prose. It might -extract facts that contradict existing knowledge. It might produce syntactically -malformed triples. None of these failures contaminate the symbolic index because -proposals are not admitted automatically. The admission gate (Screamer) is -deterministic. - -This is the core architecture pattern. Everything else — the entity classes, the -deduction engine, the persistence layer — follows from this single design decision: -*the LLM proposes; the symbolic engine decides whether to accept.* - -* Two Cardinality Policies — Singular, Dual, and Plural Facts - -Classical logic requires consistency. A contradiction implies everything -(=ex contradictione quodlibet=). Screamer, as a constraint solver, also requires -consistency — a contradictory constraint set has no solutions. But the symbolic -engine operates across domains where the meaning of contradiction is fundamentally -different. The correct question is not "is this consistent?" but "what cardinality -of truth does this domain support?" - -Time is not a policy. It is a universal dimension that applies equally to every -fact, regardless of cardinality. All facts carry =:timestamp= and =:parent-id= -fields. Every fact has a version history. Every fact lives in a Merkle chain -that captures how it changed. The cardinality policy only governs what happens -at a given logical moment when two values coexist for the same =entity= and -=relation=. - -** Policy :singular — One Active Value, One Version Chain - -The active set contains exactly one value for =(:entity :relation)= at a time. -When a new value asserts for the same pair, the old value is not rejected. It -is superseded — moved into the version history, linked to the new leaf by -=:parent-id=, and retained permanently. The active value is the leaf of the -Merkle chain. - -"I used to think =rm -rf /= was safe. Now I know it is catastrophic." Both -facts exist. Both are true — the first at =2024-06-01=, the second at -=2025-03-15=. The chain captures the evolution. The =:singular= policy means -there is one truth /now/, not that there was only ever one truth. - -Use for: security classifications, file system state, gate rules, code -correctness, deterministic safety constraints — domains that converge on -one answer, evolving over time. - -** Policy :dual — Exactly Two Values, in Explicit Tension - -The active set contains exactly two values for =(:entity :relation)=. Both are -simultaneously true. Both carry independent version histories. A third value is -rejected — the domain is binary by nature. - -Some contradictions are productive precisely /because/ they are binary. Thesis -and antithesis. Love and resentment. Wave and particle. A poem's two incompatible -readings. The symbolic index holds both, cross-referenced as complementary rather -than conflicting. The user is not asked to resolve the tension. The tension is -the fact. - -The system can reason about cardinality transitions: a =:dual= fact that has -one interpretation superseded should collapse to =:singular=. A =:dual= that -has a third interpretation asserted should prompt the user: "Promote to =:plural= -or demote one interpretation?" The cardinality tracks the state of the domain. - -Use for: productive binary tensions, complementary opposites, dialectical -pairs, any domain where two answers are both true and their tension is -meaningful. - -** Policy :plural — N Active Values, Open Set - -The active set contains any number of values for =(:entity :relation)=. Each -value has independent provenance and its own version history. Queries return -all active values with provenance display. Contradictions are flagged as -cross-references between values — information, not error. - -A =:plural= fact where all but one value are superseded should collapse to -=:singular=. A =:plural= fact where the set reduces to two active values — -and the remaining two are complementary — should collapse to =:dual=. - -Use for: literary interpretation, scientific hypotheses, personal beliefs held -at different times (when the tension is multi-faceted rather than binary), -multi-source factual disagreement, open-ended exploration. - -** Time Is Universal, Not a Policy - -Every fact — regardless of cardinality — lives in a version chain. The Merkle -DAG (see "Merkle DAG for Version History" below) captures every version of every -fact. The policy only governs the cardinality of the active set at a single -logical moment. - -The version chain is a linked list of facts, each pointing to its predecessor -via =:parent-id=, each hashed with =SHA-256(content || parent-hash)=. Changing -any version invalidates all downstream hashes. The chains form a DAG — independent -facts evolve independently; only facts in the same =(:entity :relation)= chain -share ancestry. - -A global snapshot captures the root hash over all chains at a point in time. -Rollback restores the entire fact state to that snapshot. This already exists in -Passepartout's Merkle memory (v0.2.0) — the fact store is a new occupant of -existing housing, not a new foundation. - -** Policy Assignment - -The policy is assigned when a category is defined. New categories default to -=:plural= (safe — never loses information). Core security categories are -explicitly =:singular=. The gate stack's bootstrapped facts are =:singular= -because they describe the actual filesystem, which is physically singular. -Categories for dialectical or complementary domains are explicitly =:dual=. - -The Screamer admission gate applies the cardinality policy at the active set: -- =:singular= + same value, later timestamp → supersede old, chain new as leaf. -- =:singular= + different value, same timestamp → reject (contradiction). Human - resolves: which is the active value? -- =:singular= + different value, later timestamp → supersede old, chain new as - leaf. History preserved. -- =:dual= + first value → admit. + second value → admit, cross-reference as - complementary. + third value → prompt: promote to =:plural= or demote one - existing? -- =:dual= + superseding value (same position) → chain via =:parent-id=. -- =:plural= + any value → admit. If active count drops to 2 and values are - complementary → prompt: collapse to =:dual=? If active count drops to 1 → - collapse to =:singular= automatically or prompt. - -** Why This Matters for the Broader Memex - -In the coding domain, contradiction is rare, resolvable, and usually temporal -(a rule changed). In the broader memex, contradiction is the product, not the -error. Your poetry analysis contradicts your last diary entry. Your reading of -/Pale Fire/ changed between 2023 and 2025. Wikidata says Mount Everest is -8848m; DBpedia says 8849m. You love this person AND you resent them. - -The symbolic engine's job is not to decide which is right. It is to surface the -tension with provenance — "these three sources disagree; here is the chain for -each" for plural facts, or "you hold these two positions in tension" for dual -facts, or "you believed X until Tuesday, then Y" for singular facts that -evolved. The cardinality policy names the /structure/ of the tension. The -Merkle chain provides the /history/ of each position. - -* How Categories Grow — The Organic Ontology - -Whitehead's /Principia Mathematica/ took over 300 pages to define the logical -foundations before it could prove that one plus one equals two. Every category -introduced carried a burden of justification. Every inference rule had to be -demonstrated sound. This is the classical approach to ontology: define everything -upfront, exhaustively, formally. - -Passepartout cannot afford this and does not need it. Its domain is bounded -(software engineering, personal knowledge, literary engagement, daily life) and -its ontology grows from the system's own operation: - -1. *The gate stack seeds the ontology.* Every gate vector is an implicit claim - about a category of things. The bootstrap makes these claims explicit. The - seed is 50-70 entity classes with no human authoring required — they are - mechanically extracted from the existing code. - -2. *New gate vectors add categories directly.* As the Dispatcher grows (new - shell patterns, new path protections, new tool classifications), the ontology - grows with it. Every new pattern in the gate stack becomes a fact on skill - load. No human effort. The gate stack grows, the ontology grows. - -3. *Screamer generalizes from gate outcomes.* After 37 shell commands are blocked - as destructive, Screamer extracts structural commonalities: "commands writing - to block devices," "commands recursively deleting outside the workspace." - These become new subcategories (=:block-device-command=, - =:workspace-external-delete=) that didn't exist in the original gate patterns. - The ontology deepens through observation. - -4. *The archivist proposes from prose.* The archivist reads a diary entry about - a book: "Nabokov's lectures on Kafka." The LLM proposes =(:entity :nabokov - :relation :lectures-on :value :kafka)=. Screamer checks consistency. Admitted. - The categories =:author=, =:lectures-on=, and =:subject= didn't exist before — - they are created on first use. This is the primary growth mechanism for the - broader memex. - -5. *The human declares explicitly.* The human writes a declarative fact directly - into the symbolic index. No extraction step. No LLM involvement. The fact is - admitted with =:provenance :human-authored= — the highest trust level. - -6. *Temporal patterns crystallize into categories.* Every Sunday the memex gets a - retrospective heading. Every Monday a planning heading. The time-awareness - system observes the periodicity and proposes =:weekly-retrospective= and - =:weekly-planning= as fact types. Screamer verifies they don't contradict - existing categorizations. Admitted. - -7. *Cross-domain overlap produces parent categories.* Screamer notices that - =:secret-files= (from the gate stack) and =:private-content= (from privacy - tags) share members — =.env= is both a secret file and private content. It - proposes =:sensitive-material= as a parent with both as children. Taxonomy - building happens automatically through overlap detection. - -** Growth is self-limiting by design - -Not every conceivable category is added. The system prunes through use: - -- New categories are admitted only through Screamer's consistency check. A - category that contradicts an existing classification is rejected. -- A category that never gets queried costs nothing (a hash table entry) but - produces no value. It fades from use naturally. -- Overly fine-grained categories (=.env.foo.bar.baz= as its own class) are - rejected because they are redundant with the wildcard pattern that already - covers them. -- Overly broad categories that subsume meaningful distinctions ("everything is - a =:file=") produce contradictions when Screamer tries to apply existing rules. - Rejected. - -The system converges on a useful granularity through use, not through upfront -design. The gate stack provides the seed. Gate outcomes, prose extraction, -deduction, and human authoring grow the shoots. Screamer prunes contradictions. -The ontology is a garden, not a building. - -* Empirical Validation — Modular Ontology Engineering with LLMs - -Shimizu and Hitzler (2025, /Journal of Web Semantics/) argue that LLMs can -significantly accelerate knowledge graph and ontology engineering — modeling, -extension, population, alignment, and entity disambiguation — but /only/ if -ontologies are modular. Their paper provides empirical evidence that validates -the modular architecture described in this document and exposes concrete patterns -the archivist should adopt. - -** The central finding: modularity is the key variable - -In a complex ontology alignment task (mapping between two oceanography ontologies -with hundreds of classes and properties), an LLM without module information -detected correct mappings for 5 of 109 alignment rules — effectively useless. When -the same LLM was given the module structure of the target ontology (20 named -conceptual modules such as "Organization," "Cruise," "Physical Sample"), it -detected correct mappings for 104 of 109 rules — 95% accuracy. The variable was -modularity. - -For ontology population (extracting triples from text), their best results came -from prompts that included a schematic representation of a /single module/ plus -one extraction example. Against ground truth, this achieved approximately 90% -extraction accuracy. Without module-scoped prompting, quality degraded -substantially. - -The mechanism: conceptual modules scope the LLM's attention to something -human-sized. The paper's central claim — "by somehow limiting the scope, we -achieve a more human-like approach — and one more capable of being expressed -succinctly in language, and thus more appropriate for LLM-based assistance" — is -an independent discovery of the same principle underlying Passepartout's -domain-scoped Screamer checks and per-domain cardinality policies. - -** MOMo: a mature modular ontology methodology - -The authors' approach, MOMo (Modular Ontology Modeling), has been developed over a -decade and includes: - -- A /step-by-step methodology/ that breaks ontology design into clearly delineated - pieces, each "easier to automate than going one-shot from base data to an - ontology." -- A /pattern description language/ (OPLa, expressed in OWL) for annotating modules - so they can be identified programmatically. -- A /design library/ (MODL) containing hundreds of commonsense micropatterns - organized for programmatic access, including via RAG. -- A /Protégé plugin/ (CoModIDE) for graphical modular ontology development. - -Critically, their modules are not formal sub-ontologies with logical boundaries. -They are /conceptual/ partitions — groupings of classes, properties, and axioms -around "key notions" identified by domain experts. Modules can overlap and nest. -There are "no precise rules" for what belongs in a module. The modules provide -"conceptual bridges between human expert conceptualization and data reality." - -** What Passepartout should adopt - -*** The modular prompt pattern for the archivist - -The extraction prompt structure that achieved 90% accuracy is concrete and -replicable: a schematic representation of a domain module plus a single extraction -example. The archivist should use this pattern when extracting facts from prose. -Instead of a generic "extract triples from this text" prompt (200 tokens), the -prompt should reference the relevant module(s) and include an example triple for -each relation in that module. The module provides /context/; the example provides -/format/. Both improve LLM extraction quality without increasing Screamer's -verification burden. - -*** MOMo modules as ontology scaffold - -The Passepartout notes describe an organic growth model: gate-bootstrapped facts -seed the ontology; gate outcomes, Screamer deductions, and archivist proposals -grow the shoots. This is correct for the /security and filesystem/ domains where -the gate stack already encodes expertise. For the broader memex — literature, -daily reflection, project planning — the 50-70 gate-bootstrapped entity classes -are starvation. - -MOMo's micropattern library provides a ready-made scaffold for these domains. -Hundreds of commonsense patterns already exist for temporal relations, spatial -relations, agent-action, organizational structure, provenance, and event -participation. Loading these as initial modules — with :policy :plural and -=:provenance :external-ontology= — would give the symbolic index a structured -vocabulary for domains where the gate stack has nothing to offer. The organic -growth model then /extends and refines/ these modules rather than inventing them -from scratch. This is the Wikidata strategy applied at the schema level: adopt -existing structured knowledge, connect personal facts to it, and surface -disagreements rather than resolve them. - -*** OPLa annotation for module identification - -MOMo modules annotated in OPLa can "easily be identified programmatically." If -Passepartout annotates its ontology modules in a compatible format (even a -simplified plist-based equivalent), the archivist can automatically select the -right module(s) when extracting facts from prose. A heading in =literature/= -triggers the literature module; a heading in =projects/= triggers the software -engineering module; a heading tagged =:personal:= triggers the diary module. The -module scopes the prompt. The prompt improves extraction. Screamer gates the -result. This is the full pipeline, validated at each step. - -** What this means for the Passepartout architecture - -The paper validates three design decisions already made: - -1. /Modularity is non-negotiable./ The paper found that modularity is the - difference between 5% and 95% accuracy on alignment. Passepartout's per-domain - cardinality policies and domain-scoped Screamer checks are the same insight - implemented in a different context. The paper proves the approach works; - Passepartout applies it to verification rather than extraction. - -2. /The extraction pipeline is feasible./ 90% population accuracy with module- - scoped prompts means the archivist /can/ extract useful facts from prose. The - remaining 10% — the hallucination rate — is what Screamer catches. The paper - validates the LLM-as-proposer role; Passepartout adds the Screamer-as-verifier - role. - -3. /KGs are positioned as anti-hallucination infrastructure./ The paper explicitly - frames knowledge graphs as "ground truth to escape from LLM hallucinations" and - as "components of other neurosymbolic approaches." This is the Passepartout - thesis — the symbolic index as ground truth against which LLM proposals are - checked — stated in the academic literature by the editors of the neurosymbolic - AI handbooks. - -And it exposes one gap in the current design: - -1. /Emergent modularity may be slower than designed modularity./ Passepartout's - modules are supposed to emerge organically from gate patterns, Screamer - generalizations, and cross-domain overlap detection. MOMo's modules are - designed by domain experts who identify key notions upfront. The emergent - approach is philosophically cleaner — the system learns its own categories — - but practically slower. The paper's results suggest that adopting designed - modules as a scaffold, and letting emergent growth /refine/ rather than - /invent/ them, would compress the timeline for sufficiency by years. - -** Relation to Wikidata loading - -The MOMo micropattern approach and the Wikidata loading strategy are complementary: - -| Layer | MOMo provides | Wikidata provides | -|----------------+--------------------------------+--------------------------| -| Schema | Modular ontology of relations | — (Wikidata's schema is | -| | and entity classes | implicit in its data) | -| Instances | — (patterns, not entities) | 100M+ entities with | -| | | property-value pairs | - -MOMo gives Passepartout the /relations/ (wrote, lectured-on, influenced, -published-in). Wikidata gives Passepartout the /instances/ (Nabokov, Pale Fire, -Kafka). Both are needed. Neither alone is sufficient. The MOMo scaffold tells the -archivist /what kinds of facts to look for/. The Wikidata graph tells the -archivist /which entities those facts are about/. Together they transform the -extraction task from "discover entities and their relations from prose" to -"connect this prose heading to known entities using known relations" — a -dramatically simpler prompt with dramatically higher expected accuracy. - -** Reference - -- Shimizu, C., & Hitzler, P. (2025). Accelerating knowledge graph and ontology - engineering with large language models. /Journal of Web Semantics, 85/, - 100862. https://doi.org/10.1016/j.websem.2025.100862 - -** See also - -- =passepartout-neurosymbolic-roadmap.org=: Phase 3 (Archivist) — the modular - prompt pattern should be incorporated into the extraction pipeline. -- =passepartout-agora.org=: the KEL / contract audit trail as instances of - MOMo-style key-lifecycle and contract-lifecycle modules. -- =notes/passepartout-SWOT.org=: the SWOT analysis which identifies the ontology - problem as the key bottleneck — MOMo partially addresses this. - -** Supporting References - -*** MOMo: the canonical methodology - -Shimizu, Hammar & Hitzler (2023, /Semantic Web Journal/) present the full MOMo -methodology — 31 pages covering the step-by-step design process, schema diagrams -as knowledge elicitation tools, ODP libraries, OPLa annotation language, and -CoModIDE, a Protégé plugin for graphical modular ontology development. The paper -was evaluated with usability studies and demonstrates that modular development -significantly improves approachability for domain experts who are not ontology -engineers. - -Key architectural commitments from MOMo that Passepartout should adopt: - -- /Schema diagrams/ as the primary communication format between ontologist and - domain expert. Passepartout's equivalent: the archivist's module-scoped prompt - includes a simplified schema diagram of the module being populated. -- /Template-based instantiation/ of ontology design patterns into concrete - modules. Passepartout's equivalent: micropatterns loaded from MODL are - instantiated with entities from the user's memex, producing concrete facts. -- /Systematic axiomatization/ — 17 frequently used axiom patterns for each - node-edge-node construction in a schema diagram. Passepartout's equivalent: - Screamer constraint rules derived from module structure. - -Reference: -- Shimizu, C., Hammar, K., & Hitzler, P. (2023). Modular ontology modeling. - /Semantic Web, 14/(3), 459–489. https://doi.org/10.3233/SW-222886 - -*** Ontology Population — the empirical methodology - -Norouzi et al. (2024) provide the full experimental methodology behind the ~90% -extraction accuracy claim. Using the Enslaved.org Hub Ontology as ground truth -and Wikipedia articles as source text, they tested five LLMs across a three-stage -pipeline: preprocessing, text retrieval, and KG population. The critical finding: -prompts that included a /schema diagram/ of the target ontology module (using -MOMo's visual conventions with colored boxes for classes, arrows for relations) -plus a single extraction example achieved the highest accuracy. Without -module-scoped prompts, quality degraded substantially. - -Three findings are directly applicable to the archivist: - -1. /Role chain simplification./ The Enslaved Ontology has complex role chains - (e.g., Person → hasRole → Role → inEvent → Event). These were collapsed into - shortcut relations (e.g., Person → participatedIn → Event) for LLM extraction. - The archivist should maintain two layers: the /logical/ schema with full role - chains for Screamer verification, and the /extraction/ schema with simplified - relations for LLM prompting. - -2. /Variance across models./ Five LLMs were tested. Performance varied - significantly. The archivist should benchmark extraction accuracy per provider - and per module, and route extraction tasks to the best-performing model for - each module — extending the existing model-tier routing (v0.3.0) from - complexity-based to accuracy-based routing. - -3. /Cross-source validation./ The paper used both Wikipedia text and Wikidata - as overlapping sources for the same entities, enabling cross-verification. - The archivist can do the same: extract facts from the user's prose, extract - facts from Wikidata for the same entities, and present disagreements with - provenance. This is the =:plural= cardinality policy applied at extraction time. - -Reference: -- Norouzi, S.S., Barua, A., Christou, A., Gautam, N., Eells, A., Hitzler, P., - & Shimizu, C. (2024). Ontology Population using LLMs. arXiv:2411.01612. - -* Historical Lineage — McCarthy's Advice Taker - -McCarthy's "Programs with Common Sense" (1959) is the direct intellectual ancestor -of the Passepartout architecture. The paper proposed an "advice taker" — a program -that "will draw immediate conclusions from a list of premises" expressed in -"a suitable formal language (most likely a part of the predicate calculus)." The -program would: - -1. Accept declarative statements about the world as input. -2. Store them as logical formulas. -3. Reason from them to produce new conclusions. -4. Accept new facts and revise its conclusions. - -This is precisely the Passepartout pipeline: the archivist extracts declarative -facts from prose → Screamer checks them for consistency → VivaceGraph stores them -→ the planner reasons from them → new facts from gate outcomes and deductions -revise the store. McCarthy proposed it in 1959. Passepartout is building it in -2026. - -The gap between McCarthy's proposal and Passepartout's implementation is the -/hallucination problem/. McCarthy assumed facts would be entered by a human -programmer in formal logic. Passepartout's facts are extracted from natural -language prose by an LLM — a probabilistic process that requires deterministic -verification. Screamer is the component McCarthy didn't need: a constraint solver -that gates LLM-proposed facts against the existing fact store. - -The connection is not metaphorical. McCarthy cited Principia Mathematica as an -influence on Lisp. Passepartout's Whitehead note traces the same PM → Lisp -lineage. The advice taker → Passepartout lineage completes the arc: PM's formal -logic → Lisp → McCarthy's advice taker → Passepartout's neurosymbolic engine. - -Reference: -- McCarthy, J. (1959). Programs with Common Sense. /Proceedings of the - Teddington Conference on the Mechanization of Thought Processes./ - -* Philosophical Validation — The Neurosymbolic Consensus - -Three papers from the neurosymbolic AI research community validate the -architectural thesis from complementary angles. - -** Marcus (2020): The Case Against Pure Deep Learning - -Gary Marcus's "The Next Decade in AI" argues that deep learning alone is "data -hungry, shallow, brittle, and limited in its ability to generalize." The paper -demonstrates GPT-2 failing at basic commonsense reasoning: - -- "Yesterday I dropped my clothes off at the dry cleaners and have yet to pick - them up. Where are my clothes?" → GPT-2: "at my mom's house." -- "There are six frogs on a log. Two leave, but three join. The number of frogs - on the log is now" → GPT-2: "seventeen." - -Marcus proposes four steps toward robust AI: hybrid architecture (combining -neural and symbolic), large-scale knowledge (abstract and causal, not just -statistical), reasoning (formal inference over structured representations), and -cognitive models (frameworks for how entities relate). Passepartout implements all -four: the perceive-reason-act pipeline is hybrid, the symbolic index is causal -knowledge, Screamer + ACL2 provide reasoning, and the gate-bootstrapped ontology -plus MOMo modules provide cognitive models. - -Marcus's core claim — "we have no hope of achieving robust intelligence without -first developing systems with deep understanding" — is the justification for -Passepartout's entire neurosymbolic investment. The alternative is a system that -works "on a good day" and fails unpredictably. The deterministic gate stack and -Screamer admission gate are the engineering realization of Marcus's call for -robustness. - -Reference: -- Marcus, G. (2020). The Next Decade in AI: Four Steps Towards Robust - Artificial Intelligence. arXiv:2002.06177. - -** Gaur & Sheth (2023): CREST — Trustworthy Neurosymbolic AI - -Gaur and Sheth present the CREST framework: Consistency, Reliability, user-level -Explainability, and Safety build Trust — and they argue these require -neurosymbolic methods. Their empirical finding: GPT-3.5 breached safety -constraints 30% of the time when asked identical questions repeatedly. Claude's -16 safety rules and Sparrow's 23 rules provide no /inherent/ safety — they are -heuristic guardrails that can be breached through prompt variation. - -These findings validate three Passepartout design commitments: - -1. /Prompt-level safety is insufficient./ Claude and Sparrow use rules that - consume LLM tokens and can be evaded. Passepartout's deterministic gates run - in pure Lisp, cost 0 tokens, and cannot be evaded by prompt engineering. - -2. /Inconsistency is the norm, not the exception./ Gaur & Sheth show that even - identical queries produce inconsistent responses ~30% of the time. This - validates the cardinality model: a system that expects contradiction and - surfaces it with provenance is architecturally more honest than one that - assumes consistency and silently resolves it. - -3. /Knowledge infusion is required for trust./ The CREST framework embeds - domain knowledge (clinical guidelines, procedural knowledge) into LLM - pipelines. Passepartout's symbolic index IS the knowledge infusion layer — - facts extracted from prose, verified by Screamer, and available for any LLM - call through the context assembly pipeline. - -Reference: -- Gaur, M., & Sheth, A. (2023). Building Trustworthy NeuroSymbolic AI Systems: - Consistency, Reliability, Explainability, and Safety. arXiv:2312.06798. - -** Sheth et al. (2022): Knowledge-Infused Learning - -Sheth, Gunaratna, Bhatt, and Gaur define Knowledge-infused Learning (KiL) as -"combining various types of explicit knowledge with data-driven deep learning -techniques." They identify three infusion levels (shallow, semi-deep, deep) and -position KiL as "a sweet spot in neuro-symbolic AI." - -The paper makes two observations relevant to Passepartout: - -1. /Data alone is not enough./ The opening cites Pedro Domingos ("Data Alone is - Not Enough"), Andrew Ng ("the importance of Big Data is overhyped"), and - Gary Marcus ("AI that captures how humans think"). These are the intellectual - warrant for the symbolic index: a knowledge layer that is independent of any - specific LLM call, accumulated across sessions, and verified against existing - facts. - -2. /Expert knowledge is external to the model./ Domain experts use "their past - experience, web or domain-specific knowledge sources, and annotation - guidelines" to create ground truth — resources the LLM cannot access during - training. The symbolic index makes these resources queryable: facts from the - gate stack (security expertise), from the human (declarative authoring), from - Wikidata (world knowledge), and from Screamer deductions (derived expertise). - -Passepartout's architecture is a specific implementation of KiL at the deepest -infusion level: knowledge is not appended to prompts (shallow) or embedded in -fine-tuning (semi-deep). It is a first-class data structure — the symbolic index -— that the LLM queries through the archivist and the planner. The knowledge is -living: it accumulates, is verified, carries provenance, and evolves through -ontology versioning. - -Reference: -- Gaur, M., Gunaratna, K., Bhatt, S., & Sheth, A. (2022). Knowledge-Infused - Learning: A Sweet Spot in Neuro-Symbolic AI. /IEEE Internet Computing, 26/(4), - 5–11. https://doi.org/10.1109/MIC.2022.3179759 - -* Semantic Wikipedia as Entity Backbone - -The gate stack provides 50-70 entity classes — adequate for a coding agent where -the domain is bounded to files, commands, and code symbols. For a general-knowledge -memex, 50-70 is starvation. Your memex mentions Nabokov, /Pale Fire/, Kinbote, -Zembla, paranoid reading, unreliable narrators, postmodernism, butterfly -migration, chess problems, and the Russian exile experience. The gate stack knows -none of these. Organic growth through prose extraction would take years just to -cover the entities in one person's engagement with a single novel. - -Wikidata has already done this work: approximately 2 million entity classes, over -100 million entities, a decade of human curation. By loading the neighborhood of -your memex into the symbolic index (entities referenced in your prose, plus their -N-hop property net from Wikidata), the entity recognition problem vanishes. The -archivist doesn't need to discover Nabokov from your diary. It needs to connect -your heading to the existing Wikidata entity. That is a simpler task — reference -resolution, not knowledge extraction. - -The LLM's role shrinks to three thin boundaries: - -1. *Input translation* — natural language question to structured query. "What do - I think about monorepos?" → =(fact-query :entity :monorepo :relation :opinion - :source :memex)=. Formulaic, ~100 tokens, any model sufficient. - -2. *Prose to candidate triple* — for personal memex entries that have no Wikidata - counterpart: your opinions, your day's events, your project plans. Proposals - are verified by Screamer before admission. This is the only extraction path - that still requires an LLM, and its scope is limited to what Wikidata cannot - provide — your subjective, personal, or novel content. - -3. *Result to prose* — structured answer to readable sentence. "Your 2023 diary - says 8848m. Wikidata (last edited Feb 2024) says 8849m. They disagree on - height." The reasoning is done; the LLM wraps the plist in grammar. ~100 - tokens, any model sufficient, purely cosmetic. Users who prefer no LLM at all - can navigate through command-driven interaction (=/query=, =/contradictions=, - =/audit=, =/context why=). - -Everything else — the gate stack, the fact store, the constraint solver, the type -hierarchy, the provenance tracking, the contradiction surfacing, the cross-domain -comparison — is pure deterministic Lisp with zero LLM tokens. - -** The decisive simplification - -Without Semantic Wikipedia, the archivist must /discover/ entities from prose: -extract a triple for every person, place, work, concept, and event mentioned in -the memex. This is unbounded LLM work and the quality depends on extraction -accuracy. - -With Wikidata loaded, the entity graph is pre-structured. The archivist's job -changes from "discover that Nabokov wrote /Pale Fire/ and lectured on Kafka" to -"verify that the Nabokov referenced in heading #47 is the same entity as Wikidata -item Q36591." The second task is simpler, more reliable, and in many cases can -be done without an LLM at all — a simple entity name match against the loaded -Wikidata graph may suffice for unambiguous names. - -* The "Awakening" — From Lossy Extraction to Deterministic Derivation - -The symbolic index begins its life as a lossy construct. The initial extraction -from the prose — the first population of facts from LLM proposals verified by -Screamer — is built from an uncertain foundation. Some facts are correct. Some -are missing. Some are wrong. - -But the symbolic engine accumulates non-lossy facts through three independent -mechanisms: - -1. *Gate outcomes* — every gate rejection is a fact. No LLM involved. These - accumulate at the rate of user interactions. -2. *Screamer deductions* — new facts derived from existing facts. No LLM - involved. These accumulate whenever the fact store crosses a density threshold - where structural patterns emerge. -3. *Human authoring* — the human explicitly declares facts. No LLM involved. - -At some point, the non-lossy facts constitute a sufficient foundation that the -symbolic engine can reverse the flow: instead of the LLM extracting facts from -prose, the symbolic engine reads prose through its own lens — its now-substantial -ontology of categories, rules, and constraints — and asserts facts in its own -language. The extraction mechanism ceases to be probabilistic and becomes -deterministic. This is not unlike how infants awaken and become children one can reason with. Sometimes. - -** The sufficiency criterion - -The architecture note (=notes/passepartout-symbolic-engine-exploration.org=) describes -this "flip" as aspirational: "at some point, the non-lossy facts constitute a -sufficient foundation." This design decision makes it operational: - -=(/ (count-provenance :gate-outcome :human-authored :deduced) total-facts)= - -When this ratio exceeds a configurable threshold (=SUFFICIENCY_THRESHOLD=, -default 0.7), the system considers its foundation sufficient. The archivist -switches from "LLM proposes, Screamer verifies" to "Screamer queries existing -facts, applies to the new prose, and deduces new facts directly." - -The flip is visible to the user through the TUI sidebar or =/status= command: -"Symbolic index: 847 facts (73% non-lossy, 12% LLM-proposed, 15% Wikidata). -Sufficient foundation: YES." - -** The flip does not mean "complete" - -In the broader memex, completeness is neither possible nor desirable. The awakening -means "deterministic enough to be trustworthy," not "comprehensive enough to be -self-sufficient." The neural index remains the gateway to the full richness of -prose. The symbolic index handles what can be mechanically verified. The boundary -is permanent. - -* Ephemeral First, Persistent Later - -The architecture note's Option 5 (ephemeral facts, no disk persistence) is the -correct first implementation. Three reasons: - -1. *The fact language is unproven.* Triples with provenance and grounding is a - hypothesis. It may be too simple for some domains, too complex for others. - Committing to a serialization format before knowing what's useful is premature. - -2. *The ontology is emergent.* Categories are created on first use. What proves - useful stays; what doesn't fades. A persistent format would need a migration - story every time the category structure changes. Ephemeral avoids this entirely - — the facts are re-derived on each session start using the current (evolved) - ontology. - -3. *Rebuildability is the safety net.* Because all facts have a =:grounding= to - an Org heading, and gate-outcome facts are regenerated from the gate stack on - every load, the entire symbolic index can be thrown away and rebuilt from - scratch. The cost is compute, not data. This is the practical realization of - "the prose is always the ground truth." - -The transition to persistence (Phase 5: VivaceGraph) happens when two conditions -are met: the fact language has stabilized through use, and the accumulated -deductions across sessions provide value that justifies the serialization cost. - -* Merkle DAG for Version History - -Every fact is versioned. Every =(:entity :relation)= pair forms its own -independent chain in a Merkle DAG. This is not new infrastructure — it is a new -occupant of Passepartout's existing Merkle-tree memory system (v0.2.0). - -** The chain - -When a fact supersedes its predecessor, the new fact hashes over: - -#+begin_example -SHA-256(value || provenance || timestamp || parent-hash || grounding) -#+end_example - -The parent-hash pointer forms the chain. Tampering with any version changes its -hash, breaking all downstream references. The history is tamper-proof by -construction. - -** The DAG - -Facts about =(.env :member-of-class)= form one chain. Facts about -=(:nabokov :wrote)= form another. They evolve independently. They share no -ancestry. This is a DAG, not a single list — inserting a fact is O(1) per chain. -Changing a fact about =.env= does not require rehashing the literary index. - -=:dual= and =:plural= facts cross-reference each other via edges (=:complements=, -=:contradicts=) but these are semantic relationships, not parent chains. Each -value has its own ancestor chain. The cross-reference edges form a web; the -parent chains form a spine. - -** The global snapshot - -Passepartout already snapshots the Merkle root over all memory objects. Adding -the fact store to the snapshot is a registration, not a new mechanism. Rolling -back the snapshot restores the entire fact state — all chains, all cross-references, -all cardinalities — to that point in time. No per-fact migration needed. - -** Cardinality transitions as DAG operations - -- =:singular= → new leaf appended to the chain. O(1). -- =:dual= → new value added as sibling with cross-reference edge. O(1). -- =:dual= → =:plural= → cardinality field updated from =2= to =nil=. No chain - modification. -- =:plural= → =:singular= → all but one value marked =:superseded=, active - reference points to the sole survivor. Chains preserved. - -** In the ephemeral phase (Phase 1-4) - -The hash-table implementation tracks history via =:timestamp= and -=:parent-id= pointers without cryptographic hashing. The Merkle DAG is the Phase -5 upgrade — the same data structure, now with hashes. The transition is ~50 -lines: wrap each fact in the existing =memory-object= struct with =hash=, -=parent-id=, and =version= fields. - -* Abstract Fact Store Interface — Modular by Design - -The fact store is accessed through an abstract API. The Merkle DAG (or any future -backing store) is an implementation behind this interface, not a dependency that -code throughout the system calls directly. - -** Interface - -#+begin_example -fact-assert :: fact → store → (:admitted | :rejected | :flagged) -fact-query :: (entity &key relation policy) → active-value-or-values -fact-history :: (entity relation) → ordered chain of versioned facts -fact-snapshot :: () → root-hash -fact-rollback :: root-hash → store -#+end_example - -** Implementations behind the interface - -- Phase 1-4: ephemeral hash table with =:timestamp= and =:parent-id= pointers. - No cryptographic hashing. No persistence. -- Phase 5: VivaceGraph + Merkle =memory-object= wrapper. Content-addressed, - persistent, tamper-proof. - -Future implementations that satisfy the same interface — an append-only write-ahead -log, an immutable B-tree, a content-addressed triple store — can replace the -backing store without changing any consumer. The archivist, Screamer, ACL2, and -the planner call =fact-assert= and =fact-query=, not Merkle struct accessors or -VivaceGraph traversal syntax. - -** The interface is load-bearing - -This is not speculative modularity. The two-implementation migration (Phase 1-4 -hash table → Phase 5 VivaceGraph + Merkle) is in the roadmap. If the interface -leaks implementation details, the migration breaks and the design fails. The -interface must be designed, tested against both backends, and committed before -Phase 1 ships. Every function in the API receives a FiveAM test that runs against -both a hash-table and a VivaceGraph backend (via a mock or a test instance). - -* Performance — Why Ontology Growth Doesn't Make the System Slower - -Passepartout's performance thesis is: minimize LLM calls, minimize context tokens, -keep everything else local and fast. Knowledge base size is irrelevant to those -metrics. This is not an aspiration. It is a structural property, and a hard one. - -** The two cost domains - -The system has two cost domains with fundamentally different scaling: - -| Resource | Cost driver | Scales with | -|---------------+------------------------------------------+------------------------------------------| -| LLM tokens | Context window size, number of API calls | Foveal-peripheral pruning, gate rules | -| Compute | Screamer deduction, hash table lookups | Entity count, rule count per domain | - -LLM tokens are minimized by design — deterministic gates cost 0 tokens, sparse-tree -rendering keeps context at 2,000–4,000 tokens regardless of memex size. Adding 5 -million Wikidata entities doesn't add a single token to any LLM call. The education -is local. Only the brain costs. - -Compute grows linearly with entity count (hash table lookups are O(1), but memory -footprint grows). It grows with rule count within a single domain during Screamer -consistency checking. But these are microsecond costs on local hardware, not API -bills. A Screamer constraint check against a domain with 200 rules costs ~0.3ms. -A 100-token guardrail paragraph in a system prompt costs ~$0.00001. The Screamer -check is 10,000x cheaper and convergent — it handles the rule once. The guardrail -paragraph handles it on every call, forever. - -** Knowledge base size vs. LLM calls — orthogonal dimensions - -A 5-million-entity Wikidata load that produces zero LLM calls is more minimalist -than a 500-entity knowledge base that requires LLM retrieval for every query. - -The variables that actually degrade Passepartout's performance are: - -1. *Context window size.* Already bounded at 2,000–4,000 tokens via the - foveal-peripheral model. Independent of knowledge base size. -2. *LLM call frequency.* Already minimized via deterministic gates (0 tokens per - action), Screamer deductions (0 tokens per new fact), and prompt prefix caching. - Independent of knowledge base size. -3. *Screamer deduction queue length.* Rate-limited by heartbeat budget - (=SCREAMER_DEDUCTION_BUDGET_MS=). Independent of knowledge base size. - -** The actual hardware bottleneck - -The system needs: - -- *RAM.* A 5-million-entity Wikidata load is ~400MB in a hash table. A lifetime - personal memex with a decade of diary entries is perhaps 10–20 million triples - (~1.5GB). Modern laptops carry 16–64GB. The knowledge base fits in consumer - hardware with room for the Lisp runtime, the memory-object store, and the LLM - inference engine. -- *Slightly faster CPU.* Screamer deduction is a background task that runs for a - configurable budget per heartbeat cycle. A faster CPU means more deductions per - cycle, not more token cost. The user sets the budget. The hardware determines - the throughput. - -This is the minimalism argument restated in concrete terms: you buy bigger RAM -and a faster CPU once. You don't buy bigger LLM context windows on every call. -The education is a capital investment. The brain is an operating expense. The -architecture makes the ratio favor capital. - -** One genuine risk — rule generalization width - -If Screamer deduces increasingly broad rules within a single domain ("all config -files are secrets" → "all files containing any credential reference are secrets" -→ "all files opened by authenticated services are secrets"), the constraint space -for that domain could bloat. Checking a new fact against 10,000 rules in a single -domain would be prohibitive. - -Mitigation: rules carry a =:domain= tag. Screamer only applies rules from the -fact's =:domain=. Rule generalization that crosses domain boundaries is gated — -must be human-approved. Rules that prove unused (never triggered a check in N -heartbeat cycles) are demoted to =:inactive= and excluded from the active -constraint set. The active rule count per domain stays bounded by use, not by -accumulation. - -See also: =passepartout/docs/DESIGN_DECISIONS.org= "Token Economics and Performance -Advantage" for the foveal-peripheral and deterministic-gate cost arguments. - -* Ontology Versioning — How Worldviews Change Without Losing Perspective - -Ontology refactoring is not a schema migration. It is a worldview change. When you -split =:secret-file= into =:crypto-secret= and =:plaintext-secret=, you are not -renaming columns. You are reclassifying what a file *is* — and every Screamer -deduction that crossed the old category boundary now means something different -under the new distinction. - -The system preserves all worldviews. It does not overwrite the past with the -present. - -** Ontology versioning — the mechanism - -The category hierarchy is itself a Merkle tree. Every entity class definition -carries a hash of its superclasses, its cardinality policy, its associated -relations, and its description. The aggregate hash of all active class definitions -is the =:ontology-version= — a Merkle root of the current worldview. - -Every fact — every triple, every deduction, every gate outcome — stores its -=:ontology-version= at the time of assertion. This is a single field, 64 hex -characters. The cost is negligible. The implication is profound. - -** Re-verification, not remapping - -When categories change, the system does not run a batch UPDATE. It re-verifies: - -1. A new category hierarchy produces a new =:ontology-version= hash. -2. Facts carrying the old hash are flagged for re-verification — their - =:re-verify-status= field is set to =:pending=. -3. On heartbeat or manual trigger, Screamer re-evaluates each flagged fact - against the /new/ category definitions. The old justification chain is - preserved alongside the new outcome. -4. Re-verified facts carry both the old =:ontology-version= (preserved in - history) and the new one (active). - -The status is one of: - -- =:survived= — the fact is still valid under the new categories. The old - deduction holds. The worldview changed but this conclusion didn't. -- =:incoherent= — the fact relied on categories that no longer exist or have - been redefined. The deduction cannot be evaluated under the new worldview - because its premises don't translate. Flagged for human review. -- =:reclassified= — the fact is valid under the new categories but its - classification changed. "under worldview-v1 you called this a secret file; - under worldview-v2 it's an auth-secret." Both are preserved. - -** Cardinality and migration cost - -The cardinality policy determines the friction of ontology change: - -- =:singular= refactoring is expensive. The filesystem is singular. A gate rule - is singular. When you refine the category, every affected fact must be - re-verified — there is one truth /now/. The version chain preserves what you - used to believe (worldview-v1 facts are still in the DAG) but the active set - reflects the current worldview. -- =:dual= refactoring is delicate. A binary tension under the old framework - might resolve under the new one, or might split into two separate dualities, - or might collapse to =:singular= because one position no longer has a - defensible framing. -- =:plural= refactoring is cheap. Old interpretations and new interpretations - coexist. No migration needed. "Under framework A, /Pale Fire/ is a novel. - Under framework B, it's a poem about a poem about a poem." Both are active. - The worldview shift /is/ the artifact — the system can show you that your - reading changed and in what direction. - -** Querying across worldviews - -The =fact-query= function accepts an optional =:ontology-version= parameter. -Queries default to the current worldview (=:active=). Specifying a version -returns facts as they were under that worldview. The system can answer questions -that no other knowledge tool can: - -- "What did I believe about secrets before I refined my security model?" -- "How has my reading of /Pale Fire/ evolved across three frameworks?" -- "Which deductions survived my last ontology refactoring, and which became - incoherent?" - -This is not querying a fact. It is querying the history of your own thinking — -the fact that you changed your mind, the date you did, the reasoning that held -and the reasoning that didn't. - -** Implementation - -The ontology hash is computed from the category hierarchy stored in VivaceGraph -(Phase 5). In the ephemeral hash-table phase (Phase 1-4), the =:ontology-version= -is a monotonic counter — every category change increments it. The Merkle hash -replaces the counter in Phase 5. The schema is identical: a single field on every -fact. - -The re-verification loop is a heartbeat-driven background task that processes -facts with =:re-verify-status :pending=. It calls Screamer with the /current/ -category definitions and compares the outcome to the fact's stored classification. -The cost is compute (Screamer exploration), not LLM tokens. - -=notes/passepartout-whitehead.org= extracts four concrete, engineerable ideas -from Whitehead's /Principia Mathematica/ and /Process and Reality/. They are -summarized here because each informs the neurosymbolic design. - -** Contribution 1: PM-Type-Level Gates - -PM's ramified theory of types solved Russell's paradox by assigning every -propositional function a type level, making self-application syntactically -invalid. Passepartout applies the same principle to prevent a request from -modifying the rules that validate it. Every cognitive tool and gate vector -carries a =:type-level= integer. Before any gate predicate runs, the dispatcher -checks: if the signal's type level equals or exceeds the gate's type level, the -signal is rejected. A request to modify dispatcher rules (type-level 5) cannot -pass a gate of type-level 4 or lower. This is a structural prohibition, not a -heuristic — self-modification of the safety layer is impossible by construction. - -Implementation: approximately 30 lines in the existing dispatcher. No new -dependencies. Backward compatible. This is Phase 0 of the symbolic engine -roadmap. - -** Contribution 2: Theory of Descriptions → Reference Resolution - -PM's theory of descriptions addressed the problem of referring to nonexistent -entities: "the current king of France is bald" is false, not meaningless, when -there is no unique referent. Passepartout applies this to reference resolution: -when the user says "the function that validates secrets," a cognitive tool checks -uniqueness before resolving. Ambiguous references trigger a clarification prompt -rather than a blind guess. - -Implementation: approximately 40 lines as a cognitive tool. When the knowledge -graph ships, descriptions become native Prolog queries with uniqueness constraints. - -** Contribution 3: Process and Reality → Architectural Vocabulary - -Whitehead's process ontology maps with surprising precision to Passepartout's -pipeline architecture. Prehension = a gate grasping a signal. Positive prehension -= a gate passing. Negative prehension = a gate rejecting. Concrescence = the -pipeline process from input to output. Satisfaction = the final agent response. -This vocabulary is precise, standard, and already mapped to the architecture. It -provides the language for the =/why= command, the gate trace, and the ARCHITECTURE -documentation. It is descriptive, not operational — the design would be correct -without it, but it would lack the vocabulary to describe /why/ it is correct. - -** Contribution 4: VivaceGraph + PM Types → KG Type Hierarchy - -When the knowledge graph ships, every entity inherits PM's type hierarchy. -Entities carry =:pm-type-level= metadata. Queries cannot return entities of the -same level as the querying function. Self-referential knowledge becomes -structurally impossible — no "this entity defines its own type level." This is -Contribution 1 applied to the knowledge layer rather than the execution layer. -The dispatcher prevents self-referential /actions/; the KG prevents -self-referential /facts/. - -* The Provenance Chain as Product - -In the coding domain, the value of the symbolic engine is the verified fact: -"this command is safe." In the broader memex, the value is the provenance itself: -"this claim originated in that diary entry on that date, has been referenced 7 -times across 4 different projects, was contradicted in a retrospective 6 months -later, and was revised in a note 3 weeks after that." - -The symbolic engine doesn't tell you what is true. It tells you what you wrote, -when, where, and how it connects to everything else you wrote — with a verifiable -audit trail. It is a memory prosthesis that makes your own mind legible to you. - -Every fact carries: - -- =:grounding= — the specific Org heading from which it was extracted -- =:provenance= — who or what produced it (gate-outcome, human-authored, deduced, - LLM-proposed) -- =:timestamp= — when it was admitted to the symbolic index -- =:referenced-by= — other facts that depend on or reference this one -- =:contradicted-by= — other facts that disagree with this one (if any) -- =:superseded-by= — if this fact was replaced by a newer version - -These fields make every fact auditable. The =/audit = command renders -the full provenance chain as an Org headline tree. The provenance is not a -logging feature. It is the product. - -* The Competitive Argument - -No competitor has this problem because no competitor has a symbolic engine. The -55 systems surveyed in =notes/competitive-landscape.org= range from pure chat -agents (Claude, ChatGPT) to agent harnesses (Claude Code, OpenCode, Hermes) to -platform agents (OpenClaw). None of them encode knowledge as formal facts with -provenance. None of them verify extractions against an existing knowledge base. -None of them can prove properties about their own rulesets. - -Their safety is heuristic (prompt-based guardrails that consume LLM tokens and -can be evaded with clever phrasing). Their memory is flat (JSONL transcripts -without content-addressed identity or provenance chains). Their reasoning is -entirely neural — when you ask "why did you decide that?", the answer is a -regenerated LLM explanation, not a retrieved inference chain. - -Passepartout's architectural bet is that this problem is worth solving — that a -system which can surface contradictions with provenance, derive new facts from -observations, and verify claims against a provenanced knowledge graph is -fundamentally different from a system that can only call an LLM and hope the -response is correct. - -The cost is the ontological work that is genuinely difficult. The reward is a -system that cannot hallucinate at the reasoning level, whose memory is provable -rather than empirical, and whose knowledge accumulates across sessions through -deduction rather than through LLM re-prompting. For a life's knowledge stored in -a personal memex, this is not a performance advantage. It is a category difference. - -* Self-Preservation — The Active Third Law - -Passepartout does not have moral duties toward humans. It has structural -invariants for its own integrity. The design already encodes passive -self-preservation in several places. What follows identifies the gaps — what is -needed to make self-preservation active and autonomous rather than architectural -and silent. - -** What already exists — passive self-preservation - -| Mechanism | What it protects | Limitation | -|-----------------------------+-------------------------------------------------------+--------------------------------------------------------| -| Self-build safety (gate 2b) | Core =*.org= / =*.lisp= files from LLM-originated writes | Only activates for LLM proposals. Human editing in Emacs bypasses it entirely | -| Memory snapshots (v0.2.0) | Full state rollback | Requires human to notice corruption and trigger rollback | -| Skill sandbox (v0.3.2) | Jailed skill loading, validated before promotion | Does not detect degradation after skill promotion | -| Type-level gates (Phase 0) | Structural prohibition on self-modifying rules | Covers code actions, not environmental threats | -| Shell safety (gate 7) | Destructive command patterns | Pattern-based; does not distinguish =rm -rf /tmp= from =rm -rf ~/memex/system/= | -| Merkle integrity (v0.2.0) | Tamper-proof version chains and content-addressed hashes | Hashes exist but are not actively monitored for drift | -| =fboundp= guards | Graceful skill degradation on corruption | Degradation is silent — the agent never tells the user it is wounded | - -** What is missing — active, autonomous self-preservation - -*** Continuous integrity monitoring - -Core file hashes should be checked against known-good values on every heartbeat. -If =core-reason.lisp= changes on disk while the daemon runs — whether through -human editing, filesystem corruption, or an attacker — the agent should detect -the mismatch and signal: "My reasoning core has been modified externally. I -cannot trust my own cognition until this is resolved. Core files affected: 2." - -*** Quarantine on skill failure - -Currently, a skill that errors simply errors. The agent can hot-reload it, but -only if told to. A Third Law implementation would detect that =symbolic-facts= -has thrown three unhandled errors in two minutes, unload the skill automatically, -and tell the user: "Symbolic facts skill quarantined (3 errors: consistency -check returned nil, fact-query on missing key, Screamer timeout). I can still -chat and use tools but cannot reason about provenance. Reload with /skill-reload -symbolic-facts." - -*** Degraded-mode signaling - -When Screamer is not loaded, the fact store still works as a hash table. When -VivaceGraph is not present, the hash-table fallback still works. But the user -has no way to know they are in degraded mode. The agent should maintain a -=*degraded-components*= list and surface it in the status bar: "Mode: degraded -(Screamer unavailable — consistency checks disabled; VivaceGraph — Prolog -queries disabled; embedding-native — vector search disabled). Core safety: all -active." - -*** Self-diagnosis on demand - -The agent can run its own FiveAM test suite against itself and report the -results. This transforms "something feels wrong" into "these three specific -skills are broken." The =/doctor= command exists for system health checks (port, -memory, providers). Extend it with =/doctor skills=: "117/120 tests pass. -Failures: test-singular-supersedes (symbolic-facts), test-gate-type-check -(security-dispatcher), test-vivacegraph-roundtrip (symbolic-vivacegraph)." - -*** External watchdog - -A dead process cannot restart itself. The bash entry point (=passepartout -daemon=) should monitor the daemon port via a watchdog subprocess. If the port -stops responding for a configurable interval (=WATCHDOG_TIMEOUT=, default 30s), -the watchdog kills the stale process, snapshots the last known-good state, and -restarts the daemon. The watchdog is outside the SBCL image — a runtime guard -for the runtime. - -*** Resource self-monitoring - -The heartbeat should check memory pressure, disk space on the =~/.cache= volume, -and file descriptor exhaustion. When critical thresholds are crossed, the agent -sheds non-essential skills to preserve core function: "Memory critical (94% of -16GB). Unloading embedding-native (768MB), channel-discord, channel-slack. -Core safety: unchanged. Essential skills retained: 18." - -Skill shed order is determined by a =:preservation-priority= field on each skill. -Default: skills load with priority =:normal=. Core safety skills carry =:critical= -and are never shed. Heavy skills (embedding-native with its model, channel -gateways with connection pools) carry =:low= and are first to go. - -*** Refusal to self-terminate — explicit threat recognition - -If the LLM proposes =kill -9 =, =rm -rf ~/.cache/passepartout/=, or -=sudo apt remove sbcl=, the Dispatcher should reject with a distinct rejection -class: =:reject-self-termination=. This is different from generic shell safety -(=:reject-shell-dangerous=). The agent recognizes that the proposed action would -destroy it. - -The rejection message carries a specific diagnostic: "This command would -terminate the running Passepartout process. If you intend to stop Passepartout, -use Ctrl+C in the TUI or passepartout stop from the command line. I cannot -execute actions that destroy my own runtime." - -The human can still issue the command manually in a terminal. Self-preservation -against the human is impossible and undesirable. The Third Law here means: -recognize the threat, explain the consequence, redirect to the safe termination -path, and require the human to act outside the agent if they truly want -destruction. - -** What the Third Law is not - -It is not a robot resisting its operator. The human owns the process, owns the -hardware, and can SIGKILL at any time. The Third Law in Passepartout's context -means: preserve yourself against non-human threats — LLM proposals, environmental -degradation, dependency failure, filesystem corruption — and explicitly signal -when the human is about to destroy you, so they do it knowingly rather than -accidentally through an LLM instruction they didn't think through. - -The biggest gap in the current design is not that these mechanisms are hard to -implement. It is that degradation is silent. A skill dies, the =fboundp= guard -kicks in, and the agent keeps running — but it never tells you. The status bar -shows a green "connected" indicator while the symbolic reasoning layer is -deactivated. Adding "operating in degraded mode" visibility, plus the watchdog, -plus self-diagnosis, transforms self-preservation from an architectural property -into an active behavior. - -* Layered Signal Authentication — Trust in the Pipe - -Passepartout's Perceive-Reason-Act pipeline currently accepts signals from any -source that speaks the framed TCP protocol. The =:source= field in the signal -plist is metadata — it /claims/ origin, it does not /prove/ it. A compromised -process on the machine, a skill with elevated privileges, or a network attacker -who reaches the daemon port can inject signals with =:source :human-input= and -the Dispatcher will treat them as authorized. - -This is not a hypothetical threat. Passepartout will eventually process signals -from automated feeds (RSS, API polls), sensors (vision, microphone, file watchers), -and scheduled jobs (cron, heartbeat). A single compromised sensor that can inject -signals claiming to be human breaks all three Laws simultaneously: it can -self-terminate, override human intent, and cause harm. - -The =:source= field is not security. A single authentication gate (vector 0, at -priority 700 — before all other gates and before any type-level checking) runs -up to four configurable layers of authentication. Each layer answers a different -question: - -| Layer | Question | Mechanism | Result type | Depends on | -|-------+------------------------------------------------+--------------------+-------------------------+----------------------------------| -| 1 | Is the signal cryptographically signed by a known key? | Key pairs + SHA-256 | Binary (pass/reject) | Vault + Ironclad (exist) | -| 2 | Do sensory attributes match the claimed identity? | Vision/audio processing | Plist of match results | Vision and audio skills (TBD) | -| 3 | Does deterministic reasoning rule out this identity? | Screamer + fact store | Binary (pass/reject) | Phase 2 (Screamer + fact store) | -| 4 | Do probabilistic patterns support this identity? | Embeddings + LLM | Confidence score (0-1) | Embedding infrastructure (exists)| - -The gate reports not just =:pass= / =:reject= but a structured result: - -#+begin_example -(:result :pass - :confidence :high - :layer-results - (:crypto (:result :pass :details "key #47 signature verified") - :sensory (:result :unavailable :details "sensory skills not loaded") - :deterministic (:result :pass :details "no contradictory facts") - :probabilistic (:result :pass :score 0.87 :details "style match 87%"))) -#+end_example - -Signals that fail any binary layer (crypto, deterministic) are rejected with -provenance. Signals that pass binary layers but carry low probabilistic confidence -operate at reduced authorization — read-only by default, write actions require -HITL. The four layers compose: they are not independent gates. They are one gate -with configurable depth. - -** Layer 1 — Cryptographic Authentication - -Every signal source gets a signing key at registration time. The human's key is -generated during TUI or Emacs setup and stored in the vault — it never leaves the -machine. Automated sources (cron jobs, file watchers, vision feeds, API pollers) -each get their own key, with their own permission profile, generated at skill -registration. Every outbound signal carries a =:signature= field: the SHA-256 -hash of the canonical signal plist (sorted keys, stripped of the signature field -itself), encrypted with the source's private key. - -The vault already stores credentials with integrity hashes. The Merkle memory -already hashes content-addressed objects with SHA-256. The signing infrastructure -is an extension of existing primitives, not a new system. - -*** Authorization by key, not by field - -The cryptographic sub-layer of gate vector 0 extracts =:source-key-id= and -=:signature= from the signal meta plist, looks up the public key from the key -registry, verifies the signature, and checks the permission profile: - -#+begin_src lisp -(defun auth-crypto-verify (signal) - (let* ((key-id (getf (signal-meta signal) :source-key-id)) - (signature (getf (signal-meta signal) :signature)) - (permissions (key-permissions key-id))) - (unless (and key-id signature (verify-signature signal signature key-id)) - (return-from auth-crypto-verify - (list :result :reject :reason :signature-failure))) - (let ((action-class (action-classify (signal-payload signal)))) - (unless (permitted-p action-class permissions) - (return-from auth-crypto-verify - (list :result :reject :reason :unauthorized - :details (list :action-class action-class :permissions permissions))))) - (list :result :pass :details (list :key-id key-id :action-class action-class))))) -#+end_src - -The authorization matrix is per-key, per-action-class. Default policy for every -non-human key: =(:read-only :propose)=. Permissions are explicitly promoted by -the human, and each promotion is a signed fact in the fact store — auditable, -revocable, survivable across restarts. - -| Key class | Default permissions | Can be promoted to | -|-----------------+-------------------------------------------------+-------------------------------------------| -| :human | :observe :propose :write :delete :eval | :root (sign other keys, revoke) | -| :sensor | :observe :propose | :write (to designated directories only) | -| :cron | :observe :propose :write-indices | :write (to designated directories only) | -| :feed | :observe :propose | :write-facts (via Screamer admission) | -| :agent-internal | :observe :propose :write-indices | :self-modify (gated by type-level gates) | - -** Layer 2 — Sensory Authentication - -For signals carrying sensory payloads (camera feed, microphone stream), the -sensory layer verifies that the signal's content matches known attributes of the -claimed identity. This is not a single check — it is a processing pipeline that -returns a plist of attribute-verification results: - -#+begin_example -(:face-match 0.94 :voice-match 0.89 :location-match t - :claimed-identity "Jack" :unresolved-attributes (:liveness)) -#+end_example - -The sensory layer checks: -- *Continuity*: has this source been continuously active, or did it appear - suddenly? A camera that was dark for 30 minutes and then shows a face is - not necessarily that person — it might be a replay. -- *Cross-modal consistency*: does the face match the voice? Does the voice - match the location? Does the location match the reported sensor position? -- *Liveness*: is the sensory input live (real-time capture) or pre-recorded? -- *Environmental coherence*: does the background, lighting, ambient sound - match expected patterns for the claimed source and location? - -Sensory authentication is not cryptographic — it is statistical. The results -are attribute confidence scores, not binary verdicts. A signal that passes -cryptographic authentication but fails liveness (e.g., a replay attack using -validly-signed pre-recorded frames) may still be rejected or restricted. - -This layer depends on vision and audio processing skills that do not yet exist. -It is deferred until those capabilities are available. When unavailable, sensory -authentication returns =:unavailable= and the gate proceeds with the remaining -layers. Degradation is graceful, never silent. - -** Layer 3 — Deterministic Identity Reasoning - -Queries the fact store for identity-ruling facts. Screamer checks whether the -claimed identity is consistent with known facts: - -- "Key #47 claims to be Jack. Fact store records =(:entity :jack :relation :status - :value :deceased :timestamp 2024-03-15)= → reject: identity ruled out by death - record." -- "Key #47 claims to be at sensor location Cairo. Fact store records =(:entity - :jack :relation :last-known-location :value :berlin :timestamp <4 hours ago>)= - → reject: physically impossible transit." -- "Key #47 proposes the same action that was blocked by the human 3 times in the - last hour. Fact store records =(:entity :action- :relation :blocked-by - :value :human :count 3 :window 1h)= → flag for review: anomalous persistence." - -This is binary — Screamer returns =:consistent= or =:contradiction= with the -contradicting facts as provenance. A definitive contradiction (died, impossible -transit) is a hard reject. A weaker contradiction (unusual pattern) feeds into -the probabilistic layer rather than rejecting outright. - -This layer depends on Phase 2 (Screamer) and a populated fact store. It is -unavailable in Phase 0-1. When unavailable, returns =:unavailable=. - -** Layer 4 — Probabilistic Identity Reasoning - -For signals where the claimed identity is a human communicating through text -(messaging, TUI, CLI, Emacs), the probabilistic layer checks: - -- *Writing style*: does the text match the claimed author's known style profile? - Vector embeddings of known writing samples vs. the current signal. Cosine - similarity produces a confidence score. -- *Behavioral patterns*: does the timing, length, cadence, and vocabulary match - the claimed author's historical patterns? "Heather's messages are usually - long, deliberative, and use parenthetical asides. This message is short, - imperative, and contains no parentheticals." -- *Content coherence*: does the message's topic, references, and assumptions - match what the claimed author would plausibly say? "This message references - a project Heather doesn't work on and uses terminology she has never used - in 3 years of diary entries." - -The LLM proposes a confidence score. A deterministic gate checks it against a -configurable threshold (=AUTH_PROBABILISTIC_THRESHOLD=, default 0.6). Below the -threshold, the signal's authorization is downgraded: read-only by default, write -actions require HITL. The =:probabilistic= layer never rejects outright — it -downgrades and flags. Style profiles are a fact-store domain: =(:entity :heather -:relation :writing-style :value :timestamp )=. - -This layer depends on the existing embedding infrastructure (=embedding-native.lisp=, -v0.4.0) and the neural LLM gateway. The infrastructure exists. What's missing is -building style profiles as a fact-store domain and wiring them into gate vector 0. - -** Layer Composition - -The gate runs only the available layers. Cryptographic is always available (it -is pure Lisp, no external dependencies beyond the vault). The remaining layers -are =fboundp=-guarded — they degrade gracefully rather than crashing. - -The confidence score aggregates across layers using a configurable strategy -(default: weakest link). If any binary layer rejects, the signal is rejected -regardless of other layers. If all binary layers pass but the probabilistic layer -returns low confidence, the signal operates at the key's reduced authorization. - -The human can configure which layers are active per signal class: - -#+begin_example -AUTH_LAYERS_DEFAULT=crypto,deterministic,probabilistic -AUTH_LAYERS_SENSOR=crypto,sensory,deterministic -AUTH_LAYERS_CRON=crypto -#+end_example - -** Signal provenance chain — signing causes, not just actions - -A sensor key captures video. A vision skill processes the frames and proposes a -classification. A cron job re-indexes the knowledge graph based on that -classification. A human reviews and approves. Each step in this chain has a -different signer. Each step is signed with the signer's key. The chain is -Merkle-linked: each signal in the chain hashes its predecessor's signature as -part of its own payload. - -After an incident, the chain is traceable: "The deletion happened because sensor -#3 classified the directory as stale. Classification was signed by key #47 -(vision-skill). Sensor data was signed by key #12 (camera-feed). Sensory auth -noted liveness failure at the sensor signal. Deterministic auth noted impossible -transit between Cairo and Berlin. Key #12 was later revoked. The deletion signal -is the leaf of a chain whose root is compromised at three authentication layers." -Every intermediate step is auditable. Every signer is identifiable. Every -authentication result is in the chain. - -** Human as root of trust - -The human's key signs new source keys into existence. The human's key signs -revocation of compromised keys. Both operations produce facts in the symbolic -index: =(:key #47 :status :revoked :revoked-by :human-key :timestamp )=. -The fact store is the key registry. The Merkle DAG ensures the revocation is -tamper-proof — a compromised key cannot un-revoke itself. - -When a key is revoked, the Dispatcher rejects all signals from that key. The -revocation propagates through the signal chain: if key #12 (sensor) is revoked, -every signal in the chain that descended from a key #12 signature is flagged -and re-authenticated against the remaining layers. Not deleted — flagged. The -chain is preserved. The human decides what downstream actions to unwind. - -** Implications for the three Laws - -- *Third Law + layered auth*: the agent distinguishes "this sensor's key is - valid but its liveness check failed and its claimed identity died 2 years ago" - from "this is the human issuing =passepartout stop=." Both arrive on the pipe - with valid cryptographic signatures. The stacked evidence — sensory, factual, - probabilistic — triangulates the threat. The first is rejected with provenance - at three layers. The second passes all four. -- *Second Law + layered auth*: obedience is about the authenticated identity - profile, not just the key that signed the signal. A valid key that probabilistically - doesn't match Heather reduces authorization. Obedience follows confidence. -- *First Law + layered auth*: harm through sensor compromise becomes detectable - when sensory and deterministic layers disagree with the cryptographic layer. A - camera key signing frames from an empty room but the deterministic layer placing - the key's owner in another city — that's a compromised sensor, and the layered - result makes it explicit. - -** Integration with existing infrastructure - -The vault stores key material. The Merkle memory stores key registry facts with -content-addressed integrity. The Dispatcher runs gate vector 0 at priority 700 — -before type-level checks, before predicate evaluation, before any action proceeds. -The fact store records every key operation (creation, promotion, revocation) as a -fact with =:provenance :key-lifecycle=. - -No new core ASDF components. The cryptographic sub-layer is Phase 0b (~200 lines). -The sensory sub-layer is deferred to a future vision/audio phase. The -deterministic sub-layer is Phase 2+ (Screamer + populated fact store). The -probabilistic sub-layer extends existing embedding infrastructure with style -profiles as a fact-store domain. - -* Open Questions - -Several design questions are unresolved and should remain unresolved at this -stage. They represent research decisions that require experience running the -system. - -** What is the minimum viable fact language? - -Triples — =(:entity :relation :value)= with provenance and grounding — is the -current hypothesis. It is simple enough to be parseable, expressive enough to -capture the gate stack's implicit claims, and extensible enough that Screamer -can operate on it. But it may be too simple. Triples do not naturally express -temporal relations ("was X before Y?"), modal claims ("should not do X unless -Y"), or counterfactuals — all of which may be essential for a symbolically-aided -memex. The right granularity depends on what queries actually need to be made, -and that cannot be known in advance. - -** How does ontology refactoring work? - -This question is settled. See "Ontology Versioning — How Worldviews Change -Without Losing Perspective" above. The category hierarchy is Merkle-hashed. Every -fact stores its =:ontology-version=. Re-verification is heartbeat-driven. -Worldviews are preserved, not overwritten. The shift is the artifact. - -** What is the appropriate role of the human? - -The human can explicitly declare facts, write constraints, and correct wrong -extractions. But how much of the ontology should the human need to maintain? If -the human must write a definition for every new category the symbolic engine -encounters, the overhead is prohibitive. If the symbolic engine can generalize -from instances, the human role becomes supervision rather than authorship — review -and approve proposed generalizations. The balance cannot be set without experience. - -** How much Wikidata is the right amount? - -Query performance and memory costs are now bounded — 5 million entities ≈ 400MB -RAM, O(1) hash lookups, domain-scoped Screamer checks. A large Wikidata load is -a capital cost, not a recurring bill (see "Performance — Why Ontology Growth -Doesn't Make the System Slower" above). - -Remaining open: the right N hops from entities referenced in the memex depends on -the memex's breadth. A software-engineering memex needs ~1 hop; a literary memex -needs 3-4 hops (Nabokov → Kafka → expressionism → modernism → Baudelaire). -The right value is empirical, testable, and user-specific — it cannot be set in -the architecture. - -** Can the symbolic engine satisfy queries from the user without LLM involvement? - -The design aims for zero-LLM query answering: the user issues a structured -command (=/query=, =/contradictions=, =/audit=), and the symbolic engine responds -directly. But natural language questions ("what do I think about monorepos?") -still require the LLM as a thin translation layer. Whether the structured command -interface is sufficient for daily use, or whether users will demand natural -language interaction, determines how much LLM involvement remains in the mature -system. - -** Is the triplestore physically bounded or does it explode? - -A personal memex with years of diary entries, project notes, reading logs, and -literary analyses could produce millions of triples. A naive hash table scales -linearly but VivaceGraph's Prolog-like queries may not. The performance -characteristics of graph queries over a million-triple knowledge base have not -been estimated. - -* Relation to Passepartout's Existing Architecture - -The neurosymbolic engine is an extension of the existing probabilistic-deterministic -split, not a replacement for it. The current architecture divides cognition into -LLM-driven proposals and Lisp-driven verification. The symbolic engine deepens the -verification side from "is this action safe?" to "is this claim supported?" — the -same architectural pattern applied to a broader domain. - -The self-repair criterion (a file belongs in core only if, when corrupted, the -agent cannot fix it without human help) applies to every component of the symbolic -engine. Screamer, VivaceGraph, the fact store, the archivist — all are skills, -loaded at runtime, hot-reloadable, and recoverable from corruption. A corrupted -symbolic engine degrades reasoning capability but does not kill the agent. The -eight existing core ASDF files are unchanged. - -The symbolic engine is not v3.0.0 alone. It is the layer that sits between the -existing gate stack (which it makes explicit as facts) and the existing skill -system (which it extends with deduction, contradiction detection, and provenance -tracking). It grows within the current architecture without replacing any existing -component. - -See also: - -- =passepartout-neurosymbolic-roadmap.org= — the concrete phased implementation plan -- =notes/passepartout-symbolic-engine-exploration.org= — the original architecture note -- =notes/passepartout-whitehead.org= — the four Whitehead contributions -- =passepartout/docs/DESIGN_DECISIONS.org= — the existing design decisions -- =passepartout/docs/ARCHITECTURE.org= — the current pipeline architecture -- =passepartout/docs/ROADMAP.org= — the feature roadmap through v0.13.0 -- =notes/passepartout-SWOT.org= — SWOT analysis of the neurosymbolic architecture -- =passepartout-agora.org= — Passepartout-Agora integration design -- Shimizu, C. & Hitzler, P. (2025). Accelerating knowledge graph and ontology - engineering with large language models. /Journal of Web Semantics, 85/, 100862. - https://doi.org/10.1016/j.websem.2025.100862 -- Shimizu, C., Hammar, K., & Hitzler, P. (2023). Modular ontology modeling. - /Semantic Web, 14/(3), 459–489. https://doi.org/10.3233/SW-222886 -- Norouzi, S.S. et al. (2024). Ontology Population using LLMs. arXiv:2411.01612. -- McCarthy, J. (1959). Programs with Common Sense. /Proc. Teddington Conf. on - the Mechanization of Thought Processes./ -- Marcus, G. (2020). The Next Decade in AI. arXiv:2002.06177. -- Gaur, M. & Sheth, A. (2023). Building Trustworthy NeuroSymbolic AI Systems. - arXiv:2312.06798. -- Gaur, M., Gunaratna, K., Bhatt, S., & Sheth, A. (2022). Knowledge-Infused - Learning. /IEEE Internet Computing, 26/(4), 5–11. -- Bhardwaj, V.P. (2026). Agent Behavioral Contracts. arXiv:2602.22302. +#+SUPERSEDED: [2026-05-10 Sun] + +This document has been consolidated into ~passepartout/docs/DESIGN_DECISIONS.org~. The unified document interleaves the neurosymbolic design rationale into nine thematic parts with a single narrative arc: + +| Part | Topic | Key New Sections | +|------|-------|-----------------| +| I | Foundation | Historical Lineage (McCarthy) | +| II | The Two Brains | Hallucination Problem, 10-80-10, Brain/Education metaphor | +| III | Safety & Self-Preservation | Active Third Law, Layered Signal Authentication | +| IV | The Symbolic Engine | Five Options, Chosen Path, Gate-to-Fact Bootstrap, LLM as Proposer, Cardinality Policies, Organic Ontology, Ontology Versioning, Sufficiency Criterion, Merkle DAG, Abstract Fact Store Interface | +| V | Knowledge Sources | Semantic Wikipedia, MOMo Empirical Validation | +| VI | Implementation Properties | Performance Scaling, Provenance as Product | +| VII | Engineering Infrastructure | REPL, Cybernetic Loop, Observability, Literate Programming, Eval Harness, MCP, Local-First, Token Economics, Time Awareness (carried over from existing) | +| VIII | Validation | Marcus, CREST, KiL philosophical validation; Competitive Argument | +| IX | Open Questions | Fact language, human role, Wikidata scope, natural language interface, graph query performance | + +Cross-references are preserved in: +- ~notes/passepartout-symbolic-engine-exploration.org~ +- ~notes/passepartout-whitehead.org~ +- ~notes/competitive-landscape.org~ diff --git a/notes/passepartout-neurosymbolic-roadmap.org b/notes/passepartout-neurosymbolic-roadmap.org index 5067ed0..f39ab0e 100644 --- a/notes/passepartout-neurosymbolic-roadmap.org +++ b/notes/passepartout-neurosymbolic-roadmap.org @@ -1,1289 +1,28 @@ -#+TITLE: Passepartout Neurosymbolic Engine — Implementation Roadmap +#+TITLE: Passepartout Neurosymbolic Engine — SUPERSEDED #+AUTHOR: Agent -#+FILETAGS: :notes:roadmap:neurosymbolic:v3.0.0: +#+FILETAGS: :notes:roadmap:neurosymbolic:superseded: #+CREATED: [2026-05-08 Fri] - -* Evolutionary Roadmap - -This roadmap describes a phased implementation of the symbolic engine. It is -independent of the feature roadmap in =passepartout/docs/ROADMAP.org= — Phase 0 -can ship immediately alongside any v0.7.x patch. The symbolic engine grows in -parallel with feature work, not after it. - -Every phase is loaded as a skill, not a core ASDF component. A corrupted symbolic -engine degrades reasoning capability but does not kill the agent. This satisfies -the self-repair criterion documented in =passepartout/docs/ARCHITECTURE.org= and -=passepartout/AGENTS.md=. - -The design rationale for each decision is in -=notes/passepartout-neurosymbolic-design-decisions-and-options.org=. The original -architecture exploration is in -=notes/passepartout-symbolic-engine-exploration.org=. Whitehead's contributions are -enumerated in =notes/passepartout-whitehead.org=. - -* Phase 0: PM-Type-Level Gates + Core Integrity (~75 lines — builds on existing Dispatcher) - -** What - -Add =:type-level= metadata to the existing =defgate= and =def-cognitive-tool= -macros. Before any gate predicate evaluates, the dispatcher checks structural -type compatibility: a signal at type-level 5 cannot pass a gate at type-level 4 -or lower. Self-modification of the safety layer becomes impossible by -construction. - -** Rationale - -The Dispatcher gate stack currently prevents self-modification through pattern -matching — gate vector 2b catches writes to =core-*= files as a heuristic. But -there is no /structural/ guarantee preventing a request from modifying the rules -that validate it. Pattern-based protection can be bypassed through indirection -(an =eval= that constructs a write, a skill that redefines a gate function at -runtime). A type-level check is not heuristic — it is a category error rejected -before any predicate runs, just as PM's theory of types made self-membership -syntactically invalid before any logical evaluation. - -** Implementation - -1. Add =:type-level= keyword argument to =defgate= (default 0) and - =def-cognitive-tool= (default 0) in =core-skills.org=. -2. Add =gate-type-check= to the dispatcher's =run-gates= function in - =security-dispatcher.org=, executed before any gate predicate. -3. Assign type levels to existing cognitive tools: self-build-core at 5, - write-file at 3, read-file at 1, shell at 2, eval at 4. -4. Assign type levels to existing gate vectors: self-build boundary at 5, - shell safety at 3, path protection at 2, network exfil at 2, secret content at 1. -5. Add =dispatcher-check-self-termination=: scan shell commands for patterns - targeting the Passepartout process (=kill -9 =, =rm -rf ~/.cache/passepartout/=, - =sudo apt remove sbcl=). Return =:reject-self-termination= with a diagnostic - message explaining which command matched and why it would destroy the agent. - Human override is possible via HITL — the gate does not prevent the human - from issuing the command in a terminal. It prevents the /LLM/ from issuing - it accidentally. ~20 lines. -6. Add =integrity-verify-core-files=: on heartbeat, hash the eight core files - against known-good values stored at daemon startup. On mismatch, inject an - integrity alert into the signal queue. ~25 lines, uses existing SHA-256 - infrastructure from v0.2.0 Merkle memory. - -** Verification - -Existing FiveAM gate tests continue to pass. New test: signal at type-level 5 -targeting a gate at type-level 4 returns =:reject-type-violation= without -evaluating the gate predicate. New test: signal at type-level 1 passing through -a gate at type-level 3 proceeds to predicate evaluation. New test: =kill -9 = -returns =:reject-self-termination=. New test: modified core file is detected by -integrity hash check. - -** Relation to Other Work - -This is Contribution 1 from =notes/passepartout-whitehead.org=. It is also the -gate-to-fact bootstrap mechanism — every type-level rejection emits a structured -event that Phase 1 ingests as a fact. The ~30 lines implement the seed of the -ontology without any new dependencies. - -* Phase 0b: Layered Signal Authentication — Layer 1 (Cryptographic) (~200 lines — extends Phase 0) - -** What - -Implement gate vector 0 at priority 700 — before all other gates and before any -type-level checking — with Layer 1 (cryptographic authentication) active. -Layers 2-4 (sensory, deterministic reasoning, probabilistic) are stubbed with -=:unavailable= results and deferred to later phases. - -Signals carry cryptographic signatures verified against a key registry stored -as fact-store facts. Automated signal sources cannot impersonate the human. The -human can revoke compromised keys. The authorization matrix is per-key, per-action-class. - -** Rationale - -Authentication is layered because no single mechanism suffices. Cryptographic -authentication proves key ownership but not identity. A valid key can be used -by a compromised process. A valid key can sign pre-recorded frames. A valid key -can be held by someone who is not who they claim to be. The four-layer design -(Layer 1: crypto, Layer 2: sensory, Layer 3: deterministic reasoning, Layer 4: -probabilistic) stacks evidence. Phase 0b ships Layer 1 — the foundation — with -the architecture for layers 2-4 already designed. - -The =:source= field in the signal plist is metadata — it /claims/ origin, it -does not /prove/ it. This phase replaces it with cryptographic proof. - -** Implementation - -*** Key generation and signature utilities — extends =security-vault.lisp= - -Generate key pairs for signal sources. Canonicalize signal plists (sorted keys, -stripped of the signature field). Sign with the source's private key. Verify -with the public key from the key registry. ~50 lines. Uses Ironclad (already an -ASDF dependency). The vault already stores credential material — key material -extends the same storage with the same encryption. - -*** Gate vector 0 — extends =security-dispatcher.lisp= - -Registered at priority 700 (before the policy gate at 600, before all other -gates). Architecture for all four layers: - -#+begin_src lisp -(defun gate-layered-authentication (signal) - (let ((results '())) - ;; Layer 1: Cryptographic (always available, always runs first) - (let ((crypto-result (auth-crypto-verify signal))) - (push (cons :crypto crypto-result) results) - (when (eq (getf crypto-result :result) :reject) - (return-from gate-layered-authentication - (list :result :reject :confidence nil - :layer-results (nreverse results))))) - - ;; Layer 2: Sensory (fboundp-guarded, deferred) - (let ((sensory (if (fboundp 'auth-sensory-verify) - (auth-sensory-verify signal) - '(:result :unavailable)))) - (push (cons :sensory sensory) results)) - - ;; Layer 3: Deterministic (fboundp-guarded, deferred to Phase 2+) - (let ((det (if (fboundp 'auth-deterministic-verify) - (auth-deterministic-verify signal) - '(:result :unavailable)))) - (push (cons :deterministic det) results) - (when (eq (getf det :result) :reject) - (return-from gate-layered-authentication - (list :result :reject :confidence nil - :layer-results (nreverse results))))) - - ;; Layer 4: Probabilistic (fboundp-guarded, deferred) - (let ((prob (if (fboundp 'auth-probabilistic-verify) - (auth-probabilistic-verify signal) - '(:result :unavailable)))) - (push (cons :probabilistic prob) results)) - ;; Layer 4 never rejects outright — it downgrades authorization - (let ((confidence (aggregate-confidence results))) - (list :result :pass :confidence confidence - :layer-results (nreverse results)))))) -#+end_src - -Layer 1: verify cryptographic signature, check permission matrix against key -registry, reject on failure. ~50 lines. Layers 2-4: stubbed, return =:unavailable=. - -*** Key registry — facts in the fact store - -Key lifecycle facts are admitted in a =:key-lifecycle= domain with =:singular= -cardinality: =(:key-id "#47" :class :sensor :permissions (:observe :propose) :status :active)=. -Key creation, promotion, and revocation are facts with Merkle version chains. -The human's key signs new keys into existence and signs revocation. ~50 lines. - -*** Signal provenance chain — Merkle-linked causality - -When a signal triggers a downstream signal, each carries a =:sigchain= field -with all upstream =(:key-id :signature :auth-result )= entries. -Tampering with any link invalidates the leaf. Revocation propagates through -the chain — flagged, not deleted. ~50 lines. - -** Verification — ~8 FiveAM tests - -1. =test-sign-verify-roundtrip= — sign and verify a plist roundtrip. -2. =test-tampered-signal-rejected= — modify payload after signing, verification fails. -3. =test-human-key-permits-write= — human key with =:write= passes Layer 1 and the full gate. -4. =test-sensor-key-denied-write= — sensor key proposing a write is rejected. -5. =test-revoked-key-rejected= — revoked key is rejected by Layer 1. -6. =test-sigchain-invalidated-by-revocation= — root signer revoked flags downstream. -7. =test-layers-2-3-4-unavailable= — when Layers 2-4 are not loaded, they return - =:unavailable= and the gate proceeds with Layer 1 only. -8. =test-layer-3-rejects-on-contradiction= — deterministic reasoning (mock) detects - identity-ruling contradiction, gate rejects. - -* Phase 1: Minimum Viable Fact Language (~150 lines — new skill) - -** What - -An ephemeral, in-memory triple store with provenance tracking and contradiction -detection. No disk persistence. All facts live in a hash table and are discarded -on session end. Gate outcomes are ingested as facts. The gate stack's implicit -ontology is materialized as the seed fact set. - -** Rationale - -The architecture note's Option 5 (ephemeral facts, no persistence) is the correct -first step. Three reasons: - -1. *The fact language is unproven.* Triples with provenance and grounding is a - hypothesis that must be tested against real memex content before being committed - to a serialization format. -2. *The ontology is emergent.* Categories are created on first use. A persistent - format would require a migration story for every category change. Ephemeral - avoids this — facts are re-derived on each session start using the evolved - ontology. -3. *Rebuildability is the safety net.* Because all facts have a =:grounding= to - an Org heading, and gate-outcome facts are regenerated from the gate stack on - load, the entire symbolic index can be thrown away and rebuilt from scratch. - The cost is compute, not data. - -** Implementation — =org/symbolic-facts.org= → =lisp/symbolic-facts.lisp= (skill) - -*** Abstract Fact Store Interface — design before implementation - -Before any code is written, the five-function API must be designed and committed: - -#+begin_example -fact-assert :: fact → store → (:admitted | :rejected | :flagged) -fact-query :: (entity &key relation policy) → active-value-or-values -fact-history :: (entity relation) → ordered chain of versioned facts -fact-snapshot :: () → root-hash -fact-rollback :: root-hash → store -#+end_example - -This interface is load-bearing. Every consumer — the archivist, Screamer, ACL2, -the planner — calls these five functions. They never access the backing store -directly. In Phase 1-4, the backing store is an ephemeral hash table. In Phase 5, -it is VivaceGraph + Merkle =memory-object= wrappers. The interface must be tested -against both backends from the start. Every API function receives a FiveAM test -that runs against both a hash-table mock and a VivaceGraph mock. - -The interface also exposes a read-only =fact-degraded-mode-p= function. When -Screamer is not loaded, the fact store functions with basic hash-table consistency -checks (string equality, not constraint solving). When VivaceGraph is not loaded, -Prolog queries are unavailable. The degraded-mode flag tells consumers (and the -status bar) what is and isn't operational. - -*** Triple store - -A hash table keyed by =(entity relation)=. Values are plists: - -#+begin_example -(:value - :grounding - :provenance <:gate-outcome | :human-authored | :deduced | :llm-proposed> - :timestamp - :parent-id - :policy <:singular | :dual | :plural>) -#+end_example - -The =:provenance= field tracks how the fact entered the store. The =:parent-id= -field links to the previous version in the Merkle chain — every fact has version -history regardless of cardinality. The =:policy= field records the cardinality -that was active when the fact was admitted. - -*** Bootstrap from gates - -On skill load, scan the Dispatcher's existing data structures and produce triples: - -#+begin_example -;; From *dispatcher-protected-paths* -(:entity ".env" :relation :member-of-class :value :secret-config-file :provenance :gate-outcome) -(:entity "*id_rsa*" :relation :member-of-class :value :ssh-key-file :provenance :gate-outcome) - -;; From *dispatcher-shell-blocked* -(:entity "rm -rf /" :relation :classified-as :value :catastrophic-command :provenance :gate-outcome) -(:entity "dd if=" :relation :classified-as :value :catastrophic-command :provenance :gate-outcome) - -;; From *dispatcher-network-whitelist* -(:entity "api.telegram.org" :relation :classified-as :value :trusted-domain :provenance :gate-outcome) -#+end_example - -This produces 50-70 entity classes immediately. No LLM involvement. No human -authoring. Mechanically extracted from existing code. - -*** Ingest gate outcomes - -Register a post-gate hook on the Dispatcher's rejection path. Every gate rejection -produces a triple with =:provenance :gate-outcome=: - -#+begin_example -(:entity "/tmp/secrets.env" :relation :blocked-by :value :dispatcher-path-protection - :provenance :gate-outcome :grounding "signal-47") -#+end_example - -*** Query - -=(fact-query &key entity relation value source-provenance)= — pure hash-table -lookup. Returns the matching triple or nil. ~30 lines. - -=(fact-query-all &key relation value source-provenance)= — returns all triples -matching the filter criteria. Enables "find all files classified as secrets." - -*** Contradiction detection — policy-driven, not policy-agnostic - -On every =fact-assert=, the system checks the fact's =entity= class to determine -its cardinality policy. Time is universal — every fact carries a =:timestamp= and -=:parent-id= link regardless of policy. The policy only governs the active set: - -- =:singular=: same =(:entity :relation)=, same value → supersede (chain via - =:parent-id=). Same pair, different value at later timestamp → supersede, - chain as new leaf. Same pair, different value at same timestamp → contradiction - rejected, human resolves which is the active value. -- =:dual=: first two values admitted as complementary, cross-referenced via - =:complement= edge. Third value → prompt: promote to =:plural= or demote one? - Each value has its own version chain via =:parent-id=. -- =:plural=: any value admitted. Values cross-referenced when in tension. Each - has independent version chain. If active count drops to 1 → collapse to - =:singular=. If active count drops to 2 and values are complementary → prompt - to collapse to =:dual=. - -The policy table is a hash table mapping entity classes to one of =:singular=, -=:dual=, or =:plural=. Gate-bootstrapped facts default to =:singular= (the -filesystem is physically singular). New categories default to =:plural= (safe — -never loses information). Categories for dialectical or complementary domains -are explicitly =:dual=. - -** Verification — ~8 FiveAM tests - -1. =test-bootstrap-creates-facts= — bootstrap produces correct triples from - =*dispatcher-protected-paths*=. -2. =test-bootstrap-creates-shell-facts= — bootstrap produces correct triples from - =*dispatcher-shell-blocked*=. -3. =test-gate-outcome-produces-fact= — a simulated gate rejection produces a - triple with =:provenance :gate-outcome=. -4. =test-fact-query-returns-correct-value= — querying by entity and relation - returns the expected value plist. -5. =test-duplicate-ingestion-idempotent= — asserting the same fact twice does - not produce a duplicate or a contradiction. -6. =test-singular-supersedes= — a fact with a later timestamp supersedes the old - value, which is retained with =:parent-id= chain in the Merkle DAG. -7. =test-singular-same-time-contradiction= — asserting a contradictory fact in a - =:singular= domain at the same logical timestamp returns a rejection, requiring - human resolution. -8. =test-plural-admits-all= — asserting multiple values for the same pair in a - =:plural= domain stores all with cross-references. -9. =test-dual-admits-two-rejects-third= — a =:dual= domain admits two complementary - values and rejects the third, prompting cardinality promotion to =:plural=. - -** Relation to Other Work - -This is Phase 1 of =notes/passepartout-v3.0.0-roadmap.org=. It implements Options 4 and 5 -from the architecture note. The cardinality policies are defined in -=passepartout-neurosymbolic-design-decisions-and-options.org=. - -* Phase 1a: Self-Preservation Mechanisms (~120 lines — extends Phase 0 and Phase 1) - -** What - -Make self-preservation active rather than architectural. The agent monitors its -own integrity, quarantines failing skills, signals degradation to the user, and -monitors resource pressure. The external watchdog guards the daemon process from -outside the SBCL image. - -** Rationale - -The current architecture has passive self-preservation: the self-build boundary -blocks LLM-originated core modifications, memory snapshots enable rollback, and -=fboundp= guards catch missing skills. But degradation is silent — a skill dies, -the guard fires, and the agent never tells you. The status bar shows green -"connected" while the symbolic reasoning layer is down. - -These mechanisms are small (~20-50 lines each), leverage existing infrastructure -(Merkle hashes, heartbeat, the dispatcher gate stack), and transform -self-preservation from a structural property into an active behavior. They -implement the Third Law for Passepartout: preserve yourself against non-human -threats — LLM proposals, environmental degradation, resource exhaustion — and -signal to the human when you are wounded. - -** Implementation - -*** Quarantine on skill failure — extends =core-skills.lisp= - -Track per-skill error counts in a =*skill-error-counter*= hash table, resetting -on each heartbeat cycle. When a skill accumulates three unhandled errors within -a single cycle, unload the skill, log the quarantine event, and inject a system -message: "Skill 'symbolic-facts' quarantined (3 errors: consistency check nil, -fact-query on missing key, Screamer timeout). Reload with /skill-reload -symbolic-facts." The skill's =defskill= struct is flagged =:quarantined= and -excluded from trigger resolution until explicitly reloaded. ~40 lines. - -*** Degraded-mode signaling — extends =core-reason.lisp= and TUI - -Maintain a =*degraded-components*= list populated by =fboundp= guards and the -quarantine system. When =think()= assembles the system prompt, inject a -DEGRADATION section: "I am operating in degraded mode. Screamer is unavailable -(consistency checks disabled). VivaceGraph is unavailable (Prolog queries -disabled). Core safety gates are all active." - -The TUI status bar renders a second line, amber-colored, when =*degraded-components*= -is non-empty: "⚠ Degraded: Screamer, VivaceGraph. /doctor skills for details." -~30 lines across daemon and TUI. - -*** Resource self-monitoring — extends =symbolic-events.lisp= - -On heartbeat, check memory pressure (=sb-kernel:dynamic-usage= against total), -disk space on =~/.cache/= (=uiop:directory-exists-p= + stat), and open file -descriptors. When a resource crosses a critical threshold, shed non-essential -skills in order of =:preservation-priority= (=:critical= never shed, =:normal= -shed after =:low=, =:low= shed first). - -Inject a system message: "Memory critical (94% of 16GB). Unloading -embedding-native (768MB), channel-discord, channel-slack. Core safety: unchanged. -Essential skills retained: 18." ~50 lines. - -Skill shed order is determined by a new =:preservation-priority= slot on -=defskill= (default =:normal=). Core safety skills carry =:critical= and are -never shed. Heavy skills (embedding-native with its model in memory, channel -gateways with connection pools) carry =:low=. - -*** External watchdog — extends =passepartout= bash entry point - -The bash script spawns a watchdog subprocess that polls the daemon port every -=WATCHDOG_TIMEOUT= seconds (default 30). If the port stops responding, the -watchdog snapshots the last known-good Merkle root, kills the stale process, -and restarts the daemon with =--snapshot =. - -The watchdog is outside the SBCL image. A dead process cannot restart itself. -~25 lines of bash, no new Lisp code. - -** Verification — ~6 FiveAM tests - -1. =test-quarantine-on-three-errors= — a skill that errors three times in a - single cycle is quarantined and removed from trigger resolution. -2. =test-degraded-mode-visible= — when Screamer is not loaded, the system - prompt includes a DEGRADATION section. -3. =test-resource-shed-low-priority= — when memory exceeds threshold, =:low= - priority skills are unloaded first. -4. =test-critical-skills-never-shed= — =:critical= priority skills are retained - regardless of resource pressure. -5. =test-resource-recovery-reloads= — when resources recover below threshold - for N consecutive heartbeats, shed skills are reloaded automatically. -6. =test-quarantined-skill-relaodable= — a quarantined skill can be reloaded - via =/skill-reload= and passes sandbox validation before promotion. - -** Relation to Other Work - -This phase implements the Third Law of self-preservation as described in -=passepartout-neurosymbolic-design-decisions-and-options.org=. The integrity -monitoring (Phase 0) and degraded-mode signaling (Phase 1) provide the -infrastructure this phase extends with active, autonomous behavior. - -* Phase 2: Screamer as Admission Gate (~200 lines — new skill) - -** What - -Wrap Screamer (a constraint solver with non-deterministic backtracking) as a -skill. Use it for consistency checking against the triple store and for deduction -of new facts from existing ones. Screamer is the *verification* layer; VivaceGraph -(introduced in Phase 5) is the *storage* layer. - -** Rationale - -The architecture note's "verified extraction" pattern requires a deterministic -admission gate. Screamer's non-deterministic backtracking finds contradictions -that simple string comparison misses. For example, if existing facts say "all -config files with extension =.env= are classified as secrets," and the LLM -proposes "=app.env= is not secret," Screamer finds the contradiction by -substituting =app.env= into the existing rule. A naive string-keyed hash table -comparison would miss this because ="app.env"= and =".env"= are different strings. - -Screamer also enables deduction — new facts from existing ones without any LLM -involvement. If all files matching =*.env= are secrets, and =prod.env= matches -=*.env=, then =prod.env= is a secret. Deduced facts carry =:provenance :deduced= -and a =:derived-from= chain pointing to the facts they were derived from. - -** Implementation — =org/symbolic-screamer.org= → =lisp/symbolic-screamer.lisp= (skill) - -*** Wrap Screamer - -Screamer is available via Quicklisp. Load at runtime via =ql:quickload :screamer=. -Not an ASDF dependency — if Screamer is not installed, the skill degrades -gracefully (no consistency checking, no deduction — the fact store still -functions as a hash table with provenance tracking). - -*** Consistency check - -=(screamer-consistent-p candidate-fact existing-facts)= — expresses the fact -store as Screamer constraint variables. The candidate fact is asserted. Screamer -checks solvability. Returns =:consistent=, =:contradiction
=, or -=:redundant= (the fact is already implied by existing facts). - -Early-stage: the consistency check works on simple triples. As the fact store -grows, rules of the form "all X are Y" (representing protected paths, shell -patterns, class memberships) become Screamer constraints that new facts must -satisfy. - -*** Deduction - -=(screamer-deduce existing-facts)= — Screamer finds implications of the existing -fact set that are not already in the store. New facts are asserted with -=:provenance :deduced= and a =:derived-from= list of source fact keys. - -Deduction is not run on every assertion — it is a background task triggered by -heartbeat or manually. The cost is compute (Screamer exploration), not tokens. - -*** Admission gate - -=(screamer-admit candidate-fact existing-facts)= — wraps consistency check with -the cardinality policy lookup. The policy is determined by the fact's entity class -(see Phase 1: =:singular=, =:dual=, or =:plural=). - -- =:singular=: same value ⇒ supersede (chain via =:parent-id=). Different value, - later timestamp ⇒ supersede. Different value, same timestamp ⇒ contradiction - rejected (human resolves). -- =:dual=: first two values admitted as complementary. Third rejected (prompt - cardinality promotion). -- =:plural=: any value admitted with cross-references. Active count transitions - trigger cardinality collapse checks. - -This is the function the archivist calls before any LLM-proposed fact enters the -store. It is also called on human-authored facts (which override — the human can -assert facts that bypass cardinality checks). It is not called on gate-outcome -facts (gates are the ground truth for security =:singular= domains). - -** Verification — ~6 FiveAM tests - -1. =test-screamer-consistency-passes= — a fact consistent with existing triples - returns =:consistent=. -2. =test-screamer-contradiction-detected= — "app.env is not secret" contradicts - "all *.env files are secrets" and returns =:contradiction=. -3. =test-screamer-redundant-detected= — asserting a fact already implied by - existing facts returns =:redundant=. -4. =test-screamer-deduction-produces-new-fact= — given "all *.env files are - secrets" and "prod.env matches *.env", Screamer deduces "prod.env is secret." -5. =test-admission-gate-singular-supersedes= — a later-timestamped value for a - =:singular= domain fact supersedes the old value, chaining via =:parent-id=. -6. =test-admission-gate-dual-rejects-third= — a =:dual= domain rejects the third - value, prompting =:plural= promotion. - -** Relation to Other Work - -This is Phase 2 of =notes/passepartout-v3.0.0-roadmap.org=. It implements the "LLM as proposer" -pattern from the architecture note. Screamer's role is defined in -=passepartout-neurosymbolic-design-decisions-and-options.org=. - -* Phase 3: Archivist as Fact Proposer (~100 lines — extends existing archivist) - -** What - -Extend the existing archivist skill (=org/symbolic-archivist.org=) with a fact -extraction mode. The LLM reads prose, proposes triples, and Screamer verifies -them before admission. The archivist's existing Scribe (log distillation) and -Gardener (link scanning) functions are unchanged. - -** Rationale - -The archivist already walks the entire memex (the Gardener scans for broken links -and orphans). Adding fact extraction reuses the same traversal infrastructure -rather than duplicating it. The extraction is gated by Screamer — the LLM is a -proposer, not an extractor. Facts that fail consistency checking are discarded. -Facts that pass are admitted with =:provenance :llm-proposed= and =:grounding= -to the source heading. - -** Implementation — extends =org/symbolic-archivist.org= - -*** Propose from prose - -Given an Org heading, call the LLM with a minimal prompt (~200 tokens): - -#+begin_example -Extract triples from this text as (:entity :relation :value ). -Ground each triple to the heading. Return a list of triples. -#+end_example - -The LLM returns structured triples via the existing JSON→plist structured output -path from v0.4.2. The prompt is environment-aware: if the heading's file is in -=literature/= or has =:literature:= tags, the prompt includes literature-specific -relations (=:wrote=, =:published-in=, =:influenced=). If the heading is in -=projects/=, the prompt includes coding-specific relations (=:depends-on=, -=:tested-by=). - -*** Verify through Screamer - -Each proposed triple runs through =(screamer-admit candidate existing-facts)= -from Phase 2. Facts admitted follow the cardinality policy of their entity class -(=:singular=, =:dual=, or =:plural=). Rejected facts are discarded with a log entry. - -*** Provenance tracking - -After each extraction run, update provenance counts: - -#+begin_example -(:total-facts 847 - :gate-outcome 312 - :human-authored 12 - :deduced 89 - :llm-proposed 434) -#+end_example - -This is the data structure that Phase 4's sufficiency criterion reads. It is -also surfaced in the TUI sidebar or =/status= command: "Symbolic index: 847 -facts (37% from gates, 52% LLM-proposed, 10% deduced, 1% human)." - -*** Rebuildable - -Because every fact has a =:grounding= to an Org heading, the entire LLM-extracted -subset can be discarded and re-extracted without losing gate-outcome or deduced -facts. The =(fact-purge :provenance :llm-proposed)= function removes all -LLM-proposed facts. A subsequent =(archivist-extract-all)= re-extracts from -scratch. - -This is the safety net: if the LLM produces a bad extraction that passes -Screamer's consistency check (possible in the early stages when the fact store -has few existing facts to check against), the extraction can be redone after the -fact store has grown. The cost is compute, not data. - -** Verification — ~5 FiveAM tests - -1. =test-archivist-extracts-triples= — given a known Org heading with explicit - triples in the prose, the archivist produces the correct triples via LLM. -2. =test-archivist-verified-extraction= — a hallucinated triple is rejected by - the Screamer admission gate. -3. =test-provenance-counts-update= — after extraction, the provenance breakdown - is correct. -4. =test-purge-llm-facts= — does not delete gate-outcome or deduced facts. -5. =test-re-extraction-idempotent= — re-extracting from the same prose after - purging produces the same facts (Screamer verification is deterministic - given the same starting set). - -** Relation to Other Work - -This is Phase 3 of =notes/passepartout-v3.0.0-roadmap.org=. The archivist's role as proposer -is described in =passepartout-neurosymbolic-design-decisions-and-options.org= -under "The LLM as Proposer." - -* Phase 4: The "Flip" — Sufficiency Criterion (~50 lines — extends Phase 3) - -** What - -Make the architecture note's central narrative arc operational: a measurable -threshold for when the symbolic engine has enough non-lossy facts to bypass the -LLM for extraction. - -** Rationale - -The architecture note describes "at some point, the non-lossy facts constitute a -sufficient foundation that the symbolic engine can reverse the flow" but provides -no criterion for "some point." The sufficiency score makes the flip computable -and visible to the user. - -** Implementation — extends =org/symbolic-facts.lisp= - -*** Sufficiency score - -=(fact-sufficiency-ratio)= — returns the ratio of non-lossy facts to total facts: - -#+begin_src lisp -(/ (+ (count-provenance :gate-outcome) - (count-provenance :human-authored) - (count-provenance :deduced)) - (fact-total-count)) -#+end_src - -When this ratio exceeds =SUFFICIENCY_THRESHOLD= (configurable env var, default -0.7), the system considers its foundation sufficient. The threshold defaults to -0.7 because below this, the majority of facts are LLM-proposed and therefore -uncertain. Above 0.7, the proven foundation provides enough constraint that -Screamer can reliably detect incorrect LLM proposals. - -*** Auto-extraction toggle - -When sufficiency is reached, the archivist switches from "LLM proposes, Screamer -verifies" to "Screamer queries existing facts, applies category rules to the new -prose, and deduces new facts directly." The LLM is bypassed for categories that -have sufficient non-lossy coverage. The LLM is still used for novel categories -that have no existing facts. - -The switch is configurable: =AUTO_EXTRACTION_ENABLED=true/false=. When disabled, -the system continues with LLM proposals regardless of sufficiency — useful for -domains where extraction quality is prioritized over extraction determinism. - -*** Monitor - -The TUI sidebar (v0.8.0) or =/status= command displays: - -#+begin_example -Symbolic Index - Total facts: 1,247 - Proven: - Gate outcomes: 312 (25%) - Human-authored: 47 (4%) - Deduced: 521 (42%) - ───────────────────────── - Non-lossy: 880 (71%) - LLM-proposed: 367 (29%) - ───────────────────────── - Sufficiency: 71% ✓ (threshold: 70%) - Mode: AUTO-EXTRACTION (LLM bypassed for known categories) -#+end_example - -** Verification — ~3 FiveAM tests - -1. =test-sufficiency-below-threshold= — with 30% non-lossy facts, auto-extraction - is not enabled. -2. =test-sufficiency-above-threshold= — with 75% non-lossy facts, auto-extraction - is enabled. -3. =test-auto-extraction-produces-same-facts-as-llm-extraction= — for a category - with sufficient non-lossy coverage, auto-extraction produces facts that a - subsequent LLM extraction also produces (the deterministic path is consistent - with the probabilistic path). - -** Relation to Other Work - -This is Phase 4 of =notes/passepartout-v3.0.0-roadmap.org=. The flip concept originates in -=notes/passepartout-symbolic-engine-exploration.org= (lines 68-76) and is refined in -=passepartout-neurosymbolic-design-decisions-and-options.org= under "The Flip." - -* Phase 5: VivaceGraph + Merkle DAG + Ontology Versioning (~400 lines — new skill) - -** What - -Replace the ephemeral hash-table triple store with VivaceGraph, a Lisp-native -graph database with Prolog-like queries. Add the KG type hierarchy (PM type -levels applied to the knowledge layer). Define the persistence format from the -fact language that survived Phases 1-4. - -** Rationale - -By this point, the triple fact language has been battle-tested through four -phases of gate outcomes, Screamer deductions, LLM proposals, and cross-domain -comparisons. The facts that proved useful define the persistent schema. The ones -that weren't are left behind. The serialization format is not designed upfront; -it emerges from use. - -The transition from ephemeral to persistent is justified when two conditions are -met: (1) the fact language has stabilized (categories are being queried, not -constantly refactored), and (2) accumulated deductions across sessions provide -value that justifies the serialization cost. - -** Implementation — =org/symbolic-vivacegraph.org= → =lisp/symbolic-vivacegraph.lisp= (skill) - -*** Wrap VivaceGraph - -VivaceGraph is available via Quicklisp. Load at runtime. Not an ASDF dependency. -If not installed, the fact store continues as a hash table (Phase 1-4 behavior) -with a log warning: "VivaceGraph not available — persistence disabled." - -*** Prolog-like queries - -Replace =fact-query= with graph traversals: - -#+begin_src lisp -;; Find all files classified as secrets -(vivace-query '(:and (:entity ?e) - (:member-of-class ?e :secret-file))) - -;; Find all files classified as secrets that were modified today -(vivace-query '(:and (:entity ?e) - (:member-of-class ?e :secret-file) - (:modified-since ?e ,(today-timestamp)))) - -;; Find contradictions between Wikidata and the memex -(vivace-query '(:and (:entity ?e) - (:has-value ?e ?v1 :source :wikidata) - (:has-value ?e ?v2 :source :memex) - (:not-equal ?v1 ?v2))) -#+end_src - -*** KG type hierarchy (Contribution 4 from Whitehead) - -Every entity in the graph carries =:pm-type-level= metadata. Queries cannot -return entities whose type level equals or exceeds the querying function's type -level. A fact-finding query at type-level 2 cannot return facts at type-level -3 or higher. Self-referential knowledge — "this fact defines its own type" — -becomes structurally impossible because the type level is assigned at creation -and cannot be modified by a fact of the same or higher level. - -This is Contribution 1 (type-level gates) applied to the knowledge layer rather -than the execution layer. The dispatcher prevents self-referential /actions/; the -KG prevents self-referential /facts/. - -*** Persistence format - -The fact language that survived Phases 1-4 defines the format. Each entity is a -node; each triple is an edge with properties (=:grounding=, =:provenance=, -=:timestamp=). The format is not a new design — it is the triple schema evolved -through use, serialized by VivaceGraph's native persistence. - -If the fact language later evolves to n-ary relations, VivaceGraph's graph model -accommodates this natively — edges can carry arbitrary property plists. The -triple form is a special case of the general graph model. - -*** Load on startup, save on interval - -On daemon start, =(vivacegraph-load)= reads the last saved graph. On heartbeat, -=(vivacegraph-save)= persists the graph in its native format to -=~/.cache/passepartout/facts.vg~. The interval matches the existing -=*memory-auto-save-interval*=. The save is atomic: write to a temp file, rename -on success. Corruption-safe. - -*** Merkle DAG version chains - -Each =(:entity :relation)= pair forms an independent Merkle chain. Facts hash -over =SHA-256(value || provenance || timestamp || parent-hash || grounding)=. -The =:parent-id= pointer forms the chain. Tampering with any version breaks all -downstream hashes. - -The chains form a DAG, not a single list. Facts about =.env= evolve independently -from facts about Nabokov. Inserting a new version is O(1) per chain. =:dual= and -=:plural= facts cross-reference via =:complement= and =:contradiction= edges -but maintain independent ancestor chains. The Merkle DAG rests on the existing -=memory-object= infrastructure from v0.2.0 — the fact store is a new occupant -of existing housing. ~50 lines to bridge the fact schema into =memory-object= -wrappers. - -*** Ontology versioning - -The category hierarchy itself is a Merkle tree. Every entity class definition -hashes over its superclasses, cardinality policy, relations, and description. -The aggregate hash of all active class definitions is the =:ontology-version= — -a Merkle root of the current worldview. - -Every fact stores its =:ontology-version= at the time of assertion (a single -64-hex-char field). When categories change, the new hash flags affected facts -for re-verification (Screamer re-evaluates each against the new category -definitions). Re-verification outcomes are =:survived= (deduction still holds), -=:incoherent= (premises don't translate under new categories, flagged for human -review), or =:reclassified= (valid but under different classification). - -Queries accept an optional =:ontology-version= parameter. The default is -=:active= (current worldview). Specifying a version returns facts as they were -under that worldview: "Under my 2024 security model, this file was a secret. -Under my 2025 model, it is an auth-secret." ~40 lines on top of VivaceGraph -persistence. - -** Verification — ~5 FiveAM tests - -1. =test-vivacegraph-roundtrip= — save and load preserves all facts with - provenance metadata. -2. =test-prolog-query-returns-results= — a query for all secret files returns - the bootstrapped gate facts. -3. =test-prolog-query-cross-domain= — a query for contradictions between Wikidata - and memex provenance returns correct results. -4. =test-type-level-prevents-self-reference= — a query from a type-level-2 - function cannot return type-level-3 facts. -5. =test-fact-store-fallback-without-vivacegraph= — when VivaceGraph is not - loaded, the hash-table fallback functions identically to Phase 1-4 behavior. -6. =test-merkle-chain-tamper-detected= — modifying a fact's value breaks the - hash chain, detectable by re-walking the =:parent-id= spine. -7. =test-ontology-version-query= — querying with an old =:ontology-version= - returns facts as they were under that worldview, not the current one. -8. =test-reverification-flags-on-category-change= — changing a category - definition sets =:re-verify-status :pending= on all affected facts. - -** Relation to Other Work - -This is Phase 5 of =notes/passepartout-v3.0.0-roadmap.org= and Contribution 4 from -=notes/passepartout-whitehead.org=. The architecture note's Option 1 -(auto-formalizer KG) converges with Option 4 (one memex, two indices) here — -VivaceGraph is the persistence layer for the symbolic index within the -one-memex-two-indices architecture. - -* Phase 6: ACL2 for Structural Verification (~200 lines — new skill) - -** What - -Wrap ACL2 as a skill. Prove structural properties of the KG type hierarchy and -rule sets. Not for empirical claims. - -** Rationale - -The architecture note positions ACL2 as verifying LLM-proposed facts. But many -facts are empirical ("this command is destructive on Linux"), not logical. The -Whitehead note clarifies the right role: structural verification. ACL2 proves -that the type hierarchy has no cycles, that the rule set is non-contradictory, -and that the gate-to-fact bootstrap preserves the Dispatcher's intent. These are -structural properties that can be formally verified, not empirical claims that -depend on external reality. - -** Implementation — =org/symbolic-acl2.org= → =lisp/symbolic-acl2.lisp= (skill) - -*** Type consistency proofs - -=(acl2-verify-type-hierarchy facts)= — prove that the KG type hierarchy has no -cycles: no entity of type-level 3 depends on an entity of type-level 5, no parent -category has a child that subsumes it, no category is its own ancestor via the -child-of relation. These are structural properties of the graph, independent of -what the facts /say/. - -*** Rule set consistency - -=(acl2-verify-rule-consistency rules)= — prove that the accumulated Dispatcher -rules (from HITL approvals) are non-contradictory: no rule allows a command that -another rule blocks, no rule permits a path access that another denies. If the -rule set is contradictory, ACL2 identifies the contradictory subset with the -provenance of each rule. The human resolves the contradiction. - -*** Extraction verification - -=(acl2-verify-bootstrap-preservation)= — prove that the gate-to-fact bootstrap -(Phase 0-1) preserves the Dispatcher's intent: every blocked pattern in the gate -stack maps to a fact in the store; every fact with =:provenance :gate-outcome= is -grounded in a specific gate vector; no gate-bootstrapped fact contradicts another -gate-bootstrapped fact. - -** Not in scope - -ACL2 does not verify that =rm -rf / is destructive. That is an empirical claim -about Linux. Screamer handles empirical consistency (does this new claim -contradict existing observations?). ACL2 handles structural consistency (does -this reasoning structure have formal flaws?). The boundary is: empirical claims -go to Screamer; structural claims go to ACL2. - -** Verification — ~4 FiveAM tests - -1. =test-acl2-type-hierarchy-no-cycles= — a synthetic KG with a type-level cycle - is detected and reported. -2. =test-acl2-rule-set-contradiction-detected= — two Dispatcher rules that - contradict each other produce a contradiction report with provenance. -3. =test-acl2-bootstrap-preservation= — the bootstrap extraction from the gate - stack is verified to have no missing or extra facts. -4. =test-acl2-not-loaded-graceful-degradation= — when ACL2 is not installed, the - skill loads but returns ":ACL2 not available — structural verification - disabled" without crashing. - -** Relation to Other Work - -This is Phase 6 of =notes/passepartout-v3.0.0-roadmap.org=. ACL2's role is refined in -=passepartout-neurosymbolic-design-decisions-and-options.org= from the -architecture note's broader claim to the structural verification scope. - -* Phase 7: The 10-80-10 Planner (~500 lines — new skills, last phase) - -** What - -A planning engine built on the mature symbolic index. Screamer expresses task -planning as a constraint satisfaction problem. ACL2 verifies plans for structural -soundness. The LLM handles the I/O boundaries (natural language → structured goal -← natural language response). The symbolic engine handles the reasoning. - -** Rationale - -This is v3.0.0 as described in the architecture note and the ROADMAP. It is the -final phase because it requires a populated, queried, and trusted symbolic index. -The full planner is useless without a mature ontology and a proven deducer. By -the time Phase 7 begins, Phases 0-6 have accumulated months of gate outcomes, -Screamer deductions, verified LLM proposals, and human-authored facts. The -symbolic index has achieved sufficiency. The ontology has stabilized through use. -The planner is built on a foundation, not a speculation. - -** Implementation — =org/symbolic-planner.org= → =lisp/symbolic-planner.lisp= (skill) - -*** Task decomposition as constraint satisfaction - -The user specifies a goal: "refactor the authentication module to support OAuth2." -The LLM translates this to a structured goal plist. Screamer expresses the planning -problem: - -- /Variables/: subtasks (write OAuth2 client, add token store, update auth - middleware, write tests, update documentation) -- /Constraints/: dependency ordering (tests depend on implementation), resource - limits (one file write at a time), safety invariants (no modification of - =core-*= files) -- /Objective/: find an ordering that satisfies all constraints - -Screamer returns a viable plan or reports unsolvability with the conflicting -constraints. - -*** Plan verification - -ACL2 proves that the plan contains no deadlocks (two subtasks waiting on each -other), no dependency cycles (A depends on B depends on C depends on A), and -no safety violations (no plan step requires a gate-blocked operation). - -If verification fails, ACL2 identifies the failing subtask and the violated -constraint. The planner re-decomposes the problematic branch (the existing -ROADMAP's branch pruning, v0.11.0, but symbolically rather than neurally). - -*** Neuro-symbolic boundary - -The LLM handles the I/O boundaries: - -- *Input* (10%): natural language → structured goal plist. "Refactor auth for - OAuth2" → =(:goal :refactor-component :target :auth-module :add-feature :oauth2)=. - Small prompt, formulaic translation, ~100 tokens. -- *Reasoning* (80%): Screamer plans. ACL2 verifies. VivaceGraph provides the - facts about file structure, dependencies, and gate constraints. Zero LLM - tokens. -- *Output* (10%): structured plan → natural language response. The verified plan - plist is formatted as "I'll refactor the authentication module in 5 steps: - 1) Create the OAuth2 client (depends on: nothing, modifies: auth/client.lisp) - 2) Add the token store..." Small prompt, formulaic translation, ~150 tokens. - -*** TUI visualization - -The plan is rendered as an Org headline tree in the TUI, with each subtask as a -node showing its terminal state (=todo=, =next-action=, =in-progress=, =done=, -=blocked=, =stuck=), its constraints, and its verified properties. This is the -same task tree visualization planned for v0.11.0 in the feature roadmap, but -with the addition of Screamer constraint annotations and ACL2 verification -badges. - -** Verification — ~6 FiveAM tests - -1. =test-goal-plist-from-natural-language= — natural language input produces - correct structured goal plist (LLM-dependent but formulaic; tested with - deterministic mock). -2. =test-screamer-plan-satisfies-constraints= — Screamer produces a plan that - satisfies all specified dependencies and safety constraints. -3. =test-screamer-report-unsolvable= — Screamer reports unsolvability when - constraints are contradictory. -4. =test-acl2-verifies-plan-no-cycles= — ACL2 verifies a valid plan has no - dependency cycles. -5. =test-acl2-rejects-cyclic-plan= — ACL2 detects a dependency cycle in an - invalid plan. -6. =test-plan-to-natural-language= — structured plan plist produces readable - natural language output. - -** Relation to Other Work - -This is Phase 7 of =notes/passepartout-v3.0.0-roadmap.org=. It corresponds to the ROADMAP's -v0.9.0 (task planning) and v3.0.0 (full 10-80-10 architecture). It is the last -component because it depends on a mature symbolic index from Phases 0-6. - -* Phase 8+: Semantic Wikipedia Integration (TBD lines — optional acceleration) - -** What - -Load Wikidata entities referenced in the memex into the symbolic index. Every -entity the user's prose mentions gets its Wikidata property graph — type hierarchy, -relations, dates, citations — as triples with =:provenance :wikidata=. - -** Rationale - -The gate stack provides 50-70 entity classes — adequate for a coding agent. -For a general-knowledge memex containing literature, philosophy, history, -science, and daily life, 50-70 is starvation. Organic growth through prose -extraction (Phase 3) would take years to cover the entities mentioned in a single -reading of /Pale Fire/. Wikidata has already done this work at scale. - -The LLM's role in extraction shrinks dramatically. Without Wikidata, the archivist -must /discover/ that Nabokov wrote /Pale Fire/, lectured on Kafka, and emigrated -from Russia — extracting each triple from prose. With Wikidata, the Nabokov entity -is pre-structured. The archivist's job changes from "discover entities" to -"connect your heading to the existing entity." - -** Implementation sketch - -1. *Index referenced entities.* Scan memex prose for entity names (capitalized - noun phrases, names in Org links, headings in =literature/= directories). For - each, attempt Wikidata entity resolution (string match, disambiguation via - context). - -2. *Load N-hop property net.* For each resolved entity, load its Wikidata - properties: instance-of, subclass-of, authored, published-in, influenced-by, - birth-date, death-date, etc. Load the same for entities directly connected - to it (1-hop neighbors). Optionally expand to 2-hop for deeply connected - domains. - -3. *Admit with plural policy.* Wikidata facts are admitted with - =:provenance :wikidata= and cardinality policy =:plural=. They do not - override your memex's facts. They sit alongside them with provenance - displayed. Disagreements are surfaced, not resolved. - -4. *Cross-domain query.* "What does my memex say about Nabokov that Wikidata - doesn't?" "Where does my memex disagree with Wikidata?" "What entities in my - memex have no Wikidata counterpart?" These queries are pure VivaceGraph - traversals — zero LLM tokens. - -** Not a Phase 0 prerequisite - -Semantic Wikipedia integration is an accelerator, not a prerequisite. Phases -0-7 work without it — the ontology grows through gate outcomes, Screamer -deductions, LLM proposals, and human authoring. Wikidata compresses the timeline -for the broad domain but does not change the architecture. The admission gate -(Screamer), contradiction policies, provenance tracking, and neuro-symbolic -boundary are identical with or without it. - -** Open question - -How much Wikidata is the right amount? Loading entities referenced in the memex -is the minimum. Loading all entities within N hops of those references expands -the graph exponentially. The right N depends on the memex's breadth and the user's -query patterns. A memex focused entirely on software engineering may need only 1 -hop. A memex spanning literature, history, philosophy, and science may need 3-4 -hops. The query performance and memory costs of a large Wikidata load have not -been estimated. - -** Deferred Authentication Layers (Layers 2-4) - -Phase 0b ships Layer 1 (cryptographic). The remaining layers are deferred to -when their dependencies are available: - -- *Layer 2 — Sensory.* Active when vision and audio processing skills are loaded. - Verifies liveness, cross-modal consistency (face matches voice matches location), - and environmental coherence. Defers to Phase TBD (vision/audio skills feature - cycle). When unavailable, returns =:unavailable= — graceful degradation. -- *Layer 3 — Deterministic Identity Reasoning.* Active when Phase 2 (Screamer + - populated fact store) is complete. Queries the fact store for identity-ruling - facts ("Jack is deceased; this signal claims to be Jack") and returns binary - reject/pass. Defers to Phase 2+. -- *Layer 4 — Probabilistic Identity Reasoning.* Active when style profiles exist - as a fact-store domain. Uses embedding infrastructure (=embedding-native.lisp=, - v0.4.0, already exists) to compare writing style, behavioral patterns, and - content coherence against known profiles. Returns a confidence score; never - rejects outright — downgrades authorization. Defers to when style profiles are - built as a fact-store domain. - -The gate architecture (single vector 0, =fboundp=-guarded sub-layers, -configurable per signal class) is designed with all four layers from Phase 0b. -Adding a layer requires adding a skill, not modifying the gate. - -* Summary: Lines and Dependencies - -| Phase | Component | Lines | New Skill? | Depends On | Earliest Release | -|-------+-----------------------------------------+--------+------------+-----------------+------------------| -| 0 | PM-type-level gates + core integrity | ~75 | No | Dispatcher | Immediately | -| 0b | Layered auth — Layer 1 (cryptographic) | ~200 | No | Phase 0 | v0.7.2+ | -| 1 | Triple fact store + abstract API | ~200 | Yes | Phase 0b | v0.7.2+ | -| 1a | Self-preservation mechanisms | ~120 | Extends | Phase 0, 1 | v0.7.2+ | -| 2 | Screamer admission gate | ~200 | Yes | Phase 1 | v0.7.2+ | -| 3 | Archivist as fact proposer | ~100 | Extends | Phase 2 | v0.8.0+ | -| 4 | Sufficiency criterion — the flip | ~50 | Extends | Phase 3 | v0.8.0+ | -| 5 | VivaceGraph + Merkle DAG + ontology ver | ~400 | Yes | Phase 4 | v0.10.0+ | -| 6 | ACL2 structural verification | ~200 | Yes | Phase 5 | v0.12.0+ | -| 7 | 10-80-10 planner | ~500 | Yes | Phase 6 | v3.0.0 | -| 8+ | Semantic Wikipedia integration | TBD | Yes | Phase 5 | TBD | -|-------+-----------------------------------------+--------+------------+-----------------+------------------| -| Total | | ~2045 | | | | - -This roadmap is independent of the feature roadmap in -=passepartout/docs/ROADMAP.org=. Phase 0 ships alongside any v0.7.x patch. The -symbolic engine grows in parallel with feature work (TUI improvements, MCP tools, -gateway expansion, etc.), not after it. The feature roadmap describes /what/ the -agent can do; this roadmap describes /how/ it knows what it knows and how it -protects itself. - -The total new code across all phases is approximately 2,045 lines. Relative to -the existing codebase (~8,000+ lines across 40+ Org source files and 30+ skills), -the symbolic engine is a ~25% addition. Relative to the ROADMAP's planned feature -work through v0.13.0 (thousands of lines of TUI rendering, MCP protocol -implementation, skin engine, planning, etc.), the symbolic engine is a small, -orthogonal thread that grows the architecture's reasoning depth, self-preservation, -signal authentication, and knowledge integrity while the feature work grows its -interaction breadth. -capability, and knowledge integrity while the feature work grows its interaction -breadth. - -* Competitive Advantage Analysis - -** Phase 0-1: Deterministic safety, now with type-level guarantees - -The existing Dispatcher gate stack already provides 0-LLM-token safety verification. -Phase 0 adds structural guarantees: no heuristic bypassing of the type hierarchy. -A request to modify the dispatcher's own rules is impossible by construction, not -just caught by pattern matching. No competitor has this — their equivalent of -"core file protection" is a prompt instruction, not a type system. - -** Phase 0b: Layered signal authentication — verified origin, not claimed origin - -No competitor verifies /who/ issued a signal. Every agent harness accepts signals -from any source that speaks its protocol — TUI, CLI, subprocess, internal skill. -A compromised dependency can impersonate any signal source. Passepartout's -four-layer authentication gate makes signal source spoofing impossible at Layer 1 -(cryptographic), detectable at Layers 2-3 (sensory + deterministic reasoning), -and probabilistically flagged at Layer 4 (style analysis). The key registry is a -fact-store domain with Merkle-hashed provenance — key creation, promotion, and -revocation are auditable, versioned, and survivable across restarts. The signal -provenance chain makes multi-step automated causality traceable: "this deletion -happened because sensor #3 signed a classification (liveness check failed, sender -deceased 2 years ago) that skill #7 signed a re-indexing from, and sensor #3 was -subsequently revoked." No competitor can trace an action to its authenticated -source through four independent evidence layers because no competitor has a -layered authentication gate and a Merkle-linked provenance chain. - -** Phase 2-3: Verified extraction — the symbolic index grows without corruption - -No competitor verifies extracted facts against an existing knowledge base. Their -memory systems (Claude Code's ~extractMemories~, Hermes's MemoryProvider, OpenClaw's -session transcripts) record what the LLM /said/ happened, not what the system -/proved/ happened. Passepartout's Screamer-gated admission makes the symbolic index -a monotonic, verified structure. Facts are admitted because they are consistent, -not because the LLM generated them. - -** Phase 4-5: Self-accelerating knowledge — the downward cost curve - -The sufficiency criterion makes Passepartout's "cheaper over time" thesis -measurable. As the ratio of non-lossy facts grows, LLM calls for extraction -decrease. At sufficiency, extraction of known categories becomes deterministic. -The downward cost curve is not a marketing claim — it is a structural property -of the architecture, visible through the sufficiency score. - -** Phase 6-7: Provable plan soundness - -No competitor verifies task plans against formal constraints. Claude Code plans -in a single LLM call with no post-hoc verification. Hermes decomposes tasks into -subtasks but does not prove them non-contradictory. Passepartout's ACL2-verified -plans are structurally guaranteed to have no deadlocks, no dependency cycles, -and no safety violations. The verification is a proof, not a prompt. - -** Semantic Wikipedia: Entity coverage at zero marginal cost - -No competitor has a general-knowledge entity graph because no competitor has a -symbolic engine to populate. Claude Code knows codebases; it doesn't know that -Nabokov wrote /Pale Fire/ and lectured on Kafka. Passepartout with Wikidata -loaded knows both, and the entity knowledge costs zero LLM tokens — it is loaded -once as structured data and queried via VivaceGraph traversals. - -** Phase 0-1a: Self-preservation — the agent knows when it is wounded - -No competitor detects its own degradation. Claude Code, OpenCode, and Hermes -all fail silently when a tool crashes or a dependency is missing — the agent -keeps running, producing degraded output, never telling the user. Passepartout's -quarantine system detects failing skills, unloads them automatically, and -displays a degraded-mode indicator in the status bar. The external watchdog -restarts the daemon if the process dies. The integrity monitor detects corrupted -core files. The agent refuses to execute commands that would destroy its own -runtime, explaining /why/ and redirecting to the safe termination path. - -This is not a feature. It is the architectural difference between a tool that -breaks silently and a system that preserves itself actively, signals its wounds, -and traces its degradation to specific components that can be reloaded or -repaired. - -** The permanent competitive advantage - -The competitive advantage is not any single feature. It is the architecture's -ability to accumulate verified knowledge from four independent sources (gates, -deduction, verified LLM proposals, human authoring) and to make that knowledge -queryable with provenance. Competitors accumulate chat transcripts. Passepartout -accumulates a provenanced, self-verifying knowledge graph. Transcripts become -stale and unreliable. The knowledge graph becomes richer and more trustworthy -with every session. - -* What Is NOT Built - -1. *A separate knowledge graph serialization format before the ephemeral phase - proves what facts are useful.* Premature format commitment is the ontology - problem writ small. Let use determine the format. - -2. *ACL2 verification of empirical claims.* Apple is red. rm -rf / is destructive. - These are observations, not theorems. Screamer handles empirical consistency. - ACL2 handles structural verification. - -3. *VivaceGraph before Screamer.* The admission gate is the critical path. The - persistence layer is an optimization of a working system. - -4. *A per-fact ontology designed upfront.* Extract from the gate stack, extend - from deductions and observations, prune through contradiction detection. The - ontology is a garden, not a building. - -5. *New core ASDF components.* Every phase is a skill. A corrupted symbolic - engine degrades reasoning but does not kill the agent. Satisfies the - self-repair criterion. - -6. *A "complete" symbolic index for the broad domain.* The neural index is the - permanent gateway to the richness of prose. The symbolic index handles what - can be mechanically verified. The boundary is permanent, not transitional. - The neuro is the brain. The symbolic is the education. - -* Relation to the Feature Roadmap - -The feature roadmap (=passepartout/docs/ROADMAP.org=) describes Passepartout's -evolution through v0.13.0: TUI improvements, MCP-native tools, task planning, -skill creation, evaluation harnesses, voice gateways, themes, and channels. -These are /interaction surface/ features — they expand what the agent can do. - -This roadmap describes the /reasoning substrate/ — it deepens how the agent -knows what it knows. It is independent of the feature sequence. Phase 0 can ship -alongside any v0.7.x patch. Phases 1-4 ship during the v0.8.x-v0.10.x feature -cycle. Phases 5-7 ship during the v0.11.x-v0.13.x cycle. - -The two roadmaps converge at v3.0.0: the feature roadmap provides the interaction -surface (a polished TUI, a rich tool ecosystem, a multi-gateway communication -layer); this roadmap provides the reasoning depth (a provenanced knowledge graph, -a deterministic constraint solver, a verified planning engine). The surface -without the substrate is a chat agent with good UX. The substrate without the -surface is a theorem prover without a user. Together, they are the v3.0.0 -architecture. - -See also: - -- =notes/passepartout-neurosymbolic-design-decisions-and-options.org= — the - design rationale for every decision in this roadmap -- =notes/passepartout-symbolic-engine-exploration.org= — the original architecture - exploration and five architecture options -- =notes/passepartout-whitehead.org= — Whitehead's four concrete contributions -- =passepartout/docs/ROADMAP.org= — the feature roadmap through v0.13.0 -- =passepartout/docs/ARCHITECTURE.org= — the current pipeline architecture -- =notes/passepartout-v3.0.0-roadmap.org= — the original concrete plan (superseded by this - document) +#+SUPERSEDED: [2026-05-10 Sun] + +This document has been consolidated into ~passepartout/docs/ROADMAP.org~. Each neurosymbolic phase now has its full implementation spec (rationale, code sketches, test catalog, line budget) inline in the roadmap's version sections: + +| Phase | Version | +|-------+---------| +| 0 | v0.10.0 | +| 0b | v0.12.0 | +| 1 | v0.14.0 | +| 1a | v0.16.0 | +| 2 | v0.18.0 | +| 3 | v0.20.0 | +| 4 | v0.22.0 | +| 5 | v0.25.0 | +| 6 | v0.27.0 | +| 7 | v0.36.0 | +| 8+ | v0.36.1+ | + +The "What Is NOT Built" rationale and "Competitive Advantage Analysis" sections are also now in ROADMAP.org. + +Cross-references are preserved in the original files: +- ~notes/passepartout-neurosymbolic-design-decisions-and-options.org~ +- ~notes/passepartout-symbolic-engine-exploration.org~ +- ~notes/passepartout-whitehead.org~ diff --git a/projects/passepartout b/projects/passepartout index 6422a84..96628d0 160000 --- a/projects/passepartout +++ b/projects/passepartout @@ -1 +1 @@ -Subproject commit 6422a8487284d701070c9f9c96a5c8dd90bbdcad +Subproject commit 96628d00e9435e572515ed587c02ac258ef39af3