specsmith 0.2.4.dev54__py3-none-any.whl → 0.2.4.dev589__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.
- epistemic/__init__.py +174 -0
- epistemic/belief.py +364 -0
- epistemic/certainty.py +199 -0
- epistemic/failure_graph.py +156 -0
- epistemic/py.typed +0 -0
- epistemic/recovery.py +223 -0
- epistemic/session.py +428 -0
- epistemic/stress_tester.py +355 -0
- epistemic/trace.py +209 -0
- specsmith/__init__.py +2 -2
- specsmith/__main__.py +1 -1
- specsmith/agent/__init__.py +0 -0
- specsmith/agent/broker.py +694 -0
- specsmith/agent/chat_runner.py +627 -0
- specsmith/agent/cleanup.py +314 -0
- specsmith/agent/context_seed.py +215 -0
- specsmith/agent/core.py +98 -0
- specsmith/agent/dispatch/__init__.py +35 -0
- specsmith/agent/dispatch/_status.py +18 -0
- specsmith/agent/dispatch/dag.py +292 -0
- specsmith/agent/dispatch/dispatcher.py +498 -0
- specsmith/agent/dispatch/events.py +277 -0
- specsmith/agent/dispatch/result.py +64 -0
- specsmith/agent/endpoints.py +495 -0
- specsmith/agent/events.py +254 -0
- specsmith/agent/execution_profiles.py +274 -0
- specsmith/agent/fallback.py +142 -0
- specsmith/agent/hf_leaderboard.py +947 -0
- specsmith/agent/hf_sync.py +181 -0
- specsmith/agent/indexer.py +72 -0
- specsmith/agent/llm_client.py +550 -0
- specsmith/agent/mcp.py +387 -0
- specsmith/agent/memory.py +81 -0
- specsmith/agent/model_intelligence.py +293 -0
- specsmith/agent/model_profiles.py +494 -0
- specsmith/agent/orchestrator.py +411 -0
- specsmith/agent/permissions.py +278 -0
- specsmith/agent/profiles.py +691 -0
- specsmith/agent/provider_registry.py +662 -0
- specsmith/agent/repl.py +174 -0
- specsmith/agent/router.py +78 -0
- specsmith/agent/rules.py +62 -0
- specsmith/agent/runner.py +716 -0
- specsmith/agent/safety.py +109 -0
- specsmith/agent/spawner.py +179 -0
- specsmith/agent/suggester.py +264 -0
- specsmith/agent/teams.py +103 -0
- specsmith/agent/tools.py +693 -0
- specsmith/agent/verifier.py +123 -0
- specsmith/agent/voice.py +143 -0
- specsmith/approvals.py +124 -0
- specsmith/architect.py +1 -1
- specsmith/auditor.py +928 -58
- specsmith/auth.py +279 -0
- specsmith/block_export.py +106 -0
- specsmith/channel.py +112 -0
- specsmith/ci_manager.py +498 -0
- specsmith/cli.py +11084 -246
- specsmith/commands/__init__.py +1 -1
- specsmith/commands/intelligence.py +416 -0
- specsmith/commands/issues_policy.py +241 -0
- specsmith/commands/reporting.py +891 -0
- specsmith/compliance/__init__.py +73 -0
- specsmith/compliance/_compat.py +281 -0
- specsmith/compliance/checker.py +311 -0
- specsmith/compliance/evidence.py +497 -0
- specsmith/compliance/regulations.py +798 -0
- specsmith/compliance/reporter.py +284 -0
- specsmith/compressor.py +30 -15
- specsmith/config.py +409 -17
- specsmith/console_utils.py +63 -0
- specsmith/context_orchestrator.py +290 -0
- specsmith/context_window.py +274 -0
- specsmith/credit_analyzer.py +1 -1
- specsmith/credits.py +11 -2
- specsmith/dashboard.py +125 -0
- specsmith/datasources/__init__.py +14 -0
- specsmith/datasources/base.py +141 -0
- specsmith/datasources/citations.py +83 -0
- specsmith/datasources/fpd.py +72 -0
- specsmith/datasources/odp.py +75 -0
- specsmith/datasources/patentsview.py +272 -0
- specsmith/datasources/pfw.py +81 -0
- specsmith/datasources/ppubs.py +111 -0
- specsmith/datasources/ptab.py +126 -0
- specsmith/differ.py +45 -2
- specsmith/doctor.py +146 -35
- specsmith/drive.py +126 -0
- specsmith/editor.py +277 -0
- specsmith/epistemic/__init__.py +62 -0
- specsmith/epistemic/belief.py +393 -0
- specsmith/epistemic/certainty.py +252 -0
- specsmith/epistemic/failure_graph.py +214 -0
- specsmith/epistemic/recovery.py +349 -0
- specsmith/epistemic/stress_tester.py +440 -0
- specsmith/esdb/__init__.py +194 -0
- specsmith/esdb/_license.py +226 -0
- specsmith/esdb/bridge.py +65 -0
- specsmith/esdb/sqlite_store.py +481 -0
- specsmith/eval/__init__.py +111 -0
- specsmith/eval/builtins.py +95 -0
- specsmith/eval/runner.py +208 -0
- specsmith/executor.py +1 -1
- specsmith/exporter.py +44 -7
- specsmith/governance_logic.py +1068 -0
- specsmith/governance_store.py +173 -0
- specsmith/governance_yaml.py +544 -0
- specsmith/governed_pr.py +76 -0
- specsmith/gui/__init__.py +9 -0
- specsmith/gui/app.py +50 -0
- specsmith/gui/main_window.py +317 -0
- specsmith/gui/session_tab.py +346 -0
- specsmith/gui/theme.py +369 -0
- specsmith/gui/widgets/__init__.py +3 -0
- specsmith/gui/widgets/chat_view.py +230 -0
- specsmith/gui/widgets/input_bar.py +227 -0
- specsmith/gui/widgets/provider_bar.py +150 -0
- specsmith/gui/widgets/token_meter.py +132 -0
- specsmith/gui/widgets/tool_panel.py +117 -0
- specsmith/gui/widgets/update_checker.py +81 -0
- specsmith/gui/worker.py +230 -0
- specsmith/history_search.py +159 -0
- specsmith/importer.py +499 -66
- specsmith/instinct.py +330 -0
- specsmith/integrations/__init__.py +25 -6
- specsmith/integrations/{warp.py → agent_skill.py} +19 -9
- specsmith/integrations/aider.py +1 -1
- specsmith/integrations/base.py +2 -2
- specsmith/integrations/claude_code.py +1 -1
- specsmith/integrations/codity.py +311 -0
- specsmith/integrations/copilot.py +1 -1
- specsmith/integrations/cursor.py +1 -1
- specsmith/integrations/gemini.py +1 -1
- specsmith/integrations/windsurf.py +1 -1
- specsmith/issue_reporter.py +373 -0
- specsmith/languages.py +332 -0
- specsmith/ledger.py +126 -11
- specsmith/mcp_generator.py +210 -0
- specsmith/mcp_server.py +809 -0
- specsmith/migrations/__init__.py +138 -0
- specsmith/migrations/m001_governance_yaml.py +133 -0
- specsmith/migrations/m002_agents_slim.py +106 -0
- specsmith/migrations/m003_compliance_init.py +108 -0
- specsmith/migrations/m004_ledger_esdb.py +91 -0
- specsmith/migrations/m005_agent_run_tool.py +191 -0
- specsmith/migrations/m006_session_governance.py +230 -0
- specsmith/migrations/runner.py +116 -0
- specsmith/ollama_cmds.py +409 -0
- specsmith/patent.py +287 -0
- specsmith/paths.py +152 -0
- specsmith/phase.py +627 -0
- specsmith/plugins.py +103 -2
- specsmith/policy.py +125 -0
- specsmith/profiles.py +425 -0
- specsmith/rate_limits.py +153 -4
- specsmith/recover.py +69 -0
- specsmith/releaser.py +1 -1
- specsmith/requirements.py +119 -28
- specsmith/requirements_parser.py +88 -0
- specsmith/retrieval.py +150 -0
- specsmith/risk.py +148 -0
- specsmith/safe_write.py +188 -0
- specsmith/scaffolder.py +251 -7
- specsmith/serve.py +808 -0
- specsmith/session.py +1 -1
- specsmith/session_init.py +280 -0
- specsmith/session_store.py +144 -0
- specsmith/skills/__init__.py +282 -0
- specsmith/skills/ai_agents.py +1439 -0
- specsmith/skills/cloud.py +457 -0
- specsmith/skills/corporate.py +901 -0
- specsmith/skills/cross_platform.py +570 -0
- specsmith/skills/data_engineering.py +960 -0
- specsmith/skills/devops.py +887 -0
- specsmith/skills/docs.py +1002 -0
- specsmith/skills/embedded.py +1361 -0
- specsmith/skills/governance.py +1247 -0
- specsmith/skills/hardware.py +1442 -0
- specsmith/skills/mobile.py +420 -0
- specsmith/skills/platform_engineering.py +1391 -0
- specsmith/skills/productivity.py +336 -0
- specsmith/skills/software_engineering.py +1521 -0
- specsmith/skills/specsmith_skills.py +267 -0
- specsmith/skills/ssh.py +377 -0
- specsmith/skills/web_backend.py +1427 -0
- specsmith/skills_builder.py +306 -0
- specsmith/sync.py +631 -0
- specsmith/templates/agents.md.j2 +150 -168
- specsmith/templates/community/contributing.md.j2 +2 -2
- specsmith/templates/community/pull_request_template.md.j2 +1 -1
- specsmith/templates/docs/requirements.md.j2 +7 -7
- specsmith/templates/docs/test-spec.md.j2 +3 -3
- specsmith/templates/editorconfig.j2 +10 -10
- specsmith/templates/gitattributes.j2 +13 -13
- specsmith/templates/gitignore.j2 +52 -19
- specsmith/templates/governance/belief-registry.md.j2 +77 -0
- specsmith/templates/governance/context-budget.md.j2 +3 -2
- specsmith/templates/governance/epistemic-axioms.md.j2 +105 -0
- specsmith/templates/governance/failure-modes.md.j2 +92 -0
- specsmith/templates/governance/lifecycle.md.j2 +44 -0
- specsmith/templates/governance/rules.md.j2 +27 -0
- specsmith/templates/governance/{workflow.md.j2 → session-protocol.md.j2} +1 -1
- specsmith/templates/governance/uncertainty-map.md.j2 +76 -0
- specsmith/templates/js/package.json.j2 +2 -2
- specsmith/templates/ledger.md.j2 +3 -3
- specsmith/templates/python/pyproject.toml.j2 +9 -2
- specsmith/templates/readme.md.j2 +2 -2
- specsmith/templates/rust/Cargo.toml.j2 +2 -2
- specsmith/templates/scripts/setup.cmd.j2 +25 -2
- specsmith/templates/scripts/setup.sh.j2 +24 -3
- specsmith/tool_installer.py +600 -0
- specsmith/toolrules.py +404 -0
- specsmith/tools.py +309 -13
- specsmith/trace.py +302 -0
- specsmith/transcripts.py +140 -0
- specsmith/updater.py +69 -18
- specsmith/upgrader.py +161 -31
- specsmith/validator.py +132 -7
- specsmith/vcs/__init__.py +1 -1
- specsmith/vcs/base.py +1 -1
- specsmith/vcs/bitbucket.py +1 -1
- specsmith/vcs/github.py +12 -12
- specsmith/vcs/gitlab.py +1 -1
- specsmith/vcs_commands.py +40 -4
- specsmith/wi_store.py +382 -0
- specsmith/wireframes.py +86 -0
- specsmith/workspace.py +203 -0
- specsmith-0.2.4.dev589.dist-info/METADATA +1233 -0
- specsmith-0.2.4.dev589.dist-info/RECORD +255 -0
- {specsmith-0.2.4.dev54.dist-info → specsmith-0.2.4.dev589.dist-info}/licenses/LICENSE +1 -1
- {specsmith-0.2.4.dev54.dist-info → specsmith-0.2.4.dev589.dist-info}/top_level.txt +1 -0
- specsmith/templates/docs/workflow.md.j2 +0 -15
- specsmith-0.2.4.dev54.dist-info/METADATA +0 -198
- specsmith-0.2.4.dev54.dist-info/RECORD +0 -88
- {specsmith-0.2.4.dev54.dist-info → specsmith-0.2.4.dev589.dist-info}/WHEEL +0 -0
- {specsmith-0.2.4.dev54.dist-info → specsmith-0.2.4.dev589.dist-info}/entry_points.txt +0 -0
epistemic/__init__.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""Applied Epistemic Engineering — standalone Python library.
|
|
4
|
+
|
|
5
|
+
Install
|
|
6
|
+
-------
|
|
7
|
+
pip install specsmith # installs both specsmith and epistemic
|
|
8
|
+
|
|
9
|
+
The ``epistemic`` package is co-installed with specsmith and has **zero
|
|
10
|
+
external dependencies** beyond Python 3.10+. It can be imported by any
|
|
11
|
+
Python project to incorporate AEE practices.
|
|
12
|
+
|
|
13
|
+
Quick start
|
|
14
|
+
-----------
|
|
15
|
+
The simplest entry point is ``AEESession``::
|
|
16
|
+
|
|
17
|
+
from epistemic import AEESession
|
|
18
|
+
|
|
19
|
+
session = AEESession(project_name="my-research")
|
|
20
|
+
session.add_belief(
|
|
21
|
+
artifact_id="HYP-001",
|
|
22
|
+
propositions=["Our decipherment hypothesis is internally consistent"],
|
|
23
|
+
epistemic_boundary=["Corpus: 500 inscriptions, phase 1 only"],
|
|
24
|
+
domain="linguistics",
|
|
25
|
+
)
|
|
26
|
+
result = session.run()
|
|
27
|
+
print(result.summary())
|
|
28
|
+
|
|
29
|
+
For non-trivial projects you'll want to:
|
|
30
|
+
|
|
31
|
+
1. ``add_belief()`` — register claims, hypotheses, requirements
|
|
32
|
+
2. ``add_evidence()`` / ``mark_covered()`` — record what's been validated
|
|
33
|
+
3. ``accept()`` — elevate to ACCEPTED status (binds stress-testing)
|
|
34
|
+
4. ``run()`` — execute the full AEE pipeline
|
|
35
|
+
5. ``seal()`` — cryptographically seal the epistemic state
|
|
36
|
+
|
|
37
|
+
What AEE provides
|
|
38
|
+
-----------------
|
|
39
|
+
Applied Epistemic Engineering treats belief systems like code: codable,
|
|
40
|
+
testable, and deployable. Its formal mathematical foundations include:
|
|
41
|
+
|
|
42
|
+
**Five axioms:**
|
|
43
|
+
1. Observability — every belief must be inspectable (hidden assumptions → stop)
|
|
44
|
+
2. Falsifiability — every belief must be challengeable (dogma ≠ engineering)
|
|
45
|
+
3. Irreducibility — decompose to atomic primitives (compound claims → Logic Knots)
|
|
46
|
+
4. Reconstructability — every failed belief can be reconstructed (scope may narrow)
|
|
47
|
+
5. Convergence — S+R iteration always converges to equilibrium E
|
|
48
|
+
|
|
49
|
+
**Core process: Frame → Disassemble → Stress-Test → Reconstruct**
|
|
50
|
+
|
|
51
|
+
**Key operators:**
|
|
52
|
+
S(B) = StressTester — adversarial challenge function
|
|
53
|
+
R(K) = RecoveryOperator — resolves Logic Knots K
|
|
54
|
+
G = FailureModeGraph — maps stress-test → breakpoint relations
|
|
55
|
+
E = Equilibrium point where S(G) yields no new failures
|
|
56
|
+
C = Certainty score ∈ [0, 1] from CertaintyEngine
|
|
57
|
+
|
|
58
|
+
Real-world use cases
|
|
59
|
+
--------------------
|
|
60
|
+
Software engineering: requirements as BeliefArtifacts, tests as falsifiers
|
|
61
|
+
Linguistics research: hypotheses as BeliefArtifacts, experiments as evidence
|
|
62
|
+
AI alignment: model assumptions as BeliefArtifacts, red-teaming as stress-tests
|
|
63
|
+
Policy/compliance: regulations as BeliefArtifacts, audits as failure modes
|
|
64
|
+
Patent prosecution: claims as BeliefArtifacts, prior art as stress-tests
|
|
65
|
+
|
|
66
|
+
glossa-lab example
|
|
67
|
+
------------------
|
|
68
|
+
from epistemic import AEESession, ConfidenceLevel, BeliefStatus
|
|
69
|
+
from pathlib import Path
|
|
70
|
+
|
|
71
|
+
# Create a session for Indus script decipherment research
|
|
72
|
+
session = AEESession(
|
|
73
|
+
project_name="glossa-lab-indus",
|
|
74
|
+
threshold=0.65,
|
|
75
|
+
state_file=Path(".epistemic/indus.json"),
|
|
76
|
+
trace_dir=Path(".epistemic"),
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Load previous session state
|
|
80
|
+
session.load()
|
|
81
|
+
|
|
82
|
+
# Register competing hypotheses
|
|
83
|
+
session.add_belief(
|
|
84
|
+
artifact_id="HYP-IND-001",
|
|
85
|
+
propositions=["The Indus script is logosyllabic"],
|
|
86
|
+
epistemic_boundary=["Mahadevan corpus, 2977 inscriptions, 1977 edition"],
|
|
87
|
+
domain="epigraphy",
|
|
88
|
+
status=BeliefStatus.ACCEPTED,
|
|
89
|
+
confidence=ConfidenceLevel.LOW,
|
|
90
|
+
)
|
|
91
|
+
session.add_belief(
|
|
92
|
+
artifact_id="HYP-IND-002",
|
|
93
|
+
propositions=["Indus sign frequency follows Zipf distribution"],
|
|
94
|
+
epistemic_boundary=["Same corpus as HYP-IND-001"],
|
|
95
|
+
inferential_links=["HYP-IND-001"], # confidence propagates from HYP-IND-001
|
|
96
|
+
domain="epigraphy",
|
|
97
|
+
status=BeliefStatus.ACCEPTED,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Record experimental evidence
|
|
101
|
+
session.add_evidence("HYP-IND-001", "Rao et al. 2009 — conditional entropy study")
|
|
102
|
+
session.add_evidence("HYP-IND-002", "Mahadevan 1977 — sign frequency tables")
|
|
103
|
+
session.mark_covered("HYP-IND-001") # has experimental coverage
|
|
104
|
+
|
|
105
|
+
# Run the full AEE pipeline
|
|
106
|
+
result = session.run()
|
|
107
|
+
print(result.summary())
|
|
108
|
+
|
|
109
|
+
# If there are Logic Knots (competing theories), inspect them:
|
|
110
|
+
for id1, id2, reason in result.stress_result.logic_knots:
|
|
111
|
+
print(f"Conflict: {id1} vs {id2}: {reason}")
|
|
112
|
+
|
|
113
|
+
# See the certainty map by domain
|
|
114
|
+
for score in result.certainty_report.scores:
|
|
115
|
+
print(f" {score.artifact_id}: {score.propagated_score:.2f} [{score.label}]")
|
|
116
|
+
|
|
117
|
+
# Seal this session's epistemic state
|
|
118
|
+
session.seal("stress-test", "Indus decipherment hypothesis stress-test v2")
|
|
119
|
+
session.save()
|
|
120
|
+
|
|
121
|
+
References
|
|
122
|
+
----------
|
|
123
|
+
- AEE: https://appliedepistemicengineering.com/
|
|
124
|
+
- ARE: https://github.com/organvm-i-theoria/auto-revision-epistemic-engine
|
|
125
|
+
- VERITAS: https://github.com/AionSystem/VERITAS
|
|
126
|
+
- Springer: https://doi.org/10.1007/s11948-023-00451-3
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
from __future__ import annotations
|
|
130
|
+
|
|
131
|
+
from epistemic.belief import (
|
|
132
|
+
BeliefArtifact,
|
|
133
|
+
BeliefStatus,
|
|
134
|
+
ConfidenceLevel,
|
|
135
|
+
FailureMode,
|
|
136
|
+
FailureSeverity,
|
|
137
|
+
beliefs_from_dicts,
|
|
138
|
+
parse_requirements_as_beliefs,
|
|
139
|
+
)
|
|
140
|
+
from epistemic.certainty import ArtifactCertainty, CertaintyEngine, CertaintyReport
|
|
141
|
+
from epistemic.failure_graph import FailureModeGraph, GraphNode
|
|
142
|
+
from epistemic.recovery import RecoveryOperator, RecoveryProposal, RecoveryStrategy
|
|
143
|
+
from epistemic.session import AEEResult, AEESession
|
|
144
|
+
from epistemic.stress_tester import StressTester, StressTestResult
|
|
145
|
+
|
|
146
|
+
__version__ = "0.3.0"
|
|
147
|
+
|
|
148
|
+
__all__ = [
|
|
149
|
+
# Session facade (primary entry point)
|
|
150
|
+
"AEESession",
|
|
151
|
+
"AEEResult",
|
|
152
|
+
# Belief model
|
|
153
|
+
"BeliefArtifact",
|
|
154
|
+
"BeliefStatus",
|
|
155
|
+
"ConfidenceLevel",
|
|
156
|
+
"FailureMode",
|
|
157
|
+
"FailureSeverity",
|
|
158
|
+
"parse_requirements_as_beliefs",
|
|
159
|
+
"beliefs_from_dicts",
|
|
160
|
+
# Stress testing
|
|
161
|
+
"StressTester",
|
|
162
|
+
"StressTestResult",
|
|
163
|
+
# Failure graph
|
|
164
|
+
"FailureModeGraph",
|
|
165
|
+
"GraphNode",
|
|
166
|
+
# Recovery
|
|
167
|
+
"RecoveryOperator",
|
|
168
|
+
"RecoveryProposal",
|
|
169
|
+
"RecoveryStrategy",
|
|
170
|
+
# Certainty
|
|
171
|
+
"CertaintyEngine",
|
|
172
|
+
"CertaintyReport",
|
|
173
|
+
"ArtifactCertainty",
|
|
174
|
+
]
|
epistemic/belief.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
|
|
3
|
+
"""Belief Artifact model — core AEE primitive.
|
|
4
|
+
|
|
5
|
+
This module is part of the standalone ``epistemic`` library and has
|
|
6
|
+
**zero dependencies outside Python's stdlib**. It can be imported by any
|
|
7
|
+
Python 3.10+ project, independent of specsmith.
|
|
8
|
+
|
|
9
|
+
pip install specsmith # installs both specsmith and epistemic
|
|
10
|
+
from epistemic import BeliefArtifact, StressTester, CertaintyEngine
|
|
11
|
+
|
|
12
|
+
Applied Epistemic Engineering (AEE) treats belief systems like code:
|
|
13
|
+
codable, testable, and deployable. A BeliefArtifact is the fundamental
|
|
14
|
+
unit — a structured claim about what a system does, should do, or must not
|
|
15
|
+
do, with an explicit epistemic boundary (the assumptions within which it holds)
|
|
16
|
+
and a confidence level.
|
|
17
|
+
|
|
18
|
+
Five foundational AEE axioms
|
|
19
|
+
-----------------------------
|
|
20
|
+
1. Observability — Every belief must be inspectable. Hidden assumptions
|
|
21
|
+
are a stop condition.
|
|
22
|
+
2. Falsifiability — Every belief must be challengeable. Unchallenged claims
|
|
23
|
+
are dogma, not engineering.
|
|
24
|
+
3. Irreducibility — Decompose beliefs to atomic primitives. Compound claims
|
|
25
|
+
often hide Logic Knots.
|
|
26
|
+
4. Reconstructability — Every failed belief can be reconstructed. Recovery is
|
|
27
|
+
always possible; scope may need to narrow.
|
|
28
|
+
5. Convergence — Systematic S+R application always converges to an
|
|
29
|
+
Equilibrium Point E where S(G) yields no new failures.
|
|
30
|
+
|
|
31
|
+
Real-world applications
|
|
32
|
+
-----------------------
|
|
33
|
+
- **Software engineering**: Requirements as BeliefArtifacts, test gaps as
|
|
34
|
+
stress-test failures, conflicting specs as Logic Knots.
|
|
35
|
+
- **Research**: Hypotheses as BeliefArtifacts, experimental results as
|
|
36
|
+
evidence, competing theories as Logic Knots.
|
|
37
|
+
- **AI alignment**: Model assumptions as BeliefArtifacts, red-teaming as
|
|
38
|
+
stress-testing, hallucinations as confidence failures.
|
|
39
|
+
- **Policy / compliance**: Regulatory claims as BeliefArtifacts, audit
|
|
40
|
+
findings as failure modes, contradictory requirements as Logic Knots.
|
|
41
|
+
|
|
42
|
+
References
|
|
43
|
+
----------
|
|
44
|
+
- AEE: https://appliedepistemicengineering.com/
|
|
45
|
+
- ARE framework: https://github.com/organvm-i-theoria/auto-revision-epistemic-engine
|
|
46
|
+
- VERITAS/CERTUS: https://github.com/AionSystem/VERITAS
|
|
47
|
+
- AI as Epistemic Technology (Springer): https://doi.org/10.1007/s11948-023-00451-3
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
from __future__ import annotations
|
|
51
|
+
|
|
52
|
+
import re
|
|
53
|
+
from dataclasses import dataclass, field
|
|
54
|
+
from enum import Enum
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class ConfidenceLevel(str, Enum):
|
|
59
|
+
"""Epistemic confidence assigned to a BeliefArtifact.
|
|
60
|
+
|
|
61
|
+
Maps to a numeric score used by CertaintyEngine:
|
|
62
|
+
UNKNOWN → 0.0 (no evidence, new claim)
|
|
63
|
+
LOW → 0.25 (asserted but not stress-tested)
|
|
64
|
+
MEDIUM → 0.55 (stress-tested with minor failures resolved)
|
|
65
|
+
HIGH → 0.85 (stress-tested, equilibrium reached, evidence present)
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
UNKNOWN = "unknown"
|
|
69
|
+
LOW = "low"
|
|
70
|
+
MEDIUM = "medium"
|
|
71
|
+
HIGH = "high"
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def score(self) -> float:
|
|
75
|
+
"""Numeric score for propagation calculations."""
|
|
76
|
+
return _CONFIDENCE_SCORES[self]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
_CONFIDENCE_SCORES: dict[ConfidenceLevel, float] = {
|
|
80
|
+
ConfidenceLevel.UNKNOWN: 0.0,
|
|
81
|
+
ConfidenceLevel.LOW: 0.25,
|
|
82
|
+
ConfidenceLevel.MEDIUM: 0.55,
|
|
83
|
+
ConfidenceLevel.HIGH: 0.85,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class BeliefStatus(str, Enum):
|
|
88
|
+
"""Lifecycle status of a BeliefArtifact."""
|
|
89
|
+
|
|
90
|
+
DRAFT = "draft"
|
|
91
|
+
ACCEPTED = "accepted"
|
|
92
|
+
STRESS_TESTED = "stress-tested"
|
|
93
|
+
RECONSTRUCTED = "reconstructed"
|
|
94
|
+
DEPRECATED = "deprecated"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class FailureSeverity(str, Enum):
|
|
98
|
+
"""Severity of a failure mode in the Failure-Mode Graph."""
|
|
99
|
+
|
|
100
|
+
CRITICAL = "critical"
|
|
101
|
+
HIGH = "high"
|
|
102
|
+
MEDIUM = "medium"
|
|
103
|
+
LOW = "low"
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass
|
|
107
|
+
class FailureMode:
|
|
108
|
+
"""A single failure mode discovered by the StressTester.
|
|
109
|
+
|
|
110
|
+
Represents a stress-test → breakpoint relation in the Failure-Mode Graph G.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
artifact_id: str
|
|
114
|
+
challenge: str
|
|
115
|
+
breakpoint: str
|
|
116
|
+
severity: FailureSeverity = FailureSeverity.MEDIUM
|
|
117
|
+
recovery_hint: str = ""
|
|
118
|
+
resolved: bool = False
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@dataclass
|
|
122
|
+
class BeliefArtifact:
|
|
123
|
+
"""A codable, testable, deployable unit of knowledge.
|
|
124
|
+
|
|
125
|
+
The fundamental unit of AEE. Can represent:
|
|
126
|
+
- A software requirement (REQ-CLI-001)
|
|
127
|
+
- A research hypothesis (HYP-IND-001)
|
|
128
|
+
- An architectural decision (DEC-001)
|
|
129
|
+
- A compliance claim (COMP-GDPR-001)
|
|
130
|
+
- Any structured belief that must be Observable and Falsifiable
|
|
131
|
+
|
|
132
|
+
Examples
|
|
133
|
+
--------
|
|
134
|
+
Software requirement::
|
|
135
|
+
|
|
136
|
+
req = BeliefArtifact(
|
|
137
|
+
artifact_id="REQ-API-001",
|
|
138
|
+
propositions=["The API must return HTTP 200 for valid requests"],
|
|
139
|
+
epistemic_boundary=["Platform: all", "Auth: JWT required"],
|
|
140
|
+
confidence=ConfidenceLevel.ACCEPTED,
|
|
141
|
+
status=BeliefStatus.ACCEPTED,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
Research hypothesis::
|
|
145
|
+
|
|
146
|
+
hyp = BeliefArtifact(
|
|
147
|
+
artifact_id="HYP-IND-001",
|
|
148
|
+
propositions=["Indus script uses logosyllabic encoding",
|
|
149
|
+
"Sign frequency distribution follows Zipf's law"],
|
|
150
|
+
epistemic_boundary=["Corpus: Mahadevan 2977 inscriptions, 1977"],
|
|
151
|
+
confidence=ConfidenceLevel.LOW,
|
|
152
|
+
status=BeliefStatus.ACCEPTED,
|
|
153
|
+
)
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
artifact_id: str
|
|
157
|
+
propositions: list[str] = field(default_factory=list)
|
|
158
|
+
epistemic_boundary: list[str] = field(default_factory=list)
|
|
159
|
+
inferential_links: list[str] = field(default_factory=list)
|
|
160
|
+
confidence: ConfidenceLevel = ConfidenceLevel.UNKNOWN
|
|
161
|
+
status: BeliefStatus = BeliefStatus.DRAFT
|
|
162
|
+
failure_modes: list[FailureMode] = field(default_factory=list)
|
|
163
|
+
source_text: str = ""
|
|
164
|
+
component: str = ""
|
|
165
|
+
priority: str = ""
|
|
166
|
+
# Optional metadata for non-specsmith uses
|
|
167
|
+
domain: str = "" # e.g., "linguistics", "software", "policy"
|
|
168
|
+
evidence: list[str] = field(default_factory=list) # evidence citations
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def is_accepted(self) -> bool:
|
|
172
|
+
return self.status in (
|
|
173
|
+
BeliefStatus.ACCEPTED,
|
|
174
|
+
BeliefStatus.STRESS_TESTED,
|
|
175
|
+
BeliefStatus.RECONSTRUCTED,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
@property
|
|
179
|
+
def has_failures(self) -> bool:
|
|
180
|
+
return any(not fm.resolved for fm in self.failure_modes)
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def unresolved_failures(self) -> list[FailureMode]:
|
|
184
|
+
return [fm for fm in self.failure_modes if not fm.resolved]
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def critical_failures(self) -> list[FailureMode]:
|
|
188
|
+
return [
|
|
189
|
+
fm
|
|
190
|
+
for fm in self.failure_modes
|
|
191
|
+
if not fm.resolved and fm.severity == FailureSeverity.CRITICAL
|
|
192
|
+
]
|
|
193
|
+
|
|
194
|
+
def add_evidence(self, citation: str) -> BeliefArtifact:
|
|
195
|
+
"""Add an evidence citation and elevate confidence if appropriate.
|
|
196
|
+
|
|
197
|
+
Returns self for chaining.
|
|
198
|
+
"""
|
|
199
|
+
self.evidence.append(citation)
|
|
200
|
+
if self.confidence == ConfidenceLevel.UNKNOWN and self.evidence:
|
|
201
|
+
self.confidence = ConfidenceLevel.LOW
|
|
202
|
+
return self
|
|
203
|
+
|
|
204
|
+
def to_dict(self) -> dict[str, object]:
|
|
205
|
+
"""Serialise to a plain dict (JSON-compatible)."""
|
|
206
|
+
return {
|
|
207
|
+
"artifact_id": self.artifact_id,
|
|
208
|
+
"propositions": self.propositions,
|
|
209
|
+
"epistemic_boundary": self.epistemic_boundary,
|
|
210
|
+
"inferential_links": self.inferential_links,
|
|
211
|
+
"confidence": self.confidence.value,
|
|
212
|
+
"status": self.status.value,
|
|
213
|
+
"source_text": self.source_text,
|
|
214
|
+
"component": self.component,
|
|
215
|
+
"priority": self.priority,
|
|
216
|
+
"domain": self.domain,
|
|
217
|
+
"evidence": self.evidence,
|
|
218
|
+
"failure_count": len(self.failure_modes),
|
|
219
|
+
"critical_count": len(self.critical_failures),
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
# ---------------------------------------------------------------------------
|
|
224
|
+
# Markdown parser — converts REQUIREMENTS.md entries to BeliefArtifacts
|
|
225
|
+
# ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
_REQ_HEADING = re.compile(r"^#{1,3}\s+(REQ-([A-Z0-9_]+)-(\d+))\s*(?:—\s*(.+))?$")
|
|
228
|
+
_FIELD_LINE = re.compile(r"^\s*-\s+\*\*(.+?)\*\*:\s*(.+)$")
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def parse_requirements_as_beliefs(path: Path) -> list[BeliefArtifact]:
|
|
232
|
+
"""Parse a REQUIREMENTS.md file and return a list of BeliefArtifacts.
|
|
233
|
+
|
|
234
|
+
Works with both specsmith-generated REQUIREMENTS.md files and
|
|
235
|
+
any markdown file that uses REQ-COMPONENT-NNN heading format.
|
|
236
|
+
"""
|
|
237
|
+
if not path.exists():
|
|
238
|
+
return []
|
|
239
|
+
|
|
240
|
+
content = path.read_text(encoding="utf-8")
|
|
241
|
+
artifacts: list[BeliefArtifact] = []
|
|
242
|
+
current: BeliefArtifact | None = None
|
|
243
|
+
current_desc = ""
|
|
244
|
+
|
|
245
|
+
for line in content.splitlines():
|
|
246
|
+
m = _REQ_HEADING.match(line)
|
|
247
|
+
if m:
|
|
248
|
+
if current is not None:
|
|
249
|
+
_finalise(current, current_desc)
|
|
250
|
+
artifacts.append(current)
|
|
251
|
+
req_id = m.group(1)
|
|
252
|
+
component = m.group(2)
|
|
253
|
+
desc_inline = m.group(4) or ""
|
|
254
|
+
current = BeliefArtifact(
|
|
255
|
+
artifact_id=req_id,
|
|
256
|
+
component=component,
|
|
257
|
+
source_text=desc_inline,
|
|
258
|
+
)
|
|
259
|
+
current_desc = desc_inline
|
|
260
|
+
continue
|
|
261
|
+
|
|
262
|
+
if current is None:
|
|
263
|
+
continue
|
|
264
|
+
|
|
265
|
+
fm = _FIELD_LINE.match(line)
|
|
266
|
+
if fm:
|
|
267
|
+
key = fm.group(1).lower()
|
|
268
|
+
val = fm.group(2).strip()
|
|
269
|
+
if key in ("description", "desc"):
|
|
270
|
+
current_desc = val
|
|
271
|
+
current.source_text = val
|
|
272
|
+
elif key == "priority":
|
|
273
|
+
current.priority = val
|
|
274
|
+
elif key == "status":
|
|
275
|
+
current.status = _map_status(val)
|
|
276
|
+
current.confidence = _infer_confidence(current.status)
|
|
277
|
+
elif key in ("platform", "platforms", "boundary"):
|
|
278
|
+
current.epistemic_boundary.append(f"{key.capitalize()}: {val}")
|
|
279
|
+
elif key == "domain":
|
|
280
|
+
current.domain = val
|
|
281
|
+
elif key == "evidence":
|
|
282
|
+
current.evidence.append(val)
|
|
283
|
+
else:
|
|
284
|
+
stripped = line.strip().lstrip("-").strip()
|
|
285
|
+
if stripped and not stripped.startswith("#") and not current_desc:
|
|
286
|
+
current_desc = stripped
|
|
287
|
+
|
|
288
|
+
if current is not None:
|
|
289
|
+
_finalise(current, current_desc)
|
|
290
|
+
artifacts.append(current)
|
|
291
|
+
|
|
292
|
+
return artifacts
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def beliefs_from_dicts(data: list[dict[str, object]]) -> list[BeliefArtifact]:
|
|
296
|
+
"""Construct BeliefArtifacts from a list of plain dicts.
|
|
297
|
+
|
|
298
|
+
Useful when loading from JSON, YAML, or a database::
|
|
299
|
+
|
|
300
|
+
import yaml
|
|
301
|
+
data = yaml.safe_load(open("hypotheses.yml"))
|
|
302
|
+
artifacts = beliefs_from_dicts(data["beliefs"])
|
|
303
|
+
"""
|
|
304
|
+
artifacts = []
|
|
305
|
+
for d in data:
|
|
306
|
+
a = BeliefArtifact(
|
|
307
|
+
artifact_id=str(d.get("artifact_id", "")),
|
|
308
|
+
propositions=list(d.get("propositions", [])), # type: ignore[arg-type]
|
|
309
|
+
epistemic_boundary=list(d.get("epistemic_boundary", [])), # type: ignore[arg-type]
|
|
310
|
+
inferential_links=list(d.get("inferential_links", [])), # type: ignore[arg-type]
|
|
311
|
+
confidence=ConfidenceLevel(d.get("confidence", "unknown")),
|
|
312
|
+
status=BeliefStatus(d.get("status", "draft")),
|
|
313
|
+
source_text=str(d.get("source_text", "")),
|
|
314
|
+
component=str(d.get("component", "")),
|
|
315
|
+
priority=str(d.get("priority", "")),
|
|
316
|
+
domain=str(d.get("domain", "")),
|
|
317
|
+
evidence=list(d.get("evidence", [])), # type: ignore[arg-type]
|
|
318
|
+
)
|
|
319
|
+
artifacts.append(a)
|
|
320
|
+
return artifacts
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _finalise(artifact: BeliefArtifact, desc: str) -> None:
|
|
324
|
+
if not desc:
|
|
325
|
+
return
|
|
326
|
+
artifact.source_text = artifact.source_text or desc
|
|
327
|
+
parts = re.split(r";|\band\b(?=\s+[A-Z])", desc)
|
|
328
|
+
artifact.propositions = artifact.propositions or [p.strip() for p in parts if p.strip()]
|
|
329
|
+
if not artifact.epistemic_boundary:
|
|
330
|
+
artifact.epistemic_boundary = ["Assumed correct project environment"]
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _map_status(val: str) -> BeliefStatus:
|
|
334
|
+
val_lower = val.lower()
|
|
335
|
+
if "accept" in val_lower:
|
|
336
|
+
return BeliefStatus.ACCEPTED
|
|
337
|
+
if "stress" in val_lower:
|
|
338
|
+
return BeliefStatus.STRESS_TESTED
|
|
339
|
+
if "reconstruct" in val_lower:
|
|
340
|
+
return BeliefStatus.RECONSTRUCTED
|
|
341
|
+
if "deprecat" in val_lower:
|
|
342
|
+
return BeliefStatus.DEPRECATED
|
|
343
|
+
return BeliefStatus.DRAFT
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def _infer_confidence(status: BeliefStatus) -> ConfidenceLevel:
|
|
347
|
+
return {
|
|
348
|
+
BeliefStatus.DRAFT: ConfidenceLevel.UNKNOWN,
|
|
349
|
+
BeliefStatus.ACCEPTED: ConfidenceLevel.LOW,
|
|
350
|
+
BeliefStatus.STRESS_TESTED: ConfidenceLevel.MEDIUM,
|
|
351
|
+
BeliefStatus.RECONSTRUCTED: ConfidenceLevel.HIGH,
|
|
352
|
+
BeliefStatus.DEPRECATED: ConfidenceLevel.LOW,
|
|
353
|
+
}.get(status, ConfidenceLevel.UNKNOWN)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
__all__ = [
|
|
357
|
+
"BeliefArtifact",
|
|
358
|
+
"BeliefStatus",
|
|
359
|
+
"ConfidenceLevel",
|
|
360
|
+
"FailureMode",
|
|
361
|
+
"FailureSeverity",
|
|
362
|
+
"parse_requirements_as_beliefs",
|
|
363
|
+
"beliefs_from_dicts",
|
|
364
|
+
]
|