memproof 0.1.0__tar.gz → 0.3.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.
Files changed (29) hide show
  1. {memproof-0.1.0 → memproof-0.3.0}/PKG-INFO +27 -2
  2. {memproof-0.1.0 → memproof-0.3.0}/README.md +25 -0
  3. {memproof-0.1.0 → memproof-0.3.0}/memproof/__init__.py +1 -1
  4. {memproof-0.1.0 → memproof-0.3.0}/memproof/cli.py +50 -0
  5. memproof-0.3.0/memproof/skills.py +529 -0
  6. memproof-0.3.0/memproof/skillsec.py +309 -0
  7. {memproof-0.1.0 → memproof-0.3.0}/memproof.egg-info/PKG-INFO +27 -2
  8. {memproof-0.1.0 → memproof-0.3.0}/memproof.egg-info/SOURCES.txt +5 -1
  9. {memproof-0.1.0 → memproof-0.3.0}/memproof.egg-info/requires.txt +1 -1
  10. {memproof-0.1.0 → memproof-0.3.0}/pyproject.toml +2 -2
  11. {memproof-0.1.0 → memproof-0.3.0}/tests/test_cli.py +1 -1
  12. memproof-0.3.0/tests/test_security.py +163 -0
  13. memproof-0.3.0/tests/test_skills.py +225 -0
  14. {memproof-0.1.0 → memproof-0.3.0}/LICENSE +0 -0
  15. {memproof-0.1.0 → memproof-0.3.0}/memproof/__main__.py +0 -0
  16. {memproof-0.1.0 → memproof-0.3.0}/memproof/checks/__init__.py +0 -0
  17. {memproof-0.1.0 → memproof-0.3.0}/memproof/checks/freshness.py +0 -0
  18. {memproof-0.1.0 → memproof-0.3.0}/memproof/checks/frontmatter.py +0 -0
  19. {memproof-0.1.0 → memproof-0.3.0}/memproof/checks/links.py +0 -0
  20. {memproof-0.1.0 → memproof-0.3.0}/memproof/checks/provenance.py +0 -0
  21. {memproof-0.1.0 → memproof-0.3.0}/memproof/checks/structure.py +0 -0
  22. {memproof-0.1.0 → memproof-0.3.0}/memproof/model.py +0 -0
  23. {memproof-0.1.0 → memproof-0.3.0}/memproof/report.py +0 -0
  24. {memproof-0.1.0 → memproof-0.3.0}/memproof/vault.py +0 -0
  25. {memproof-0.1.0 → memproof-0.3.0}/memproof.egg-info/dependency_links.txt +0 -0
  26. {memproof-0.1.0 → memproof-0.3.0}/memproof.egg-info/entry_points.txt +0 -0
  27. {memproof-0.1.0 → memproof-0.3.0}/memproof.egg-info/top_level.txt +0 -0
  28. {memproof-0.1.0 → memproof-0.3.0}/setup.cfg +0 -0
  29. {memproof-0.1.0 → memproof-0.3.0}/tests/test_checks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memproof
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Evidence-first health checks for Markdown knowledge vaults.
5
5
  Author: memproof contributors
6
6
  License-Expression: MIT
@@ -19,24 +19,49 @@ License-File: LICENSE
19
19
  Requires-Dist: pyyaml>=6.0
20
20
  Provides-Extra: dev
21
21
  Requires-Dist: pytest>=8.0; extra == "dev"
22
- Requires-Dist: ruff>=0.6; extra == "dev"
22
+ Requires-Dist: ruff==0.17.2; extra == "dev"
23
23
  Requires-Dist: mypy>=1.11; extra == "dev"
24
24
  Dynamic: license-file
25
25
 
26
26
  # memproof
27
27
 
