feat(plane): repo-facts memory task (task 5)

plane/tasks/repo_facts.py computes, from source text only and without a
model or git, the product files of a workspace (tests, vendored trees,
node_modules, dist/build, minified bundles and dot-directories excluded via
the layout facts plus the model_sinks.py filter), the functions each file
declares (Python, PHP, JavaScript/TypeScript, Java, Go, Ruby declaration
patterns extended from sink_candidates.py) and, per candidate function, the
call sites in other product files with path, 1-based line and enclosing
function, capped at 40 and sorted (Requirement 5.1). Output is byte-identical
across runs over the same tree (Requirement 5.2).

Under the task contract the unit is one file: a row goes to units.jsonl as
each file finishes and a restart reuses the rows computed for the same
candidate set (Requirement 2.2); facts.json is assembled from the rows and
summary.json is written last, refusing `done` unless every unit finished.
The entrypoint reads OUSAST_WORKSPACE_DIR, OUSAST_OUTPUT_DIR and optional
OUSAST_INPUT_CANDIDATES only (Requirement 2.1) and exits 0 on done, 2 on
failed with the traceback recorded in summary.json.

tests/test_plane_repo_facts.py: a three-file tree with a tests/ file, a
vendored file, a node_modules bundle and a dot-directory; cross-file callers
with line and enclosing function, same-file and declaration lines excluded,
the 40 cap, byte-identical second run, resume that recomputes only the
missing unit, a crash that leaves `failed` with the unit counts and resumes
to `done`, and the declaration patterns per language.

The two new modules are registered as spec-owned in the module audit (their
importer, the runner, lands in task 3) and the audit manifest is regenerated.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EmM1j46qgKMh3zqD1QMwEo
This commit is contained in:
Marius Ciepluch
2026-09-29 17:55:34 +02:00
co-authored by Claude Fable 5.1
parent 3acd6c8822
commit 2a490eed59
5 changed files with 658 additions and 4 deletions
@@ -1,7 +1,7 @@
{
"modules": 120,
"modules": 122,
"counts": {
"load_bearing": 111,
"load_bearing": 113,
"standalone_capability": 9
},
"orphaned": [],
@@ -401,6 +401,7 @@
"model.specs",
"model.taint",
"plane.budget",
"plane.tasks.repo_facts",
"preprocess",
"push.assistance",
"push.cache",
@@ -528,6 +529,7 @@
"importers": [
"model.partitions",
"model.scan",
"plane.tasks.repo_facts",
"preprocess",
"push.runner"
]
@@ -661,6 +663,18 @@
"reason": "ai-service-plane Req 2.3/2.4: metered chat client with usd and calls ceilings; task integration in tasks 3, 6",
"importers": []
},
{
"module": "plane.tasks",
"classification": "load_bearing",
"reason": "ai-service-plane Req 4.1: the task entrypoint package the runner imports by name; runner integration pending (task 3)",
"importers": []
},
{
"module": "plane.tasks.repo_facts",
"classification": "load_bearing",
"reason": "ai-service-plane Req 5.1/5.2: source-only functions and callers per file; runner integration pending",
"importers": []
},
{
"module": "policy",
"classification": "load_bearing",
@@ -707,6 +721,7 @@
"model.partitions",
"model.scan",
"pairs",
"plane.tasks.repo_facts",
"push.runner",
"rank",
"regress.candidate",
@@ -1337,6 +1352,5 @@
"cli"
]
}
],
"note": "Group 8: runner reaches recomputed versioned eligibility and its frozen scorer."
]
}