faultsguards 0.1.0__tar.gz

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.
@@ -0,0 +1,8 @@
1
+ Heuremen LLC
2
+ Source: https://heuremen.org (Faults and Guards) and this repository
3
+
4
+ Free to download, read, run and cite with attribution (Heuremen LLC, with a link to https://heuremen.org).
5
+ Use of the text inside a prompt, a tool call, a retrieval step or a review at the time a model answers is permitted.
6
+ All rights are reserved otherwise. Text and data mining, and use of this text or data to train, fine-tune or build AI models, are not permitted.
7
+ This is an express reservation of rights, also made in machine-readable form at https://indahl.ai/robots.txt and https://indahl.ai/.well-known/tdmrep.json.
8
+ Policy: https://indahl.ai/terms#ai-training
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: faultsguards
3
+ Version: 0.1.0
4
+ Summary: Faults and Guards from Heuremen LLC: the failure modes a model commits doing measurement work, and the procedures against them, as data, prompts and an MCP server.
5
+ Author: Heuremen LLC
6
+ License: Heuremen LLC
7
+ Source: https://heuremen.org (Faults and Guards) and this repository
8
+
9
+ Free to download, read, run and cite with attribution (Heuremen LLC, with a link to https://heuremen.org).
10
+ Use of the text inside a prompt, a tool call, a retrieval step or a review at the time a model answers is permitted.
11
+ All rights are reserved otherwise. Text and data mining, and use of this text or data to train, fine-tune or build AI models, are not permitted.
12
+ This is an express reservation of rights, also made in machine-readable form at https://indahl.ai/robots.txt and https://indahl.ai/.well-known/tdmrep.json.
13
+ Policy: https://indahl.ai/terms#ai-training
14
+
15
+ Requires-Python: >=3.9
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE.txt
18
+ Dynamic: license-file
19
+
20
+ # faultsguards
21
+
22
+ The Faults and Guards from Heuremen LLC as a Python package. Faults is the catalogue of failure modes a model commits doing measurement work. Guards is the set of procedures built against them. The PDFs are at https://heuremen.org/faults.pdf and https://heuremen.org/guards.pdf. The text is also a dataset at https://huggingface.co/datasets/indahl/faultsguards. This package makes the same text usable inside an LLM workflow: structured data, prompt and checklist builders, function-calling schemas, and an MCP server.
23
+
24
+ Live page: https://indahl.ai/iris (the Faults and Guards bench and findings). Dataset: https://huggingface.co/datasets/indahl/faultsguards.
25
+
26
+ Standard library only. It never calls a model and never touches the network. It builds text and returns it.
27
+
28
+ ## Install
29
+
30
+ ```
31
+ pip install git+https://github.com/Heuremen-LLC/faultsguards
32
+ ```
33
+
34
+ ## Look things up
35
+
36
+ ```
37
+ python -m faultsguards faults # the failure modes by family
38
+ python -m faultsguards guards # the procedures by part
39
+ python -m faultsguards show guard 8 # one entry in full
40
+ python -m faultsguards search two option # words in titles and text
41
+ ```
42
+
43
+ ## Put the guards in front of a model
44
+
45
+ ```python
46
+ import faultsguards as fg
47
+ system = fg.system_prompt() # titles only, short. full=True includes every guard's text
48
+ ahead = fg.preflight("Compare our model against the vendor claim.") # the guards that run before the work, then your task
49
+ review = fg.review_prompt(my_text, numbers=[1, 3, 4]) # asks a model to review a text against chosen faults
50
+ ```
51
+
52
+ Each builder marks its own wrapper sentences with "Package line:" so you can tell them from the published text. The review labels are COMMITS, AVOIDS, CANNOT_TELL, NOT_APPLICABLE.
53
+
54
+ ## Function calling
55
+
56
+ `fg.tool_schemas()` returns schemas for list, get, search, preflight and review. `fg.call_tool(name, args)` runs a call and returns the result. See examples/03_tool_calling.py.
57
+
58
+ ## MCP
59
+
60
+ ```
61
+ python -m faultsguards mcp
62
+ ```
63
+
64
+ Newline-delimited JSON-RPC over stdio: initialize, tools/list, tools/call, ping. A client config is in examples/04_mcp_client_config.json.
65
+
66
+ ## What is tested
67
+
68
+ The data in `src/faultsguards/data` is generated from `source/FAULTS.html` and `source/GUARDS.html` by `tools/extract.py`, and a test regenerates it and requires it to equal what ships. Every extracted paragraph is checked to occur in the source. The MCP server is driven through real stdio. Every example runs offline in the test suite. CI rebuilds both PDFs from the sources with headless Chrome and requires their text to equal the published PDFs, ignoring spacing.
69
+
70
+ ```
71
+ python -m unittest discover -s tests
72
+ python tools/build_pdfs.py build && python tools/verify_pdfs.py build
73
+ ```
74
+
75
+ ## What this does not claim
76
+
77
+ Loading this text into a model is not shown to make the model avoid the faults. The Guards document reports that discipline did not change the rate of the most common failure, and that is carried here unchanged. A model test of the effect needs its own plan and is not part of this release.
78
+
79
+ ## Terms
80
+
81
+ Free to download, read, run and cite with attribution. Use inside a prompt, tool or retrieval step at answer time is permitted. Use of the text to train, fine-tune or build AI models is not permitted. See LICENSE.txt. Heuremen LLC, https://heuremen.org.
@@ -0,0 +1,62 @@
1
+ # faultsguards
2
+
3
+ The Faults and Guards from Heuremen LLC as a Python package. Faults is the catalogue of failure modes a model commits doing measurement work. Guards is the set of procedures built against them. The PDFs are at https://heuremen.org/faults.pdf and https://heuremen.org/guards.pdf. The text is also a dataset at https://huggingface.co/datasets/indahl/faultsguards. This package makes the same text usable inside an LLM workflow: structured data, prompt and checklist builders, function-calling schemas, and an MCP server.
4
+
5
+ Live page: https://indahl.ai/iris (the Faults and Guards bench and findings). Dataset: https://huggingface.co/datasets/indahl/faultsguards.
6
+
7
+ Standard library only. It never calls a model and never touches the network. It builds text and returns it.
8
+
9
+ ## Install
10
+
11
+ ```
12
+ pip install git+https://github.com/Heuremen-LLC/faultsguards
13
+ ```
14
+
15
+ ## Look things up
16
+
17
+ ```
18
+ python -m faultsguards faults # the failure modes by family
19
+ python -m faultsguards guards # the procedures by part
20
+ python -m faultsguards show guard 8 # one entry in full
21
+ python -m faultsguards search two option # words in titles and text
22
+ ```
23
+
24
+ ## Put the guards in front of a model
25
+
26
+ ```python
27
+ import faultsguards as fg
28
+ system = fg.system_prompt() # titles only, short. full=True includes every guard's text
29
+ ahead = fg.preflight("Compare our model against the vendor claim.") # the guards that run before the work, then your task
30
+ review = fg.review_prompt(my_text, numbers=[1, 3, 4]) # asks a model to review a text against chosen faults
31
+ ```
32
+
33
+ Each builder marks its own wrapper sentences with "Package line:" so you can tell them from the published text. The review labels are COMMITS, AVOIDS, CANNOT_TELL, NOT_APPLICABLE.
34
+
35
+ ## Function calling
36
+
37
+ `fg.tool_schemas()` returns schemas for list, get, search, preflight and review. `fg.call_tool(name, args)` runs a call and returns the result. See examples/03_tool_calling.py.
38
+
39
+ ## MCP
40
+
41
+ ```
42
+ python -m faultsguards mcp
43
+ ```
44
+
45
+ Newline-delimited JSON-RPC over stdio: initialize, tools/list, tools/call, ping. A client config is in examples/04_mcp_client_config.json.
46
+
47
+ ## What is tested
48
+
49
+ The data in `src/faultsguards/data` is generated from `source/FAULTS.html` and `source/GUARDS.html` by `tools/extract.py`, and a test regenerates it and requires it to equal what ships. Every extracted paragraph is checked to occur in the source. The MCP server is driven through real stdio. Every example runs offline in the test suite. CI rebuilds both PDFs from the sources with headless Chrome and requires their text to equal the published PDFs, ignoring spacing.
50
+
51
+ ```
52
+ python -m unittest discover -s tests
53
+ python tools/build_pdfs.py build && python tools/verify_pdfs.py build
54
+ ```
55
+
56
+ ## What this does not claim
57
+
58
+ Loading this text into a model is not shown to make the model avoid the faults. The Guards document reports that discipline did not change the rate of the most common failure, and that is carried here unchanged. A model test of the effect needs its own plan and is not part of this release.
59
+
60
+ ## Terms
61
+
62
+ Free to download, read, run and cite with attribution. Use inside a prompt, tool or retrieval step at answer time is permitted. Use of the text to train, fine-tune or build AI models is not permitted. See LICENSE.txt. Heuremen LLC, https://heuremen.org.
@@ -0,0 +1,22 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "faultsguards"
7
+ version = "0.1.0"
8
+ description = "Faults and Guards from Heuremen LLC: the failure modes a model commits doing measurement work, and the procedures against them, as data, prompts and an MCP server."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { file = "LICENSE.txt" }
12
+ authors = [{ name = "Heuremen LLC" }]
13
+ dependencies = []
14
+
15
+ [project.scripts]
16
+ faultsguards = "faultsguards.cli:main"
17
+
18
+ [tool.setuptools.packages.find]
19
+ where = ["src"]
20
+
21
+ [tool.setuptools.package-data]
22
+ faultsguards = ["data/*.json"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ """faultsguards: the Faults and Guards of Heuremen LLC as data, prompts and an MCP server. https://heuremen.org/faults.pdf https://heuremen.org/guards.pdf"""
2
+ __version__ = '0.1.0'
3
+ from .core import load, faults, guards, get_fault, get_guard, families, search, source_info
4
+ from .prompts import checklist, preflight, system_prompt, review_prompt, tool_schemas, call_tool, OUTCOMES
@@ -0,0 +1,3 @@
1
+ import sys
2
+ from .cli import main
3
+ sys.exit(main())
@@ -0,0 +1,34 @@
1
+ """python -m faultsguards COMMAND. faults, guards, show, search, prompt, preflight, review, tools, mcp."""
2
+ import sys, json, argparse
3
+ from . import __version__
4
+ from .core import faults, guards, get_fault, get_guard, search, families
5
+ from .prompts import system_prompt, preflight, review_prompt, tool_schemas
6
+ def main(argv=None):
7
+ ap = argparse.ArgumentParser(prog='faultsguards', description='Faults and Guards, Heuremen LLC. https://heuremen.org/faults.pdf')
8
+ ap.add_argument('--version', action='version', version=__version__); sub = ap.add_subparsers(dest='cmd')
9
+ sub.add_parser('faults', help='list the failure modes'); sub.add_parser('guards', help='list the procedures')
10
+ s = sub.add_parser('show', help='print one entry in full'); s.add_argument('which', choices=['fault', 'guard']); s.add_argument('number', type=int)
11
+ s = sub.add_parser('search', help='search by words'); s.add_argument('query', nargs='+')
12
+ s = sub.add_parser('prompt', help='a system prompt listing the guards'); s.add_argument('--full', action='store_true')
13
+ s = sub.add_parser('preflight', help='the guards that run before the work'); s.add_argument('--task'); s.add_argument('--full', action='store_true')
14
+ s = sub.add_parser('review', help='a prompt reviewing a text file against the faults'); s.add_argument('file'); s.add_argument('--numbers', type=int, nargs='*')
15
+ sub.add_parser('tools', help='function-calling schemas as JSON'); sub.add_parser('mcp', help='run the MCP server over stdio')
16
+ a = ap.parse_args(argv)
17
+ if a.cmd == 'faults':
18
+ for f in families('faults'):
19
+ print(f['part']); [print(' %d. %s' % (e['number'], e['title'])) for e in faults() if e['number'] in f['numbers']]
20
+ elif a.cmd == 'guards':
21
+ for f in families('guards'):
22
+ print(f['part']); [print(' %d. %s' % (e['number'], e['title'])) for e in guards() if e['number'] in f['numbers']]
23
+ elif a.cmd == 'show': e = (get_fault if a.which == 'fault' else get_guard)(a.number); print('%d. %s\n%s\n\n%s' % (e['number'], e['title'], e['part'], e['text']))
24
+ elif a.cmd == 'search':
25
+ for h in search(' '.join(a.query)): print('%s %d. %s' % (h['document'], h['number'], h['title']))
26
+ elif a.cmd == 'prompt': print(system_prompt(a.full))
27
+ elif a.cmd == 'preflight': print(preflight(a.task, a.full))
28
+ elif a.cmd == 'review': print(review_prompt(open(a.file, encoding='utf-8').read(), a.numbers))
29
+ elif a.cmd == 'tools': print(json.dumps(tool_schemas(), indent=1))
30
+ elif a.cmd == 'mcp':
31
+ from .mcp_server import serve; serve()
32
+ else: ap.print_help()
33
+ return 0
34
+ if __name__ == '__main__': sys.exit(main())
@@ -0,0 +1,34 @@
1
+ """Data access for the Faults and Guards. The data is generated from the published sources (tools/extract.py) and never edited by hand."""
2
+ import json, os, re
3
+ _D = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
4
+ _cache = {}
5
+ def load(which):
6
+ """which is 'faults' or 'guards'. Returns the whole document: intro, parts, entries, sections."""
7
+ if which not in ('faults', 'guards'): raise ValueError("which must be 'faults' or 'guards'")
8
+ if which not in _cache: _cache[which] = json.load(open(os.path.join(_D, which + '.json'), encoding='utf-8'))
9
+ return _cache[which]
10
+ def faults(): return load('faults')['entries']
11
+ def guards(): return load('guards')['entries']
12
+ def _get(entries, n):
13
+ for e in entries:
14
+ if e['number'] == int(n): return e
15
+ raise KeyError(n)
16
+ def get_fault(n): return _get(faults(), n)
17
+ def get_guard(n): return _get(guards(), n)
18
+ def families(which='faults'):
19
+ """The parts of the document in order, each with its entry numbers."""
20
+ out = []
21
+ for e in load(which)['entries']:
22
+ if not out or out[-1]['part'] != e['part']: out.append(dict(part=e['part'], numbers=[]))
23
+ out[-1]['numbers'].append(e['number'])
24
+ return out
25
+ def search(query, which=None):
26
+ """Entries whose title or text contain every word of the query, case-insensitive. which: 'faults', 'guards' or None for both."""
27
+ words = [w for w in re.findall(r'\w+', query.lower()) if w]; hits = []
28
+ for w in ((which,) if which else ('faults', 'guards')):
29
+ for e in load(w)['entries']:
30
+ hay = (e['title'] + ' ' + e['text']).lower()
31
+ if all(x in hay for x in words): hits.append(dict(document=w, number=e['number'], title=e['title'], part=e['part']))
32
+ return hits
33
+ def source_info():
34
+ return dict(faults='https://heuremen.org/faults.pdf', guards='https://heuremen.org/guards.pdf', publisher='Heuremen LLC')