28
+ [![PyPI](https://img.shields.io/pypi/v/memproof.svg)](https://pypi.org/project/memproof/)
29
+ [![test](https://github.com/hsys123/memproof/actions/workflows/test.yml/badge.svg)](https://github.com/hsys123/memproof/actions/workflows/test.yml)
30
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
31
+
28
32
  Evidence-first health checks for Markdown knowledge vaults.
29
33
 
30
34
  `memproof` answers one question: **can you prove what your knowledge base claims?**
31
35
  Every finding carries a `path:line`, the evidence behind it, and a concrete fix.
32
36
  It is read-only, offline, and deterministic.
33
37
 
38
+ ## Security rule layer
39
+
40
+ memproof skills also scans every skill for credential-shaped strings,
41
+ rule-override instructions, memory-file tampering, and fetch-piped-to-execute
42
+ combos. Evidence for matched secrets is masked in the report - the finding tells
43
+ you where and what shape, never the value itself. Use --no-security to run
44
+ spec/registry checks only.
45
+
46
+ ## Check Agent Skills (agentskills.io)
47
+
48
+ Point `memproof skills` at a directory of `skills/<name>/SKILL.md` to validate the agentskills.io
49
+ contract: kebab-case names that match their directory, description limits,
50
+ optional-field types and unknown keys. Add `--registry skills.json` to diff the disk against a declared skill registry in both directions.
51
+
52
+ ```bash
53
+ memproof skills ./skills --registry config/skills.json --fail-on high
54
+ ```
55
+
34
56
  ## Install
35
57
 
36
58
  ```bash
37
59
  uv tool install memproof
38
60
  # or
39
61
  pip install memproof
62
+
63
+ # before the PyPI release, install straight from GitHub:
64
+ uv tool install git+https://github.com/hsys123/memproof
40
65
  ```
41
66
 
42
67
  ## Use
@@ -1,17 +1,42 @@
1
1
  # memproof
2
2
 
3
+ [![PyPI](https://img.shields.io/pypi/v/memproof.svg)](https://pypi.org/project/memproof/)
4
+ [![test](https://github.com/hsys123/memproof/actions/workflows/test.yml/badge.svg)](https://github.com/hsys123/memproof/actions/workflows/test.yml)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+
3
7
  Evidence-first health checks for Markdown knowledge vaults.
4
8
 
5
9
  `memproof` answers one question: **can you prove what your knowledge base claims?**
6
10
  Every finding carries a `path:line`, the evidence behind it, and a concrete fix.
7
11
  It is read-only, offline, and deterministic.
8
12
 
13
+ ## Security rule layer
14
+
15
+ memproof skills also scans every skill for credential-shaped strings,
16
+ rule-override instructions, memory-file tampering, and fetch-piped-to-execute
17
+ combos. Evidence for matched secrets is masked in the report - the finding tells
18
+ you where and what shape, never the value itself. Use --no-security to run
19
+ spec/registry checks only.
20
+
21
+ ## Check Agent Skills (agentskills.io)
22
+
23
+ Point `memproof skills` at a directory of `skills/<name>/SKILL.md` to validate the agentskills.io
24
+ contract: kebab-case names that match their directory, description limits,
25
+ optional-field types and unknown keys. Add `--registry skills.json` to diff the disk against a declared skill registry in both directions.
26
+
27
+ ```bash
28
+ memproof skills ./skills --registry config/skills.json --fail-on high
29
+ ```
30
+
9
31
  ## Install
10
32
 
11
33
  ```bash
12
34
  uv tool install memproof
13
35
  # or
14
36
  pip install memproof
37
+
38
+ # before the PyPI release, install straight from GitHub:
39
+ uv tool install git+https://github.com/hsys123/memproof
15
40
  ```
16
41
 
17
42
  ## Use
@@ -1,3 +1,3 @@
1
1
  """memproof — evidence-first health checks for Markdown knowledge vaults."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.3.0"
@@ -10,6 +10,15 @@ from .checks import ALL_CHECKS
10
10
  from .checks import links as links_check
11
11
  from .model import Finding
12
12
  from .report import render_json, render_markdown, write_report
13
+ from .skills import (
14
+ render_json as render_skills_json,
15
+ )
16
+ from .skills import (
17
+ render_markdown as render_skills_markdown,
18
+ )
19
+ from .skills import (
20
+ scan_skills,
21
+ )
13
22
  from .vault import load_vault
14
23
 
15
24
  FAIL_RANK = {"high": 0, "medium": 1, "low": 2}
@@ -56,6 +65,20 @@ def build_parser() -> argparse.ArgumentParser:
56
65
  default=None,
57
66
  help="reference date for freshness checks (YYYY-MM-DD)",
58
67
  )
68
+ skills = subparsers.add_parser("skills", help="check Agent Skills (SKILL.md) spec conformance")
69
+ skills.add_argument("path", type=Path, help="directory containing skills/<name>/SKILL.md")
70
+ skills.add_argument("--registry", type=Path, help="JSON file listing the expected skill ids")
71
+ skills.add_argument(
72
+ "--no-security", action="store_true", help="skip the secret/injection/exec rule layer"
73
+ )
74
+ skills.add_argument("--format", choices=("markdown", "json"), default="markdown")
75
+ skills.add_argument("--output", type=Path, help="write the report to this file")
76
+ skills.add_argument(
77
+ "--fail-on",
78
+ choices=("none", "low", "medium", "high"),
79
+ default="none",
80
+ help="exit 1 when a finding at or above this severity exists",
81
+ )
59
82
  subparsers.add_parser("version", help="print the version")
60
83
  return parser
61
84
 
@@ -80,6 +103,33 @@ def main(argv: list[str] | None = None) -> int:
80
103
  print(__version__)
81
104
  return 0
82
105
 
106
+ if args.command == "skills":
107
+ skills_root = args.path
108
+ if not skills_root.is_dir():
109
+ print(f"memproof: not a directory: {skills_root}", file=sys.stderr)
110
+ return 2
111
+ skill_findings, scan = scan_skills(
112
+ skills_root, args.registry, security=not args.no_security
113
+ )
114
+ content = (
115
+ render_skills_markdown(scan, skill_findings)
116
+ if args.format == "markdown"
117
+ else render_skills_json(scan, skill_findings)
118
+ )
119
+ if args.output:
120
+ write_report(args.output, content)
121
+ print(f"wrote {args.output}")
122
+ else:
123
+ sys.stdout.write(content)
124
+ if args.fail_on == "none":
125
+ return 0
126
+ threshold = FAIL_RANK[args.fail_on]
127
+ worst = min(
128
+ (FAIL_RANK.get(finding.severity, 99) for finding in skill_findings),
129
+ default=99,
130
+ )
131
+ return 1 if worst <= threshold else 0
132
+
83
133
  root = args.path
84
134
  if not root.is_dir():
85
135
  print(f"memproof: not a directory: {root}", file=sys.stderr)