fpf-thinking-map 1.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fpf_thinking_map/FPF_AUDIT_RESPONSE.md +88 -0
- fpf_thinking_map/FPF_FLOOR_MAP.md +119 -0
- fpf_thinking_map/FPF_SOURCE_TO_CODE_RELATION_AUDIT.md +91 -0
- fpf_thinking_map/README.md +266 -0
- fpf_thinking_map/REJECTED_C32_CANDIDATE_SYNTHESIS.md +62 -0
- fpf_thinking_map/REJECTED_NQD_OEE_CULTURAL_EVOLUTION.md +64 -0
- fpf_thinking_map/SOURCES.md +73 -0
- fpf_thinking_map/WHY_THIS_EXISTS.md +92 -0
- fpf_thinking_map/__init__.py +81 -0
- fpf_thinking_map/examples.py +564 -0
- fpf_thinking_map/guards.py +314 -0
- fpf_thinking_map/logic.py +444 -0
- fpf_thinking_map/primitives.py +454 -0
- fpf_thinking_map/py.typed +0 -0
- fpf_thinking_map/state.py +535 -0
- fpf_thinking_map/traversal.py +359 -0
- fpf_thinking_map/verify.py +1008 -0
- fpf_thinking_map-1.2.1.dist-info/METADATA +216 -0
- fpf_thinking_map-1.2.1.dist-info/RECORD +22 -0
- fpf_thinking_map-1.2.1.dist-info/WHEEL +5 -0
- fpf_thinking_map-1.2.1.dist-info/licenses/LICENSE +33 -0
- fpf_thinking_map-1.2.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# FPF Source-to-Code Relation Audit — Response
|
|
2
|
+
|
|
3
|
+
Reviewer: prichindel.com
|
|
4
|
+
Date: 2026-06-24
|
|
5
|
+
Input: `FPF_SOURCE_TO_CODE_RELATION_AUDIT.md` (50 items)
|
|
6
|
+
|
|
7
|
+
## Summary verdict
|
|
8
|
+
|
|
9
|
+
The audit is accurate. All 50 items are real findings — no false positives. The question is which ones to fix, which to accept as intentional compression, and which to defer.
|
|
10
|
+
|
|
11
|
+
The guiding principle: **this package is a compiled thinking map, not a FPF reimplementation**. We extracted 8 objects from a 51k-line spec. Every compression was a conscious trade: less fidelity to the source, more usability for a mid-tier model chewing a per-move slice.
|
|
12
|
+
|
|
13
|
+
The audit correctly identifies where compression crossed into **wrong-shape** (we said something the spec forbids) vs **missing** (we left something out). Wrong-shape must be fixed. Missing is a judgment call.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Category 1: Fix now (wrong-shape or high-value missing, no runtime bloat)
|
|
18
|
+
|
|
19
|
+
These items either violate the source spec in a way that produces incorrect behavior, or are cheap to fix without widening the per-step chew.
|
|
20
|
+
|
|
21
|
+
| ID | What | Why fix | How |
|
|
22
|
+
|----|------|---------|-----|
|
|
23
|
+
| **R02** | `parent_context_id` encodes forbidden context containment | The FPF spec explicitly says "contexts do not form holarchies with each other." Our field contradicts this. | **Remove `parent_context_id` from `ContextPrimitive`.** Cross-context relation goes through bridges only. |
|
|
24
|
+
| **R40** | Gate lattice missing `BLOCK`; `ABSTAIN` overloaded as both "insufficient info" and "hard denial" | Source gate lattice is `abstain ≤ pass ≤ degrade ≤ block`. Our `ABSTAIN` conflates two distinct outcomes. | **Add `GateDecision.BLOCK` to the enum.** `ABSTAIN` = insufficient evidence (can be resolved). `BLOCK` = hard denial (cannot proceed). Update gate evaluation and guards. |
|
|
25
|
+
| **R30** | `WorkPrimitive(kind=PLAN)` compresses `WorkPlan` into `Work` | Source explicitly separates `U.Work` (occurrence) from `U.WorkPlan` (intent). Our `WorkKind` enum masks a real type distinction. | **Split into `WorkPrimitive` (enactment only) and `WorkPlanPrimitive` (planning only).** Drop `WorkKind` enum — the type IS the distinction. |
|
|
26
|
+
| **R05** | Context invariants stored but never enforced | Invariants are strings that nothing reads. They exist in the prompt state but are not checked by guards or logic. | **Add invariant-check guard** that evaluates invariant expressions against the current state. Even if invariants stay semi-formal (strings the LLM evaluates), they should at least appear in the guard/logic path, not just in the glossary dump. |
|
|
27
|
+
|
|
28
|
+
## Category 2: Fix next round (genuine gaps, but require design thought)
|
|
29
|
+
|
|
30
|
+
These items are real structural absences. Fixing them adds value but requires deciding on shape. Queue for next pass.
|
|
31
|
+
|
|
32
|
+
| ID | What | Why next round | Shape sketch |
|
|
33
|
+
|----|------|---------------|-------------|
|
|
34
|
+
| **R07/R08** | No first-class `RoleAssignment` — roles bound directly via runtime IDs | The audit is right: FPF has `U.RoleAssignment` as a distinct object that binds holder to role inside a context with a time window. Our `actor_role_ids` is a shortcut. | Add `RoleAssignment` dataclass with `holder_id`, `role_id`, `context_id`, `window`. `RuntimeBinding` references assignments, not raw role IDs. `active_roles` resolves from assignments. |
|
|
35
|
+
| **R09** | No `RoleEnactment` — work doesn't reference the assignment it was performed under | Source says `RoleEnactment ::= <work, by: RoleAssignment>`. Our `WorkPrimitive.actor_role_id` is a loose string, not a reference to an assignment. | When R07/R08 land, add `performed_under: str` (assignment ID) to `WorkPrimitive`. |
|
|
36
|
+
| **R17** | `CommitmentPrimitive` lacks `subject`, `referents`, `owed_to`, `source` | Source commitment is richer: accountable subject, who it's owed to, what it refers to, where it came from. Our version only has modality + evidence refs. | Add fields. These don't widen per-step chew because commitments are only consulted when explicitly in scope. |
|
|
37
|
+
| **R20/R21** | No speech-act structure for communicative work | Source has `U.SpeechAct` as a `U.Work` subtype for approvals, authorizations, revocations. We have no way to model "approval as a communicative act that institutes a commitment." | Add `SpeechActPrimitive` as a `WorkPrimitive` subtype with `act_types`, `addressed_to`, `institutes`. Only enters the path when the current move is communicative. |
|
|
38
|
+
| **R32** | `WorkPrimitive` lacks `primary_target` and source-aligned work kinds | Source distinguishes Operational / Communicative / Epistemic work kinds and requires a primary target. | Add `work_kind` (operational/communicative/epistemic) and `primary_target` fields. |
|
|
39
|
+
| **R24/R25** | Evidence is flat — no typed DAG, no `verifiedBy` vs `validatedBy` distinction | Source evidence graph has typed nodes, edges, and a formal-vs-empirical anchor split. Ours is `supports: list[str]`. | Add `EvidenceEdge` dataclass with `kind` (supports/contradicts/verifies/validates) and build a minimal graph. Keep the evidence primitive itself flat; the graph is a separate structure on `SemanticMap`. |
|
|
40
|
+
|
|
41
|
+
## Category 3: Accept as intentional compression (do not fix)
|
|
42
|
+
|
|
43
|
+
These items are correctly identified as missing, but adding them would turn the thinking map into a FPF reimplementation. The compression is the feature.
|
|
44
|
+
|
|
45
|
+
| IDs | What | Why keep compressed |
|
|
46
|
+
|-----|------|-------------------|
|
|
47
|
+
| **R01** | `ContextPrimitive` is not a `U.Holon` with a `U.Boundary` | The holonic foundation is FPF's deepest abstraction layer. We don't need Entity → Holon → System/Episteme for a thinking map. Context-as-bounded-frame is sufficient. |
|
|
48
|
+
| **R03** | Roles not structurally attached to context object | Roles are indexed by `context_id` globally, and `active_roles` validates context match at runtime. Attaching a role registry directly to the context object would duplicate the `SemanticMap.roles` dict. The runtime behavior is correct. |
|
|
49
|
+
| **R04** | Bridge lacks `fit/congruence` field | `translation_loss` is sufficient for the current use case. Adding a formal congruence level adds semantic weight without operational benefit in the thinking map. |
|
|
50
|
+
| **R06** | No bridge-mediated term translation path | Bridge-aware term lookup is a RAG/retrieval feature, not a thinking map feature. The map tells the LLM that a bridge exists and what the loss is; the LLM does the translation. |
|
|
51
|
+
| **R10/R11** | No holder-kind eligibility model | FPF's distinction between System holders (behavioral roles) and Episteme holders (status roles) is deep ontology. The thinking map doesn't need to type-check holders; it needs to check role conflicts and context scope. |
|
|
52
|
+
| **R12** | No assignment window / time discipline | Time windows are important in FPF for formal role lifecycle. In the thinking map, temporal validity is handled by evidence freshness and external constraints, not by role assignment windows. |
|
|
53
|
+
| **R13** | Authoritative vs observational role assignments | This distinction matters in formal FPF gate semantics. In the thinking map, the guard layer handles gate authority via the gate-transition binding, not via role assignment modes. |
|
|
54
|
+
| **R14** | `specializes` pointer not used for `requiredRoles` substitution | Role substitution is FPF's formal role algebra. The thinking map checks conflict (⊥) which is the operationally critical case. Specialization substitution is a vertical enrichment. |
|
|
55
|
+
| **R15** | Conflict checked as simultaneous IDs, not overlapping assignment windows | Same as R12 — window discipline is deferred. ID-based conflict check catches the operational case. |
|
|
56
|
+
| **R16** | No bundle operator (⊗) | Role bundles are formal role algebra. The thinking map supports multi-role binding via `actor_role_ids` and checks conflicts. Bundles add formalism without operational payoff at this level. |
|
|
57
|
+
| **R18** | Commitment checks reduce to evidence completion | Source wants accountable subject distinct from evidence. For the thinking map, evidence-backed commitment is the operational check. Subject accountability is a governance layer concern. |
|
|
58
|
+
| **R19** | No commitment conflict channel | The logic layer's `exclusive_with` handles action contradictions. Formal commitment-level conflict requires the richer commitment model from R17. |
|
|
59
|
+
| **R22** | No "institutes/updates/revokes" relation | This is the speech-act machinery from R20/R21. Deferred to that implementation. |
|
|
60
|
+
| **R23** | Publication is "just a face record" | Intentional. Publication is out of the step path. Adding projection lineage turns it into a rendering engine. |
|
|
61
|
+
| **R26** | No symbol carrier register (SCR/RSCR) | Deep FPF publication machinery. Not needed for a thinking map. |
|
|
62
|
+
| **R27** | No scope separation between design-time and run-time evidence | Good formal discipline, but the thinking map's evidence is always runtime (current_evidence). Design-time evidence doesn't enter the per-step path. |
|
|
63
|
+
| **R28** | No external-transformer relation for evidence production | Important in FPF for audit trails. The thinking map trusts evidence IDs as given by the binding. Externality is a governance concern. |
|
|
64
|
+
| **R29** | No ordered trace or method instantiation card | `method_id` is a loose pointer. For the thinking map, this is sufficient — the model doesn't need to reconstruct method instantiation chains per step. |
|
|
65
|
+
| **R31/R33** | Work lacks `performedBy`, `isExecutionOf` as first-class links | These are source canonical relations. The thinking map uses loose IDs (`method_id`, `actor_role_id`). First-class links would be the right shape after R07/R08/R09 land. |
|
|
66
|
+
| **R34** | `method_id` collapses method and method-description | FPF's Method/MethodDescription distinction. For the thinking map, a method reference is enough. |
|
|
67
|
+
| **R35** | No capability primitive | `U.Capability` is a system attribute in FPF. The thinking map checks role eligibility and gate passage, not capability declarations. |
|
|
68
|
+
| **R36** | Work lacks occurrence window, resource ledger, acceptance outcome | Full work record semantics. The thinking map tracks inputs/outputs and evidence refs. Detailed occurrence tracking is an execution engine concern. |
|
|
69
|
+
| **R37** | No work acceptance against spec-standard chain | CAC (Context-Assignment-Standard) checks are formal FPF acceptance. The thinking map's guards cover context and evidence, not spec-standard chains. |
|
|
70
|
+
| **R38** | `WorkPlan` lacks dependencies, budgets, variance dimensions | Full planning semantics. Deferred to R30 split, but detailed planning fields are execution-engine scope. |
|
|
71
|
+
| **R39** | No `plannedAs` / fulfilment / variance relation | Depends on R30 (WorkPlan split). Deferred. |
|
|
72
|
+
| **R41/R42/R43/R44** | Gate model lacks profiles, CV/GF split, decision logs, fold policies | Deep gate semantics. The thinking map's gate model (checks → tri-state → decision) covers the operational case. Profile-bound folds and decision logs are audit-trail features. |
|
|
73
|
+
| **R45/R46/R47/R48/R49** | Publication lacks viewpoints, pin discipline, comparator sets, publication-scope | Deep MVPK semantics. Publication is intentionally thin in the thinking map — it's a face label, not a rendering engine. |
|
|
74
|
+
| **R50** | Slice-first runtime is built from compressed primitives | Correct observation. This is the design: compressed primitives → small slices → usable per-step chew. Enriching primitives is the next pass (Category 2), but only fields that don't widen the slice. |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Scorecard
|
|
79
|
+
|
|
80
|
+
| Category | Count | Action |
|
|
81
|
+
|----------|-------|--------|
|
|
82
|
+
| Fix now (wrong-shape or cheap high-value) | 4 items (R02, R05, R30, R40) | Implement this round |
|
|
83
|
+
| Fix next round (genuine gaps, need design) | 6 items (R07/R08, R09, R17, R20/R21, R24/R25, R32) | Queue with shape sketches |
|
|
84
|
+
| Intentional compression (keep as-is) | 40 items | Document as design decisions |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
prichindel.com | 2026-06-24 | v1.0.0
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# FPF Semantic Floor Map
|
|
2
|
+
|
|
3
|
+
Vertical amplification levels derived from FPF spec section layering.
|
|
4
|
+
Each floor defines a TTL range for evidence decay during agentic traversal.
|
|
5
|
+
|
|
6
|
+
The elevator has 5 floors. Evidence at each floor decays at the rate defined by that floor's base TTL. The hop counter (step_count) increments each `step()` call and drives the decay.
|
|
7
|
+
|
|
8
|
+
## Floor definitions
|
|
9
|
+
|
|
10
|
+
| Floor | Name | Base TTL | Decay formula | FPF sections |
|
|
11
|
+
|-------|------|----------|---------------|-------------|
|
|
12
|
+
| 0 | STRUCTURAL | None (infinite) | Never during traversal | A.1.1, A.2, A.3.3, A.6.9, A.21 defs |
|
|
13
|
+
| 1 | BINDING | 10 steps | Fixed: 10 | A.2.1, A.2.8, A.15.2 |
|
|
14
|
+
| 2 | EVIDENTIARY | 8 × F × R | `max(1, round(F × R × 8))` | A.10, B.3, B.3.4 |
|
|
15
|
+
| 3 | OPERATIONAL | 2 steps | Fixed: 2 | A.2.9, A.15.1, A.21 eval |
|
|
16
|
+
| 4 | PUBLICATION | None (inherited) | Source-dependent | E.17 |
|
|
17
|
+
|
|
18
|
+
## FGR-modulated decay (Floor 2)
|
|
19
|
+
|
|
20
|
+
At the EVIDENTIARY floor, the FGR trust tuple directly determines TTL:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
computed_ttl = max(1, round(formality × reliability × 8))
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The scope (G) dimension is not used in TTL — it measures claim breadth, not temporal stability.
|
|
27
|
+
|
|
28
|
+
| F (formality) | R (reliability) | Computed TTL | Example |
|
|
29
|
+
|--------------|----------------|-------------|---------|
|
|
30
|
+
| 1.0 | 1.0 | 8 | Formal proof from authoritative source |
|
|
31
|
+
| 0.8 | 0.9 | 6 | CI test results from reliable pipeline |
|
|
32
|
+
| 0.7 | 0.8 | 4 | Peer review from known reviewer |
|
|
33
|
+
| 0.5 | 0.5 | 2 | Manual test, moderate confidence |
|
|
34
|
+
| 0.3 | 0.4 | 1 | Anecdotal report, untested source |
|
|
35
|
+
| 0.2 | 0.3 | 1 | Hearsay (floor: always at least 1) |
|
|
36
|
+
|
|
37
|
+
## Decay timeline
|
|
38
|
+
|
|
39
|
+
When evidence age reaches TTL boundaries:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
age < TTL → CURRENT (guard allows)
|
|
43
|
+
TTL ≤ age < 2×TTL → STALE (guard warns)
|
|
44
|
+
age ≥ 2×TTL → EXPIRED (evidence dead)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Example for OPERATIONAL evidence (TTL=2):
|
|
48
|
+
```
|
|
49
|
+
Step 0: added → CURRENT
|
|
50
|
+
Step 1: → CURRENT
|
|
51
|
+
Step 2: age=TTL → STALE (guard: "evidence is stale")
|
|
52
|
+
Step 3: → STALE
|
|
53
|
+
Step 4: age=2×TTL → EXPIRED
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Example for EVIDENTIARY evidence with F=0.8, R=0.9 (TTL=6):
|
|
57
|
+
```
|
|
58
|
+
Step 0: added → CURRENT
|
|
59
|
+
Step 5: → CURRENT
|
|
60
|
+
Step 6: age=TTL → STALE
|
|
61
|
+
Step 11: → STALE
|
|
62
|
+
Step 12: age=2×TTL → EXPIRED
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Primitive → Floor mapping
|
|
66
|
+
|
|
67
|
+
### Floor 0: STRUCTURAL — the building itself
|
|
68
|
+
|
|
69
|
+
| Primitive | FPF source | Why this floor |
|
|
70
|
+
|-----------|-----------|---------------|
|
|
71
|
+
| ContextPrimitive | A.1.1 U.BoundedContext | Meaning frames are build-time. Changing a context mid-traversal changes the board. |
|
|
72
|
+
| ContextBridge | A.6.9 CrossContextSameness | Bridge topology defines what cross-context moves are possible. Structural. |
|
|
73
|
+
| RolePrimitive | A.2 Role Taxonomy | Role definitions (responsibilities, conflicts, specialization) require governance to change. |
|
|
74
|
+
| TransitionPrimitive | A.3.3 U.Dynamics | State machine topology is compiled. Adding/removing transitions = redesigning the board. |
|
|
75
|
+
| GatePrimitive (definition) | A.21 GateProfilization | Gate structure (what checks, what evidence required) is build-time. |
|
|
76
|
+
| GateCheck (definition) | A.21 GateProfilization | Individual check definitions are structural. |
|
|
77
|
+
|
|
78
|
+
### Floor 1: BINDING — session-stable, can expire
|
|
79
|
+
|
|
80
|
+
| Primitive | FPF source | Why this floor |
|
|
81
|
+
|-----------|-----------|---------------|
|
|
82
|
+
| RoleAssignment | A.2.1 U.RoleAssignment | Assignments have validity windows (valid_from/valid_until). They bind a holder to a role for a period. |
|
|
83
|
+
| CommitmentPrimitive | A.2.8 U.Commitment | Obligations persist until revoked or expired. Deontic validity windows. |
|
|
84
|
+
| WorkPlanPrimitive | A.15.2 U.WorkPlan | Plans go stale as circumstances evolve. FPF A.4: "planning ≠ enactment" — plans are intent, not fact. |
|
|
85
|
+
|
|
86
|
+
### Floor 2: EVIDENTIARY — decays with trust (FGR-modulated)
|
|
87
|
+
|
|
88
|
+
| Primitive | FPF source | Why this floor |
|
|
89
|
+
|-----------|-----------|---------------|
|
|
90
|
+
| EvidencePrimitive | A.10 Evidence Graph | FPF B.3.4 explicitly: "evidence decays." Freshness is a first-class property. |
|
|
91
|
+
| FGR trust tuple | B.3 Trust & Assurance | The trust assessment itself has a shelf life. High-formality evidence from reliable sources decays slower. |
|
|
92
|
+
|
|
93
|
+
### Floor 3: OPERATIONAL — per-step ephemeral
|
|
94
|
+
|
|
95
|
+
| Primitive | FPF source | Why this floor |
|
|
96
|
+
|-----------|-----------|---------------|
|
|
97
|
+
| SpeechActPrimitive | A.2.9 U.SpeechAct | Communicative acts are events. An approval is valid at the moment it was given; its scope may not cover future states. |
|
|
98
|
+
| WorkPrimitive | A.15.1 U.Work | Enactment records are historical fact, but their relevance to current decisions is ephemeral. "We deployed yesterday" ≠ "we can deploy now." |
|
|
99
|
+
| GatePrimitive (evaluation result) | A.21 gate result | A gate evaluation is valid at the step it was computed. Evidence may change next step. |
|
|
100
|
+
|
|
101
|
+
### Floor 4: PUBLICATION — inherited freshness
|
|
102
|
+
|
|
103
|
+
| Primitive | FPF source | Why this floor |
|
|
104
|
+
|-----------|-----------|---------------|
|
|
105
|
+
| PublicationPrimitive | E.17 MVPK | Views project lower floors. A publication's freshness = min(freshness of its source work). If the source evidence expired, the publication is stale. |
|
|
106
|
+
|
|
107
|
+
## Design notes
|
|
108
|
+
|
|
109
|
+
**Why scope (G) is not used in TTL**: scope measures how broad a claim is ("this test covers the whole API" vs "this test covers one endpoint"). Broad claims don't decay faster or slower — they're just bigger. Formality and reliability determine shelf life.
|
|
110
|
+
|
|
111
|
+
**Why STRUCTURAL has no TTL**: changing a context definition or a role taxonomy mid-traversal is a board redesign, not a step. If structural primitives change, the SemanticMap must be rebuilt. The hop counter is irrelevant.
|
|
112
|
+
|
|
113
|
+
**Why OPERATIONAL is 2, not 1**: a gate evaluation at step N might inform the decision at step N+1 (the agent evaluates, then acts). But by step N+2, the evaluation should be refreshed. Two steps gives the agent one move to act on the result.
|
|
114
|
+
|
|
115
|
+
**The elevator analogy**: the building can be any height (traversal can be any number of steps). But the elevator's capacity is fixed per floor. Evidence at Floor 3 expires after 2 steps regardless of building height. Evidence at Floor 0 never expires — it IS the building.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
prichindel.com | 2026-06-26 | v1.1.1
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# FPF Source To Code Relation Audit
|
|
2
|
+
|
|
3
|
+
Purpose: sentence-scoped backlog for missing or compressed relations between the FPF source text and the current `fpf_thinking_map` code.
|
|
4
|
+
|
|
5
|
+
Rule for this artifact:
|
|
6
|
+
- Focus on relation coverage, not synonym coverage.
|
|
7
|
+
- Keep evidence close to the source sentence.
|
|
8
|
+
- Keep interpretation minimal.
|
|
9
|
+
- "Address" means "relation should be represented more explicitly or enforced more directly".
|
|
10
|
+
|
|
11
|
+
Sources audited in this pass:
|
|
12
|
+
- `FPF-Spec.md` (external; not included in this repository)
|
|
13
|
+
- Current code in `fpf_thinking_map/`
|
|
14
|
+
|
|
15
|
+
Legend:
|
|
16
|
+
- `missing` = relation not represented as a first-class structure or check
|
|
17
|
+
- `partial` = relation is hinted at but structurally compressed or under-enforced
|
|
18
|
+
- `wrong-shape` = relation exists but in a shape that contradicts source discipline
|
|
19
|
+
|
|
20
|
+
## Backlog
|
|
21
|
+
|
|
22
|
+
| ID | Status | Source lines | Source evidence | Code target | Address |
|
|
23
|
+
| --- | --- | --- | --- | --- | --- |
|
|
24
|
+
| R01 | wrong-shape | `FPF-Spec.md:1078-1150` | "`U.BoundedContext` is a `U.Holon`" and "declares a `U.Boundary`" | `primitives.py:23-35` | `ContextPrimitive` has no `holon` / `boundary` representation. Add explicit boundary-bearing shape or equivalent marker. |
|
|
25
|
+
| R02 | wrong-shape | `FPF-Spec.md:1100-1114` | "contexts do not form holarchies with each other" and "no is-a or containment relations" | `primitives.py:31` | `parent_context_id` encodes forbidden context containment/inheritance. Remove or replace with explicit bridge-based relation only. |
|
|
26
|
+
| R03 | partial | `FPF-Spec.md:1087-1096` | Context local constitution includes `Glossary`, `Invariants`, `Roles`, `Bridges` | `primitives.py:32-34` | `Roles` are not structurally attached to the context object, only globally indexed by `context_id`. Add direct local taxonomy attachment or explicit context-side role registry. |
|
|
27
|
+
| R04 | partial | `FPF-Spec.md:1093-1096` | Bridges carry explicit cross-context relations with "loss/fit notes" and congruence examples | `primitives.py:44-53` | `ContextBridge` has `translation_loss` but no fit / congruence level field. Add explicit fit relation carrier. |
|
|
28
|
+
| R05 | missing | `FPF-Spec.md:1118-1123` | "Any invariant authored in a Context applies only to holons and processes operating within that Context" | `primitives.py:33`, `state.py:267-305`, `traversal.py:112-209` | Invariants are stored as free-text strings but never evaluated or scoped as operational constraints. Add context-local invariant enforcement path. |
|
|
29
|
+
| R06 | partial | `FPF-Spec.md:1078-1086` | "Cross-context sameness is never inferred from spelling; alignment only via explicit Bridge artifacts" | `primitives.py:36-40`, `state.py:97-112` | Local glossary resolution exists, but no bridge-mediated term translation path is executable. Add bridge-aware relation lookup instead of local-only term resolution. |
|
|
30
|
+
| R07 | missing | `FPF-Spec.md:1122-1124` | "`U.RoleAssignment` references exactly one `U.BoundedContext` in its `context` field" | `state.py:35-54`, `state.py:142-153` | No `RoleAssignment` object exists; runtime binding of `actor_role_ids` cannot carry assignment-local context cardinality or issuance evidence. |
|
|
31
|
+
| R08 | missing | `FPF-Spec.md:1450-1456` | "`U.RoleAssignment` binds holder holon to role inside a bounded context, optionally within a time window" | `state.py:35-54`, `primitives.py:68-89` | Introduce first-class `RoleAssignment` primitive instead of binding roles directly on runtime input. |
|
|
32
|
+
| R09 | missing | `FPF-Spec.md:1452-1454`, `1508-1515` | "Separates that binding from `U.RoleEnactment`" and "`RoleEnactment ::= <work, by: RoleAssignment>`" | `primitives.py:102-121`, `state.py:79-80` | No enactment object or explicit `work -> role assignment` relation exists. Add enactment relation or equivalent reference field. |
|
|
33
|
+
| R10 | missing | `FPF-Spec.md:1481-1486` | "Behavioural roles: holder is a `U.System`" and "Status roles: holder is a `U.Episteme`" | `primitives.py:68-89`, `state.py:42-54` | No holder-kind eligibility model exists. Add holder kind and role kind checks. |
|
|
34
|
+
| R11 | missing | `FPF-Spec.md:1479-1480` | "`holder ∉ {U.Role, U.RoleAssignment}`" | `state.py:42-54`, `primitives.py:68-89` | No holder typing means this prohibition cannot be checked. Add typed holder binding and validation. |
|
|
35
|
+
| R12 | missing | `FPF-Spec.md:1486-1488` | "If `window` is present, enactments occur within it" | `state.py:35-54`, `primitives.py:102-121` | No assignment window or enactment time window discipline exists. Add assignment window and check it during work / transition decisions. |
|
|
36
|
+
| R13 | partial | `FPF-Spec.md:1495-1501` | "Authoritative" vs "Observational" role assignments have different gate effects | `guards.py:122-147`, `state.py:142-153` | Runtime roles are undifferentiated. Add assignment mode so guards can distinguish gate-opening authority from observational classification. |
|
|
37
|
+
| R14 | partial | `FPF-Spec.md:4627-4630` | "`≤` specialization MUST satisfy requiredRoles substitution" | `primitives.py:85` | Only one `specializes` pointer exists, but no expansion of `requiredRoles` or transition eligibility uses it. Add substitution evaluation path. |
|
|
38
|
+
| R15 | partial | `FPF-Spec.md:4632-4635` | "`⊥` overlapping windows on the same holder ... are ill-formed" | `primitives.py:84`, `guards.py:108-119` | Conflict is checked only as simultaneous active role IDs, not as overlapping assignments for the same holder and window. |
|
|
39
|
+
| R16 | missing | `FPF-Spec.md:4637-4641` | "`⊗` bundle is satisfied iff simultaneous valid assignments for each conjunct role" | `primitives.py:68-89`, `guards.py:209-250` | No bundle operator exists. Add conjunctive role bundle representation and satisfaction check. |
|
|
40
|
+
| R17 | missing | `FPF-Spec.md:4706-4753` | Commitment required fields include `subject`, `modality`, `scope`, `validityWindow`, `referents`; optional `owedTo`, `adjudication`, `source` | `primitives.py:137-154` | `CommitmentPrimitive` lacks `subject`, `referents`, `owed_to`, `source`; current shape is too compressed for source commitment semantics. |
|
|
41
|
+
| R18 | partial | `FPF-Spec.md:4694-4704` | Commitment must keep "accountable subject explicit" and not assign agency to descriptions | `primitives.py:137-154`, `logic.py:205-213` | Current commitment checks reduce commitment to evidence completion. Add explicit accountable subject relation distinct from evidence satisfaction. |
|
|
42
|
+
| R19 | missing | `FPF-Spec.md:4697-4701` | "Conflicts can be represented" | `primitives.py:137-154`, `logic.py:30-260` | No commitment conflict / contradiction relation exists beyond generic rule exclusivity. Add explicit commitment conflict channel if commitments are to remain source-faithful. |
|
|
43
|
+
| R20 | missing | `FPF-Spec.md:4990-5070` | "`U.SpeechAct` is a `U.Work` occurrence whose primary effect is communicative" | `primitives.py:96-121` | `WorkKind` only has `PLAN` and `ENACTMENT`. Add communicative / operational / epistemic work kinds or a speech-act subtype. |
|
|
44
|
+
| R21 | missing | `FPF-Spec.md:5033-5047` | `U.SpeechAct` carries `actTypes`, `addressedTo`, `utteranceRefs`, `carrierRefs`, `institutes` | `primitives.py:102-121`, `traversal.py:25-35` | No speech-act structure exists, so approvals / authorizations / revocations cannot be modeled as communicative work objects. |
|
|
45
|
+
| R22 | partial | `FPF-Spec.md:5015-5023` | "act can institute (or update/revoke) commitments, role assignments, statuses, etc., by reference" | `primitives.py:137-154`, `state.py:73-95` | No explicit "institutes / updates / revokes" relation exists between communicative work and commitments or assignments. |
|
|
46
|
+
| R23 | partial | `FPF-Spec.md:14540-14549`, `14602-14606` | Publication is typed projection `I→D→S` and "is not execution" | `primitives.py:305-319` | `PublicationPrimitive` is just a face record. Add projection lineage and explicit separation from work execution. |
|
|
47
|
+
| R24 | missing | `FPF-Spec.md:14580-14584` | EPV-DAG is "typed, acyclic" and "disjoint from mereology" | `primitives.py:250-265` | Evidence is flat; `supports` / `contradicts` do not encode typed DAG nodes or acyclicity. Add evidence graph structure, node kinds, and edge kinds. |
|
|
48
|
+
| R25 | missing | `FPF-Spec.md:14587-14589` | `verifiedBy` vs `validatedBy` are distinct anchor relations | `primitives.py:250-265` | Evidence model has no formal-vs-empirical anchor split. Add explicit anchor relation kind. |
|
|
49
|
+
| R26 | missing | `FPF-Spec.md:14590-14593`, `14641-14645` | `SCR` / `RSCR` emission and carrier resolution are mandatory for aggregate publication | `primitives.py:250-265`, `primitives.py:305-319` | No symbol carrier register structure exists. Add carrier register object or pinned carrier list structure. |
|
|
50
|
+
| R27 | missing | `FPF-Spec.md:14595-14599`, `14646-14649` | Design-time `MethodDescription` and run-time `Work` traces must not mix in one EPV-DAG instance | `primitives.py:102-121`, `primitives.py:250-265` | No explicit scope separation in evidence layer. Add node scope / relation type or distinct graphs. |
|
|
51
|
+
| R28 | missing | `FPF-Spec.md:14600-14602`, `14650-14652` | Evidencing `TransformerRole` must be external to the holon under evaluation | `primitives.py:250-265`, `guards.py:35-201` | No external-transformer relation exists for evidence production. Add evidencer identity and externality check. |
|
|
52
|
+
| R29 | partial | `FPF-Spec.md:14612-14617` | `Γ_method` run-time traces record `happenedBefore` and point to the `MethodDescription` they instantiate | `primitives.py:117`, `state.py:115-121` | `method_id` exists, but no ordered trace relation or method instantiation card exists. |
|
|
53
|
+
| R30 | missing | `FPF-Spec.md:15359-15425` | Strict distinction among `U.Role`, `U.Method`, `U.MethodDescription`, `U.Capability`, `U.WorkPlan`, `U.Work` | `primitives.py:96-121`, `state.py:66`, `state.py:79-80` | `WorkPrimitive(kind=PLAN)` compresses `WorkPlan` into `Work`, breaking source type separation. Split `WorkPlan` into distinct primitive. |
|
|
54
|
+
| R31 | missing | `FPF-Spec.md:15407-15418` | "`U.Work` is execution of a `U.MethodDescription` by a Holder acting under a `U.RoleAssignment`" | `primitives.py:102-121` | `WorkPrimitive` lacks holder / assignment / execution-chain structure strong enough for the canonical relation chain. |
|
|
55
|
+
| R32 | missing | `FPF-Spec.md:15420-15427` | Every `U.Work` declares `primaryTarget` and a kind: Operational / Communicative / Epistemic | `primitives.py:102-121` | Add `primary_target` and source-aligned work-kind taxonomy. |
|
|
56
|
+
| R33 | missing | `FPF-Spec.md:15464-15487`, `15609-15616` | Canonical relations include `performedBy`, `isExecutionOf`, `describes`, `bindsCapability` | `primitives.py:102-121`, `state.py:64-71` | These relations are only implicit via loose IDs, not represented as first-class links. |
|
|
57
|
+
| R34 | missing | `FPF-Spec.md:15398-15406`, `15588-15595` | `U.Method` and `U.MethodDescription` are distinct | `primitives.py:117` | `method_id` collapses method and method-description identity. Split into `method_id` and `method_description_id` or equivalent. |
|
|
58
|
+
| R35 | missing | `FPF-Spec.md:15401-15404` | `U.Capability` is an attribute of a `U.System` and distinct from work and method | `primitives.py:68-121`, `state.py:35-54` | No capability primitive or runtime capability check exists. |
|
|
59
|
+
| R36 | partial | `FPF-Spec.md:15549-16020` | `U.Work` includes dated occurrence, parameter bindings, resource consumption, outcomes, affected referent | `primitives.py:119-121` | Inputs/outputs exist, but no explicit occurrence window, resource ledger, affected referent, or acceptance outcome structure exists. |
|
|
60
|
+
| R37 | missing | `FPF-Spec.md:15700-15740` | CAC checks: context, assignment, standard | `state.py:194-216`, `traversal.py:211-260` | Transition and traversal checks cover context and evidence partially, but no explicit work acceptance against spec-standard chain exists. |
|
|
61
|
+
| R38 | missing | `FPF-Spec.md:15945-16018` | `U.WorkPlan` has planned windows, dependencies, intended performers, budgets, acceptance targets, variance dimensions | `primitives.py:102-121`, `state.py:66`, `guards.py:83-105` | Planning is treated as one `WorkPrimitive`; add dedicated `WorkPlan` / `PlanItem` structures and fulfilment / variance relations. |
|
|
62
|
+
| R39 | partial | `FPF-Spec.md:15983-16003` | Work may fulfil, partially fulfil, deviate from, or be unplanned against a plan item | `primitives.py:102-121`, `state.py:79-80` | No explicit `plannedAs` / fulfilment / variance relation exists between actual work and plan items. |
|
|
63
|
+
| R40 | wrong-shape | `FPF-Spec.md:20569-20605` | Gate decision lattice is `abstain ≤ pass ≤ degrade ≤ block` | `primitives.py:164-168`, `logic.py:168-177`, `traversal.py:246-255` | `GateDecision` lacks `BLOCK`, and `ABSTAIN` is used as blocked/fail-closed. Restore source lattice explicitly. |
|
|
64
|
+
| R41 | missing | `FPF-Spec.md:20605-20635` | `OperationalGate(profile)` and `GateCheckRef` / profile-bound folds are first-class | `primitives.py:171-218` | Gate model has checks but no gate profile, no fold policy object, no check references distinct from inline checks. |
|
|
65
|
+
| R42 | missing | `FPF-Spec.md:20636-20660` | Distinction between CV and GF is explicit in gate semantics | `primitives.py:188-218`, `guards.py:122-147` | No explicit CV/GF layer split exists. Add gate-evaluation dimension if source compliance matters. |
|
|
66
|
+
| R43 | missing | `FPF-Spec.md:20661-20730` | Gate system includes decision log, equivalence witness, scope merge semantics | `primitives.py:188-218`, `state.py:223-265` | Current gate evaluation returns only final decision and missing evidence. Add decision log / witness / merge trace if source relation should be preserved. |
|
|
67
|
+
| R44 | partial | `FPF-Spec.md:20569-20592` | Unknown / timeout / error folds are profile-bound, not hardcoded | `primitives.py:199-211` | `fail_closed` is a binary shortcut, not a source-style profile fold. |
|
|
68
|
+
| R45 | partial | `FPF-Spec.md:37026-37110` | MVPK is a typed/functorial projection over morphisms and "faces do not create new claims" | `primitives.py:305-319` | Current publication face enum preserves "no new semantics" in docstring but not as pinned constraints / lineage fields. |
|
|
69
|
+
| R46 | missing | `FPF-Spec.md:37080-37135` | Viewpoint and `U.PublicationScope` are explicit | `primitives.py:305-319` | Add viewpoint / publication-scope fields instead of only `face` + `audience`. |
|
|
70
|
+
| R47 | missing | `FPF-Spec.md:37136-37225` | Faces carry pins/refs, lawful orders, comparator sets, set-return semantics | `primitives.py:305-319`, `logic.py:287-318` | No comparator-set or pin discipline exists for publication outputs. |
|
|
71
|
+
| R48 | missing | `FPF-Spec.md:37190-37220`, `15760-15795` | Across-run comparisons forbid hidden scalarization and require declared comparator sets | `primitives.py:305-319`, `logic.py:227-240` | Risk and logic outputs are scalar/simple, but no publication comparison discipline exists. |
|
|
72
|
+
| R49 | partial | `FPF-Spec.md:14621-14623`, `37026-37225` | Publication / rendering / upload is work by an external transformer on carriers, cited in SCR | `primitives.py:305-319`, `primitives.py:102-121` | Publication object is detached from actual publication work and carriers. Add explicit publication-work anchor. |
|
|
73
|
+
| R50 | partial | `FPF-Spec.md:15549-16020`, `20569-20840` | Runtime should stay bite-sized, but semantic enforcement still depends on typed relations, not just string labels | `state.py:223-265`, `traversal.py:97-110` | Slice-first runtime is good horizontally, but the slice is still built from compressed primitives. Next pass should enrich primitives without widening prompt payload. |
|
|
74
|
+
|
|
75
|
+
## Lowest-friction next pass
|
|
76
|
+
|
|
77
|
+
These are the highest-value relation repairs that do not require widening the runtime chew:
|
|
78
|
+
|
|
79
|
+
1. Add first-class `RoleAssignment` and keep `actor_role_ids` as derived runtime convenience, not the semantic source of truth.
|
|
80
|
+
2. Split `WorkPlan` from `WorkPrimitive`; stop using `WorkKind.PLAN` as a substitute for the source distinction.
|
|
81
|
+
3. Restore gate lattice with explicit `BLOCK`; stop overloading `ABSTAIN` as the only hard denial outcome.
|
|
82
|
+
4. Add `primary_target`, source-aligned work kinds, and explicit `performedBy` / `isExecutionOf` references.
|
|
83
|
+
5. Add a minimal typed evidence graph layer with `verifiedBy` / `validatedBy` and external evidencer identity.
|
|
84
|
+
6. Remove `parent_context_id` or demote it out of kernel semantics; use bridges only for cross-context relation.
|
|
85
|
+
7. Add speech-act structure for communicative work that institutes / revokes commitments and assignments by reference.
|
|
86
|
+
|
|
87
|
+
## Notes
|
|
88
|
+
|
|
89
|
+
- This file is intentionally not a redesign document.
|
|
90
|
+
- It is a relation-coverage backlog for a follow-up pass.
|
|
91
|
+
- Source line spans are section-local evidence bands, not full formal proofs.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
# FPF Thinking Map
|
|
2
|
+
|
|
3
|
+
This folder contains a Python package that helps an AI model make decisions step by step. It does this by combining two things: a structured framework for reasoning (called FPF) and basic logic operations (AND, OR, NOT, etc.) from computer science.
|
|
4
|
+
|
|
5
|
+
No external dependencies. Pure Python 3.12+. No pip install needed.
|
|
6
|
+
|
|
7
|
+
## What problem this solves
|
|
8
|
+
|
|
9
|
+
When you give an AI model a question like "should we deploy this release?", the model can answer anything. It might forget to check if tests passed. It might skip asking for approval. It might say "deploy" and "collect more evidence" in the same breath.
|
|
10
|
+
|
|
11
|
+
This package gives the model a small, structured board to reason on. The board has:
|
|
12
|
+
- facts about the current situation (what evidence exists, what gates are open)
|
|
13
|
+
- rules about what is allowed (you cannot deploy without approval)
|
|
14
|
+
- logic checks that are deterministic (the model cannot override them)
|
|
15
|
+
|
|
16
|
+
The model reads the board, then picks from a fixed set of moves: continue, ask, abstain, escalate, collect evidence, etc.
|
|
17
|
+
|
|
18
|
+
## Where this comes from
|
|
19
|
+
|
|
20
|
+
Two sources, both real academic material:
|
|
21
|
+
|
|
22
|
+
**Source 1: [FPF (First Principles Framework)](https://github.com/ailev/FPF)**
|
|
23
|
+
- A transdisciplinary specification (~51,000 lines) by Anatoly Levenchuk — "operating system for thought"
|
|
24
|
+
- It defines how to structure reasoning about systems: what roles exist, what evidence is needed, what gates must pass, how to transition between states
|
|
25
|
+
- We did NOT copy the whole spec. We extracted 10 objects from it and turned them into Python dataclasses
|
|
26
|
+
- The full spec lives in the [ailev/FPF](https://github.com/ailev/FPF) repository
|
|
27
|
+
|
|
28
|
+
**Source 2: Computational logic lectures (Mitev L.)**
|
|
29
|
+
- 5 lecture PDFs on propositional logic from a university course
|
|
30
|
+
- "Bazele programarii logice" (Fundamentals of Logic Programming)
|
|
31
|
+
- 5 lecture PDFs (c1p through c5p) — not included in this repository
|
|
32
|
+
- We took the 6 basic logic operators (NOT, AND, OR, XOR, IMPLIES, IFF) and built them as Python classes that evaluate against the current state
|
|
33
|
+
- The key pattern we adopted is from lecture 5: the Wumpus World. An agent navigates a grid, uses propositional logic to determine which cells are safe. Same idea here — the model navigates semantic states, uses logic to determine which moves are safe
|
|
34
|
+
|
|
35
|
+
## What is in each file
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
fpf_thinking_map/
|
|
39
|
+
│
|
|
40
|
+
├── primitives.py 10 semantic objects + 5 semantic floors from FPF
|
|
41
|
+
├── state.py Binding, state, TTL tracking, evidence status, slice
|
|
42
|
+
├── guards.py 9 deterministic guards the model cannot break
|
|
43
|
+
├── logic.py 6 logic operators + EvidenceFresh + decision rules
|
|
44
|
+
├── traversal.py Step engine with 10 lawful outcomes (incl. IDLE, BRIDGE)
|
|
45
|
+
├── verify.py Self-test: run it, if 18/18 pass, package works
|
|
46
|
+
│
|
|
47
|
+
├── examples.py 5 deploy decision scenarios (all features in action)
|
|
48
|
+
│
|
|
49
|
+
├── __init__.py Package exports
|
|
50
|
+
├── README.md This file
|
|
51
|
+
└── SOURCES.md Detailed source attribution
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## The 10 objects from FPF (primitives.py)
|
|
55
|
+
|
|
56
|
+
These are Python dataclasses. Each one was extracted from a specific section of the FPF spec. v1.1: includes SemanticFloor (5 vertical levels) and FGR-modulated TTL decay.
|
|
57
|
+
|
|
58
|
+
| Object | What it is | Plain example |
|
|
59
|
+
|--------|-----------|---------------|
|
|
60
|
+
| `ContextPrimitive` | A bounded area where words have specific meanings | "Project Delivery" context where "deploy" means "push to production" |
|
|
61
|
+
| `RolePrimitive` | A role someone plays in a context, with conflicts | "Analyst" role — cannot also be "Approver" (separation of duties) |
|
|
62
|
+
| `WorkPrimitive` | A record of something planned or actually done | "Deployment plan" (plan) vs "Deployment executed at 3pm" (enactment) |
|
|
63
|
+
| `CommitmentPrimitive` | A rule: MUST, SHOULD, or MAY do something | "MUST have test results before deploying" |
|
|
64
|
+
| `GatePrimitive` | A checkpoint with pass/degrade/abstain outcome | "Deployment gate" — checks if tests passed AND approval obtained |
|
|
65
|
+
| `EvidencePrimitive` | A piece of evidence with a trust score (F-G-R) | "Test results from CI pipeline" — formality: 0.8, reliability: 0.9 |
|
|
66
|
+
| `TransitionPrimitive` | A move from one state to another, may require a gate | "ready_for_decision → deploying" requires deploy_gate to pass |
|
|
67
|
+
| `PublicationPrimitive` | A way to show results to an audience | "Assurance view for stakeholders" — only available after gate passes |
|
|
68
|
+
|
|
69
|
+
## The 6 logic operators (logic.py)
|
|
70
|
+
|
|
71
|
+
These are the standard logic operators from computer science. They evaluate to true or false against the current state.
|
|
72
|
+
|
|
73
|
+
| Operator | Symbol | What it checks | Example |
|
|
74
|
+
|----------|--------|---------------|---------|
|
|
75
|
+
| NOT | ¬ | The opposite | `NOT(evidence exists)` → true when evidence is missing |
|
|
76
|
+
| AND | ∧ | Both must be true | `tests_pass AND approval_obtained` → true only when both exist |
|
|
77
|
+
| OR | ∨ | At least one true | `rollback_plan OR not_at_deploy` → true if either holds |
|
|
78
|
+
| XOR | ⊕ | Exactly one true | `analyst XOR approver` → true when exactly one role is active |
|
|
79
|
+
| IMPLIES | → | If A then B | `gate_blocked IMPLIES gaps_exist` → false only when gate is blocked but no gaps |
|
|
80
|
+
| IFF | ↔ | Both same value | `ready_state IFF gate_passes` → true when both true or both false |
|
|
81
|
+
|
|
82
|
+
These get composed into `DecisionRule` objects. Each rule has:
|
|
83
|
+
- a `name`
|
|
84
|
+
- a `condition` (composed from the operators above)
|
|
85
|
+
- an `action_if_true` and optional `action_if_false`
|
|
86
|
+
- a `kind`: block, warn, route, or hint
|
|
87
|
+
- `tags` for filtering (so you can evaluate only "deploy" rules, or only "roles" rules)
|
|
88
|
+
- `exclusive_with` for contradiction detection
|
|
89
|
+
|
|
90
|
+
Rules are collected in a `LogicLayer` and evaluated together. The layer checks for consistency (no contradictory actions firing at the same time).
|
|
91
|
+
|
|
92
|
+
## The 9 guards (guards.py)
|
|
93
|
+
|
|
94
|
+
These are hard constraints. The model cannot override them. If a guard says DENY, the action is blocked.
|
|
95
|
+
|
|
96
|
+
| Guard | What it prevents |
|
|
97
|
+
|-------|-----------------|
|
|
98
|
+
| `commitment_evidence` | You cannot claim a MUST commitment is met without the evidence it requires |
|
|
99
|
+
| `planning_not_enactment` | Having a plan does not mean the work is done — cannot transition to "done" without enactment records |
|
|
100
|
+
| `role_conflict` | Two incompatible roles cannot be active at the same time (e.g., analyst and approver) |
|
|
101
|
+
| `gate_pass` | If a transition requires a gate and the gate abstains (insufficient evidence), the transition is blocked |
|
|
102
|
+
| `scope_check` | You cannot act in another context without an explicit bridge between contexts |
|
|
103
|
+
| `evidence_freshness` | Stale or TTL-expired evidence triggers a warning (uses floor-based decay) |
|
|
104
|
+
| `context_invariants` | Context invariants are surfaced as warnings for the model to consider |
|
|
105
|
+
| `expired_assignment` | Expired role assignments cannot authorize new work |
|
|
106
|
+
| `speech_act_validity` | Expired or revoked speech acts (approvals, authorizations) trigger denial |
|
|
107
|
+
|
|
108
|
+
Each guard has a `GuardScope` (TRANSITION, ROLE, EVIDENCE, or GLOBAL). The engine can evaluate only guards relevant to a specific move.
|
|
109
|
+
|
|
110
|
+
## How a step works (traversal.py)
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Input: an ActiveState (context + role + evidence + current position)
|
|
114
|
+
optionally: a specific transition_id to focus on
|
|
115
|
+
|
|
116
|
+
1. Check: is there an active context? If not → CHANGE_FRAME
|
|
117
|
+
2. Evaluate logic rules (filtered by tags if given)
|
|
118
|
+
- If rules contradict each other → ABSTAIN
|
|
119
|
+
3. Run guards (scoped to the transition if given)
|
|
120
|
+
- If any guard says DENY and evidence is missing → COLLECT_EVIDENCE
|
|
121
|
+
- If any guard says DENY and no evidence path → ABSTAIN
|
|
122
|
+
4. Check for missing evidence on current transitions
|
|
123
|
+
- If gaps exist → COLLECT_EVIDENCE
|
|
124
|
+
5. Check if transitions exist from current state
|
|
125
|
+
- If actions available → CONTINUE
|
|
126
|
+
- If bridges available → BRIDGE (cross-context escape)
|
|
127
|
+
- If nothing → IDLE (at rest, not stuck)
|
|
128
|
+
- If transitions available → CONTINUE
|
|
129
|
+
|
|
130
|
+
Output: an Outcome with:
|
|
131
|
+
- kind: continue / ask / abstain / escalate / publish / revise_plan / collect_evidence / change_frame / idle / bridge
|
|
132
|
+
- reason: why this outcome
|
|
133
|
+
- missing_evidence: what is needed (if applicable)
|
|
134
|
+
- warnings: non-blocking issues
|
|
135
|
+
- llm_prompt_state: the JSON the model reads to decide its next move
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
When `transition_id` is given, the model gets a `slice()` — a tiny dict with just the move, its gate, its evidence, and whether it can fire. That is the per-move maneuver board.
|
|
139
|
+
|
|
140
|
+
## How state works (state.py)
|
|
141
|
+
|
|
142
|
+
Three objects:
|
|
143
|
+
|
|
144
|
+
**SemanticMap** — the static board. You register all your primitives here once. It does not change during a run.
|
|
145
|
+
|
|
146
|
+
**RuntimeBinding** — the input variables for one question/task. Includes:
|
|
147
|
+
- `task`, `goal`, `actor`
|
|
148
|
+
- `actor_role_ids` — which roles are active (must be explicitly listed, not inferred)
|
|
149
|
+
- `active_context_id` — which context we are in
|
|
150
|
+
- `current_evidence` — what evidence is available right now
|
|
151
|
+
- `risk_level` — low / normal / high / critical
|
|
152
|
+
- `candidate_actions`, `constraints`, `available_tools`, `audience`
|
|
153
|
+
|
|
154
|
+
**ActiveState** — the live state. Combines the map + binding + current position. Properties:
|
|
155
|
+
- `active_roles` — only roles that match both the binding AND the active context (no cross-context leakage)
|
|
156
|
+
- `possible_transitions` — only transitions in the active context from the current state
|
|
157
|
+
- `missing_evidence_for(transition_id)` — what this specific move needs that we don't have
|
|
158
|
+
- `slice(transition_id)` — tiny dict for one move
|
|
159
|
+
- `transition_to(transition_id)` — execute a transition (checks context, evidence, and gates)
|
|
160
|
+
|
|
161
|
+
**MoveTrace** — compressed history. Only stores last move, not full history: previous_state, last_transition_id, blockers, evidence_delta.
|
|
162
|
+
|
|
163
|
+
## Boundary rules (enforced, not advisory)
|
|
164
|
+
|
|
165
|
+
These constraints are checked at execution time, not just in the display layer:
|
|
166
|
+
|
|
167
|
+
1. **A transition from context B cannot execute when context A is active.** Both `attempt_transition()` and `transition_to()` check context match.
|
|
168
|
+
2. **A transition with `required_evidence` cannot execute if that evidence is missing.** Both `attempt_transition()` and `transition_to()` enforce this.
|
|
169
|
+
3. **Bound roles are validated against the active context.** A role from context B will not appear in `active_roles` when context A is active.
|
|
170
|
+
4. **Risk-sensitive logic rules are skipped at normal/low risk.** Only evaluated when risk is high or critical.
|
|
171
|
+
|
|
172
|
+
## How to run
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# From the repo root:
|
|
176
|
+
|
|
177
|
+
# Verify the package works (18 checks)
|
|
178
|
+
python -m fpf_thinking_map.verify
|
|
179
|
+
|
|
180
|
+
# Run the deploy decision scenario
|
|
181
|
+
python -m fpf_thinking_map.examples
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
All three should run without errors. `verify` exits 0 on success, 1 on failure.
|
|
185
|
+
|
|
186
|
+
## How to build a new domain
|
|
187
|
+
|
|
188
|
+
Step 1: Create a `SemanticMap` and register your primitives.
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from fpf_thinking_map.state import SemanticMap, RuntimeBinding
|
|
192
|
+
from fpf_thinking_map.primitives import (
|
|
193
|
+
ContextPrimitive, RolePrimitive, GatePrimitive, GateCheck,
|
|
194
|
+
EvidencePrimitive, TransitionPrimitive, Freshness, FGR,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
sm = SemanticMap()
|
|
198
|
+
sm.register_context(ContextPrimitive(
|
|
199
|
+
context_id="my_domain",
|
|
200
|
+
label="My Domain",
|
|
201
|
+
glossary={"review": "check code for correctness"},
|
|
202
|
+
))
|
|
203
|
+
sm.register_role(RolePrimitive("reviewer", "Reviewer", "my_domain"))
|
|
204
|
+
sm.register_gate(GatePrimitive("review_gate", "Review Gate", "my_domain", checks=[
|
|
205
|
+
GateCheck("tests", "Tests must pass", required_evidence=["test_results"]),
|
|
206
|
+
]))
|
|
207
|
+
sm.register_transition(TransitionPrimitive(
|
|
208
|
+
"start_to_reviewed", "Start → Reviewed", "my_domain",
|
|
209
|
+
from_state="start", to_state="reviewed",
|
|
210
|
+
required_gate_id="review_gate",
|
|
211
|
+
required_evidence=["test_results"],
|
|
212
|
+
))
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Step 2: Optionally create logic rules.
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
from fpf_thinking_map.logic import (
|
|
219
|
+
LogicLayer, DecisionRule, RuleKind,
|
|
220
|
+
EvidencePresent, GatePasses,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
logic = LogicLayer()
|
|
224
|
+
logic.add_rule(DecisionRule(
|
|
225
|
+
name="review_ready",
|
|
226
|
+
condition=EvidencePresent("test_results").AND(GatePasses("review_gate")),
|
|
227
|
+
action_if_true="proceed_to_review",
|
|
228
|
+
action_if_false="not_ready",
|
|
229
|
+
kind=RuleKind.ROUTE,
|
|
230
|
+
tags=["review"],
|
|
231
|
+
))
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Step 3: Create the engine and run a step.
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from fpf_thinking_map.traversal import ThinkingMapTraversal
|
|
238
|
+
|
|
239
|
+
engine = ThinkingMapTraversal(sm, logic_layer=logic)
|
|
240
|
+
binding = RuntimeBinding(
|
|
241
|
+
task="review PR #42",
|
|
242
|
+
actor_role_ids=["reviewer"],
|
|
243
|
+
active_context_id="my_domain",
|
|
244
|
+
current_evidence=["test_results"],
|
|
245
|
+
)
|
|
246
|
+
state = engine.build_active_state(binding, current_state="start")
|
|
247
|
+
outcome = engine.step(state, transition_id="start_to_reviewed")
|
|
248
|
+
# outcome.kind → OutcomeKind.CONTINUE (if evidence and gate pass)
|
|
249
|
+
# outcome.llm_prompt_state → the JSON for the model to read
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## What this is NOT
|
|
253
|
+
|
|
254
|
+
- Not a prompt template or system prompt
|
|
255
|
+
- Not a retrieval/RAG system for FPF text
|
|
256
|
+
- Not a replacement for the full FPF spec (51k lines — we extracted 8 objects)
|
|
257
|
+
- Not a symbolic AI / expert system (the LLM interprets; logic + guards constrain)
|
|
258
|
+
- Not a framework to build on top of — it is a small self-contained package
|
|
259
|
+
|
|
260
|
+
## Known design decisions
|
|
261
|
+
|
|
262
|
+
- `satisfied: true` on a vacuously true implication (antecedent false → implication holds trivially) is mathematically correct. The action is suppressed on HINT/WARN rules, so the model sees no misleading instruction. The `satisfied` flag itself stays honest.
|
|
263
|
+
- `demo_walk()` auto-fires the first available transition. It is for testing and examples only, not for operational use. In real use, the LLM calls `step()` and `attempt_transition()` with explicit choices.
|
|
264
|
+
- Publications are registered on the map but stay out of the step/guard/logic path. They are for publish-type moves only.
|
|
265
|
+
|
|
266
|
+
prichindel.com | 2026-06-26 | v1.1.2
|