wikifier 4.6.0__tar.gz → 4.6.1__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.
- {wikifier-4.6.0/wikifier.egg-info → wikifier-4.6.1}/PKG-INFO +1 -1
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_agent_loop.py +46 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/__init__.py +1 -1
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/cli.py +5 -19
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/health.py +6 -2
- {wikifier-4.6.0 → wikifier-4.6.1/wikifier.egg-info}/PKG-INFO +1 -1
- {wikifier-4.6.0 → wikifier-4.6.1}/CONTRIBUTING.md +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/LICENSE +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/MANIFEST.in +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/README.md +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/diagnostics.html +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/docs/spec.md +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/index.html +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/pyproject.toml +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/setup.cfg +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/skills/run.md +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_barrel_invalidation.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_gap_closure.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_health.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_import_cache.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_multi_lang_parsers.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_parsers.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/tests/test_selftest_wrappers.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/__main__.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/agent_loop.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/contracts.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/daemon.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/diagnostics.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/import_cache.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/index.html +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/library.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/locking.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/mcp/__init__.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/mcp/server.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/__init__.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/_edge.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/bree.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/c_cpp.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/cdia.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/csharp.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/go_lang.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/java.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/javascript.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/python.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/parsers/rust.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/project_root.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/resolution.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/scripts/wikifier.bat +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/scripts/wikifier.ps1 +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/scripts/wikifier.sh +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier/serve.py +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier.egg-info/SOURCES.txt +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier.egg-info/dependency_links.txt +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier.egg-info/entry_points.txt +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier.egg-info/requires.txt +0 -0
- {wikifier-4.6.0 → wikifier-4.6.1}/wikifier.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wikifier
|
|
3
|
-
Version: 4.6.
|
|
3
|
+
Version: 4.6.1
|
|
4
4
|
Summary: Zero-dependency agent-to-agent codebase wiki for LLMs and AI agents. Autonomously maintained via record-change and mark-green for token-efficient lookup of files, dependencies, health, and summaries — across tiny scripts to 50k+ monorepos. Optional MCP server with rich tools for agents.
|
|
5
5
|
Author-email: Aron Amos <aron@example.com>
|
|
6
6
|
Maintainer: Aron Amos
|
|
@@ -78,6 +78,52 @@ class TestContentHonestDirty(TempProjectTestCase):
|
|
|
78
78
|
self.assertIn("Yellow", data3["entries"]["mod.py"]["status"])
|
|
79
79
|
self.assertIn("content", data3["entries"]["mod.py"]["reason"].lower())
|
|
80
80
|
|
|
81
|
+
def test_legacy_green_without_hash_rewrite_yellows(self):
|
|
82
|
+
"""Criterion 2: Green with no source_content_hash + real rewrite must Yellow.
|
|
83
|
+
|
|
84
|
+
Must not seed post-edit hash and stay Green (post-upgrade / legacy path).
|
|
85
|
+
"""
|
|
86
|
+
p = self.write("legacy.py", "print('v1')\n")
|
|
87
|
+
# Legacy Green: upsert only — no source_content_hash baseline
|
|
88
|
+
health_mod.upsert_entry(self.root, "legacy.py", "🟢 Green", "legacy green no hash")
|
|
89
|
+
data = health_mod.load_health(self.root)
|
|
90
|
+
self.assertNotIn("source_content_hash", data["entries"]["legacy.py"] or {})
|
|
91
|
+
from wikifier import import_cache as ic
|
|
92
|
+
cache = {}
|
|
93
|
+
ic.update_file_data(cache, "legacy.py", mtime=1, imports=[], resolved_pairs=[])
|
|
94
|
+
ic.save_cache(self.root, cache)
|
|
95
|
+
# Real content rewrite
|
|
96
|
+
p.write_text("print('v2-rewritten')\n", encoding="utf-8")
|
|
97
|
+
cache = ic.load_cache(self.root)
|
|
98
|
+
cache["legacy.py"]["mtime"] = 1 # force dirty vs disk
|
|
99
|
+
ic.save_cache(self.root, cache)
|
|
100
|
+
r = cli.check_changes(project_root=self.root)
|
|
101
|
+
self.assertTrue(r.get("success"), r)
|
|
102
|
+
self.assertGreaterEqual(int(r.get("changes_detected") or 0), 1)
|
|
103
|
+
data2 = health_mod.load_health(self.root)
|
|
104
|
+
ent = data2["entries"]["legacy.py"]
|
|
105
|
+
self.assertIn("Yellow", ent["status"])
|
|
106
|
+
# Must not have silently stored the post-edit hash as trusted baseline
|
|
107
|
+
self.assertNotEqual(
|
|
108
|
+
ent.get("source_content_hash"),
|
|
109
|
+
compute_source_content_hash(p),
|
|
110
|
+
"must not seed post-edit content hash without mark_green",
|
|
111
|
+
)
|
|
112
|
+
# After mark_green, baseline is set and further touch-only stays green
|
|
113
|
+
cli.mark_green("legacy.py", "re-baselined", project_root=self.root)
|
|
114
|
+
data3 = health_mod.load_health(self.root)
|
|
115
|
+
self.assertIn("source_content_hash", data3["entries"]["legacy.py"])
|
|
116
|
+
baseline = data3["entries"]["legacy.py"]["source_content_hash"]
|
|
117
|
+
cache = ic.load_cache(self.root)
|
|
118
|
+
cache["legacy.py"]["mtime"] = 1
|
|
119
|
+
ic.save_cache(self.root, cache)
|
|
120
|
+
os.utime(p, None)
|
|
121
|
+
r2 = cli.check_changes(project_root=self.root)
|
|
122
|
+
self.assertTrue(r2.get("success"), r2)
|
|
123
|
+
data4 = health_mod.load_health(self.root)
|
|
124
|
+
self.assertIn("Green", data4["entries"]["legacy.py"]["status"])
|
|
125
|
+
self.assertEqual(data4["entries"]["legacy.py"]["source_content_hash"], baseline)
|
|
126
|
+
|
|
81
127
|
|
|
82
128
|
class TestSessionBootstrapAndSuggest(TempProjectTestCase):
|
|
83
129
|
def test_session_bootstrap_shape(self):
|
|
@@ -1208,48 +1208,34 @@ def check_changes(project_root: Optional[Union[str, Path]] = None) -> Dict[str,
|
|
|
1208
1208
|
if stored_hash and live and stored_hash == live:
|
|
1209
1209
|
verdict = {"content_dirty": False, "reason": "content_unchanged", "seed_baseline": False, "hash": live}
|
|
1210
1210
|
elif not stored_hash and live:
|
|
1211
|
-
|
|
1211
|
+
# no baseline → dirty (do not seed post-edit hash)
|
|
1212
|
+
verdict = {"content_dirty": True, "reason": "no_baseline", "seed_baseline": False, "hash": live}
|
|
1212
1213
|
elif live and stored_hash and stored_hash != live:
|
|
1213
1214
|
verdict = {"content_dirty": True, "reason": "content_changed", "seed_baseline": False, "hash": live}
|
|
1214
1215
|
except Exception:
|
|
1215
1216
|
pass
|
|
1216
1217
|
|
|
1217
|
-
if verdict.get("seed_baseline") and verdict.get("hash") and isinstance(ent, dict):
|
|
1218
|
-
ent["source_content_hash"] = verdict["hash"]
|
|
1219
|
-
entries[rel] = ent
|
|
1220
|
-
health_dirty = True
|
|
1221
|
-
seeded_baselines += 1
|
|
1222
|
-
# Do not Yellow solely for first baseline seed on mtime thrash
|
|
1223
|
-
continue
|
|
1224
1218
|
if not verdict.get("content_dirty") and verdict.get("reason") == "content_unchanged":
|
|
1225
1219
|
skipped_mtime_only += 1
|
|
1226
1220
|
continue
|
|
1227
|
-
# Content changed
|
|
1221
|
+
# Content changed, no baseline, or unclassifiable: Yellow.
|
|
1222
|
+
# Never write source_content_hash here — only mark_green sets the
|
|
1223
|
+
# trusted baseline (avoids seeding post-edit bytes and staying Green).
|
|
1228
1224
|
reason = (
|
|
1229
1225
|
"content changed since last trusted baseline (check_changes content-honest)"
|
|
1230
1226
|
if verdict.get("reason") == "content_changed"
|
|
1231
1227
|
else "content change or no baseline (check_changes content-honest auto-detect)"
|
|
1232
1228
|
)
|
|
1233
1229
|
_upsert(root, rel, "🟡 Yellow", reason)
|
|
1234
|
-
# refresh local entries view after upsert
|
|
1235
1230
|
try:
|
|
1236
1231
|
health_data = _health_mod.load_health(root)
|
|
1237
1232
|
entries = health_data.setdefault("entries", {})
|
|
1238
|
-
if verdict.get("hash") and rel in entries and isinstance(entries[rel], dict):
|
|
1239
|
-
# keep prior baseline until mark-green; do not update hash on yellow
|
|
1240
|
-
pass
|
|
1241
1233
|
health_dirty = False # upsert already saved
|
|
1242
1234
|
except Exception:
|
|
1243
1235
|
pass
|
|
1244
1236
|
_add_to_pending(root, rel, "Content change auto-detected — review and run mark-green after wiki update")
|
|
1245
1237
|
_ensure_journal_entry(root, "auto-detected", rel, reason)
|
|
1246
1238
|
changed_count += 1
|
|
1247
|
-
if health_dirty and health_data is not None:
|
|
1248
|
-
try:
|
|
1249
|
-
if hasattr(_health_mod, "save_health"):
|
|
1250
|
-
_health_mod.save_health(root, health_data)
|
|
1251
|
-
except Exception:
|
|
1252
|
-
pass
|
|
1253
1239
|
# Keep pending queue aligned with lean monitored_paths (no flood outside scope)
|
|
1254
1240
|
if hasattr(_health_mod, "prune_pending_to_monitored"):
|
|
1255
1241
|
try:
|
|
@@ -272,12 +272,16 @@ def classify_content_dirty(
|
|
|
272
272
|
"seed_baseline": False,
|
|
273
273
|
}
|
|
274
274
|
if not stored_hash:
|
|
275
|
+
# No trusted baseline (legacy Green / never mark-green): when this path is
|
|
276
|
+
# under check_changes dirty observation, treat as needing attention so a
|
|
277
|
+
# post-edit rewrite cannot silently re-seed the *new* bytes and stay Green.
|
|
278
|
+
# Callers that only want to migrate baselines should use an explicit seed helper.
|
|
275
279
|
return {
|
|
276
|
-
"content_dirty":
|
|
280
|
+
"content_dirty": True,
|
|
277
281
|
"missing": False,
|
|
278
282
|
"hash": live,
|
|
279
283
|
"reason": "no_baseline",
|
|
280
|
-
"seed_baseline":
|
|
284
|
+
"seed_baseline": False,
|
|
281
285
|
}
|
|
282
286
|
if stored_hash == live:
|
|
283
287
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wikifier
|
|
3
|
-
Version: 4.6.
|
|
3
|
+
Version: 4.6.1
|
|
4
4
|
Summary: Zero-dependency agent-to-agent codebase wiki for LLMs and AI agents. Autonomously maintained via record-change and mark-green for token-efficient lookup of files, dependencies, health, and summaries — across tiny scripts to 50k+ monorepos. Optional MCP server with rich tools for agents.
|
|
5
5
|
Author-email: Aron Amos <aron@example.com>
|
|
6
6
|
Maintainer: Aron Amos
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|