Commit Graph
959 Commits
Author SHA1 Message Date
Marius CiepluchandClaude Opus 5 eab89bf203 feat(authorization-obligations): reports and ranking name the obligation
Task 3.2. Each obligation finding prints its operation, the missing discharger
with the provenance that failed, the evidence behind the label, the known fix
learned from the corpus and the hunter's intent verdict; the Obligations section
lists the sibling sets evaluated and the declared policy version. SARIF carries
the same as properties.

Obligation findings rank by resource sensitivity times label weight, declared
above consistency above function-local, and stay strictly below every proven
finding. Proof rungs live on verdicts rather than on static findings, so the
cap takes the proven ids from the run's triggerable verdicts.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-06 07:24:13 +02:00
Marius CiepluchandClaude Opus 5 e13a397942 feat(authorization-obligations): run the checker in MAP with config and manifest counters
Task 3.1. The obligations proposer runs after variant search in standard and
deep scans, reads the declared policy from the target, and never writes it.
Its findings are appended after every other finding and never enter the sandbox
candidate set. The manifest block carries the sibling sets, the under-populated
count, the operations examined, the findings by label, the policy version, the
stage degradations, and the sibling sets themselves.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-06 07:24:13 +02:00
Marius CiepluchandClaude Opus 5 2249de8d2e feat(authorization-obligations): the obligation checker, path-aware and function-local
Task 2.5. An obligated operation that is reached and has no dominating
discharger is reported at suspicion, labeled by why the obligation exists:
a declared policy clause, the practice of sibling handlers, or, in the degraded
no-path mode, the operation fact alone. With path records and neither a clause
nor a sibling norm nothing justifies the obligation and nothing is reported.

A declared public route waives the path guard wherever it is required, not only
where siblings practice it (Req 4.4). A malformed store row is recorded as a
degradation naming the record instead of being skipped silently.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-06 07:24:13 +02:00
Marius CiepluchandClaude Opus 5 8e26dfd1e2 feat(authorization-obligations): group sibling handlers and find consistency anomalies
Task 2.2. Handlers on the same resource under the same module are siblings;
when at least min_siblings of them discharge an obligation and one does not,
that one is the anomaly and the discharging siblings are its evidence (Req 3.2).
A set with fewer members than the minimum is under-populated and never reported
(Req 3.3). A public route among authenticated siblings is a missing path guard
with the mapper's access classification as evidence (Req 3.4).

The sibling key is the module path without its suffix, so two same-named files
in different directories are never merged. Witness validity (an identity
constraint counts only when it binds the authenticated context) is one helper
shared by operations, siblings and the checker.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-06 07:24:13 +02:00
Marius CiepluchandClaude Fable 5.1 fe5f233c00 feat(authorization-obligations): Dominance protocol with an order-based default
Task 2.4 (Req 5.1, 5.2). Decorator and router witnesses dominate the
handler; a constraint or a non-permissive value dominates the operation
it sits on; a guard call before the operation dominates by contract;
other statement witnesses need an early exit between them and the
operation; along a path record an earlier hop dominates. Guard dominance
replaces the implementation behind the same protocol later.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 19:38:04 +02:00
Marius CiepluchandClaude Fable 5.1 aaee724ebd feat(authorization-obligations): declared policy with a closed schema
Task 2.3 (Req 4.1, 4.2). load_declared_policy: closed top-level,
resource and route fields; access public|authenticated|role; identity
source restricted to the facts' authenticated-context sources; comment-
stripped version hash; trailing-* route globs; unknown fields and values
rejected by name; the tool never writes the file.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 19:38:04 +02:00
Marius CiepluchandClaude Fable 5.1 a8b9dae6b3 feat(authorization-obligations): operations and discharge witnesses in a parsed file
Task 2.1 (Req 3.1, 5.4). find_operations, find_discharges (decorators,
guard and check calls, identity constraints with their provenance,
non-permissive settings) and covers; chained call sites deduped; the
resource token is the receiver head, the fact's resource argument, or a
SQL table name.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 19:38:04 +02:00
Marius CiepluchandClaude Fable 5.1 8324b243a0 feat(authorization-obligations): export obligation shapes through the existing store
Task 1.3 (Req 2.1, 2.2, 2.4).

- seed.pair_lessons derives obligation shapes for absence-mechanism rows
  and falls back to the sink shape when no obligation is learned, so the
  flow store is unchanged; skip reasons name the accepted dischargers.
- append_from_pair accepts both shape families (guard carries the
  discharger kind); search_tree ignores obligation rows;
  obligation_mechanisms selects them.
- Measured on vibe-py: the two vampi pairs seed protected_read /
  identity_constraint / authenticated_context.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 19:38:04 +02:00
Marius CiepluchandClaude Fable 5.1 ec3a1438e8 feat(authorization-obligations): obligation shapes derived from trusted pairs
Task 1.2 (Req 2.1, 2.3, 2.5).

- semantic/obligations/shapes.py: ObligationShape (family obligation,
  text-free key), derive_obligation and explain_skip. The lesson is any
  discharged operation of the target's walker-visible kind, fixed side
  first and then the vulnerable function's own safe branch, since
  Real-Vuln twins are flag-toggled identical functions or unrelated trap
  functions; keyword constraints are read from the call's source line
  (positional-only IR call sites); an identity constraint bound from the
  request or a constant discharges nothing.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 19:38:04 +02:00
Marius CiepluchandClaude Fable 5.1 f44dd2c512 feat(authorization-obligations): obligated operations and dischargers as closed facts
Task 1.1 (Req 1.1-1.5).

- semantic/obligations/facts.py: closed OPERATION_KINDS, DISCHARGER_KINDS
  and PROVENANCE_KINDS; OperationFact and DischargerFact (calls,
  decorators, identity sources, constraint params, request sources,
  permissive values); load_obligation_facts rejects unknown kinds and
  fields by name; per-language scoping.
- ruleset/obligations/{python,javascript,typescript}.toml beside (never
  inside) the flow facts directory. Protected reads and writes are
  discharged by an identity constraint or an ownership check; a path
  guard discharges privileged actions only.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 19:38:04 +02:00
Marius CiepluchandClaude Fable 5.1 c53eddd69d docs(authorization-obligations): cover criterion 4.5 in task 5.1; tasks approved, ready for implementation
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 16:46:28 +02:00
Marius CiepluchandClaude Fable 5.1 88cda276aa docs(authorization-obligations): approve design; generate tasks
Six task groups in the design's migration order: closed facts and
obligation shapes; operations, siblings, declared policy, dominance
protocol and the checker; MAP wiring, reports, ranking and hunter intent;
corpus harvest mode, labels, leave-one-out and relabeling; the
obligations lever; validation. All 44 acceptance criteria covered; no
task waits on the unimplemented upstream specs (path-aware evaluation
enters through the Dominance protocol and an optional PathRecord input).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 16:46:00 +02:00
Marius CiepluchandClaude Fable 5.1 27626d3a07 docs(authorization-obligations): approve requirements; design and research
Requirements approved by the maintainer in session. Design: closed
obligation facts (operations and dischargers), obligation shapes as a
second family in the mechanism store, sibling-set consistency and an
optional declared policy as the policy sources, a Dominance protocol
with an order-based default so the checker works function-local before
reachability and guard dominance land, findings at suspicion carrying
consistency_violation / declared_policy_violation / function_local as
data, reports, manifest and ranking fields, handler_context harvest
mode, leave-one-out per obligation kind, and an obligations lever with
pending policy clauses under the existing gate. All 44 acceptance
criteria traced.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 16:42:58 +02:00
Marius CiepluchandClaude Fable 5.1 a87755830a docs(specs): kick off authorization-obligations (brief + requirements, unapproved)
Absence bugs as obligations rather than flows: obligated operations and
discharger kinds as closed facts, obligation shapes learned from trusted
pairs, the application's policy recovered from sibling-handler
consistency and an optional declared policy file, path-aware evaluation
with a function-local degraded mode, honest rungs below proof, an
`obligations` improve lever under the holdout gate. Depends on
reachability-flow-model and guard-dominance-regime; the roadmap marks
reachability as the critical path for two consumers.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 16:31:49 +02:00
Marius CiepluchandClaude Fable 5.1 381ea7b92d docs(corpus-seeded-mechanisms): close the spec after six review rounds
- tasks.md: all tasks checked; rounds 1-6 recorded with RED evidence,
  measured leave-one-out and admission numbers, and the recorded design
  deviations.
- spec.json: completed 2026-09-05.
- roadmap: corpus-seeded-mechanisms marked completed; the loop is closed
  end to end (export -> improve admits under the holdout clause -> scan
  searches -> reports name the mechanism).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 15:37:32 +02:00
Marius CiepluchandClaude Fable 5.1 e5d191ffec chore(cli): wrap the mechanism-candidates help text
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 15:37:32 +02:00
Marius CiepluchandClaude Fable 5.1 b3b47ad757 feat(corpus-seeded-mechanisms): the mechanisms lever runs from ousast improve
Review rounds 3-5 remediations (Req 5, 7).

- ousast improve resolves candidates from the target's calibration dir,
  then the working directory's (where `mechanisms export` writes), and
  admits into <target>/.openultrasast/calibration/mechanisms.jsonl,
  where a scan of that target reads; --mechanism-candidates,
  --mechanism-store, --no-mechanisms; --dry-run redirects the store to
  scratch; accepted rounds print admit/retract <id>.
- run_improvement threads the store paths; RoundOutcome carries the
  mechanism edits; reverted mechanism keys are blocked outright; a
  no-gain admission is rejected as mechanism_no_gain; a retraction may
  name an admitted record that left the candidate set.
- leave-one-out forwards variant-search degradations and pins the
  containment and label rules; mechanisms export defaults to the
  candidates file so it never re-admits a tombstone.
- design §Lever rewritten to the implemented gate; README and docs show
  export -> improve -> scan.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 15:35:08 +02:00
Marius CiepluchandClaude Fable 5.1 624024e72a feat(corpus-seeded-mechanisms): reports name the mechanism, its known fix guard and pair provenance
Task 5.1 (Req 6.1, 6.3).

- reports.py: the markdown and SARIF writers take the mechanisms a run
  cites; a finding cites one through its mechanism:<id> tag (variant) or
  its merged overlay record's mechanism_id; markdown shows Mechanism,
  Known fix guard and Learned from pairs per finding plus a Mechanisms
  section, SARIF properties carry mechanism_id/summary/guard/pairs;
  variant findings keep suspicion, merged inventory findings keep their
  own evidence level; reports without mechanisms are unchanged.
- cli: _search_variants returns the cited mechanisms from the store and
  the scan passes them to both writers.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 15:35:08 +02:00
Marius CiepluchandClaude Fable 5.1 23aae79768 feat(corpus-seeded-mechanisms): improve loop admits recovering mechanisms and retracts leakers
Task 4.2 (Req 5.3, 5.4, 5.5).

- propose_mechanism_edits: retract admitted records that leak on a
  holdout fixed side; admit a candidate only when a trial store holding
  it alone recovers a currently missed holdout pair without leaking.
- run_round(mechanism_candidates=, mechanism_store=): validates, applies
  after the rule gate passed, re-scores the holdout pairs per profile with
  variant search (evaluate_mechanism_profiles), and rejects with a
  byte-for-byte revert on mechanism_leak, profile_regression or
  mechanism_no_gain; the journal records each mechanism edit with its
  pair provenance and the metrics before and after.
- The rule gate and its per-profile clause are unchanged.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:55:00 +02:00
Marius CiepluchandClaude Fable 5.1 73e856a06b feat(corpus-seeded-mechanisms): the mechanisms lever admits or retracts exporter records
Task 4.1 (Req 5.1, 5.2, 5.5).

- validator: MechanismEdit (admit | retract by record id) under the
  `mechanisms` lever; validate_mechanism accepts only records from the
  exporter candidate set with origin corpus, a closed guard and source
  kinds, and identifier-only shape text; free-form shapes are rejected.
- apply_mechanism_edits appends the record (admit) or a retracted
  tombstone (retract) so the log stays append-only; StoreSnapshot.restore
  reverts byte for byte. MechanismStore.load folds tombstones away.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:55:00 +02:00
Marius CiepluchandClaude Fable 5.1 f11cf183de docs(corpus-seeded-mechanisms): leave-one-out table in the roadmap
Task 3.2 (Req 4.4, 7.2): per-slice leave-one-out next to the pair
baselines; reported, never a gate.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:55:00 +02:00
Marius CiepluchandClaude Fable 5.1 64ac46c24c feat(corpus-seeded-mechanisms): leave-one-out is the corpus's own detection rate
Task 3.1 (Req 4.1-4.4).

- semantic/loo.py: every scorable pair is held out once; a temporary
  store is seeded from the other seeded/reviewed pairs (advisory and
  title pairs are scored as targets, never teach; known_limit skipped);
  both excerpts are searched for variants and scored with the pair rules
  (detected inside the labeled function naming the labeled mechanism or
  sink; silent when the fixed side yields no hit); found_by and leaked_by
  name the records and the pairs that taught them; metrics per slice,
  profile and mechanism; score_pair_with_store is shared with the lever.
- cli: `pairs --slice S --loo [--loo-out P]` writes loo.json; never a gate.
- First measurement: vibe-py 35 pairs, 11 detected, 21 silent, Youden
  -0.086, 16 teaching pairs.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:55:00 +02:00
Marius CiepluchandClaude Fable 5.1 8f444051f2 refactor(corpus-seeded-mechanisms): apply review round 2 suggestions
- variant_search.search_tree skips a malformed store row with a
  variants_store_row_invalid degradation instead of aborting the scan;
  a hit on a demoted or flowless overlay record is never merged (test).
- seed.pair_lessons is the one shape derivation shared by the exporter
  and leave-one-out; labels pass line and sink together; pairs without a
  labeled function are reported as no_labeled_function.
- config parses [variants].max_mechanisms with the shared int helper.
- regress.candidate.hotspot_from_finding is the one zero-score hotspot
  helper for forced inventory and variant findings.
- design synced (SearchResult, hits_to_findings summaries, candidate.py).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:55:00 +02:00
Marius CiepluchandClaude Fable 5.1 a767ba80b4 feat(corpus-seeded-mechanisms): variant findings in MAP, sandbox-eligible, counted in the manifest
Task 2.3 (Req 3.4, 3.5, 3.6, 6.2).

- [variants] enabled / max_mechanisms config; MAP runs variant search
  after the overlay in standard and deep scans only, appends the variant
  findings, rewrites overlay.json with merged ids, and the manifest
  records mechanisms_searched, files_searched, findings and
  merged_into_overlay.
- REGRESS: variant findings join the candidate list after the promotions
  as zero-score hotspots, under the existing safety check and cap.
- Spec notes for group 2 and the design synced (variant_search.py,
  seed.py, derive_shape signature).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:40:15 +02:00
Marius CiepluchandClaude Fable 5.1 c1621777f9 feat(corpus-seeded-mechanisms): structural variant search merged with overlay flows
Task 2.2 (Req 3.1-3.3, 3.6).

- variants.match_shapes: call sites whose trailing callee name and arity
  match a shape and whose source positions all carry a source of any
  kind; constants and arity mismatches never match.
- semantic/variant_search.py: search_tree over a tree's parsed files with
  the store's corpus shapes (bounded by max_mechanisms, language
  degradations recorded); hits_to_findings merges a hit into an overlay
  promote/coverage record at the same call site (mechanism_id, no
  duplicate) and otherwise emits variant:<id>:<path>:<line> at suspicion
  with the pair provenance in the rationale.
- OverlayRecord.mechanism_id (additive).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:40:15 +02:00
Marius CiepluchandClaude Fable 5.1 a7b3b36025 feat(corpus-seeded-mechanisms): export trusted pairs as mechanism records
Task 2.1 (Req 1.1, 1.2, 1.5, 2.5).

- semantic/seed.py: export_mechanisms seeds only seeded/reviewed,
  non-known-limit, parsing pairs with cached excerpts; every skip carries
  a reason (tier, known_limit, parse_failed, language unsupported with a
  degradation, pointer not cached, no labeled sink call site); runs
  offline over the vendored catalog.
- variants.derive_shape: labels that name only a function and a mechanism
  resolve to the fact-sink call inside that function (CWE match and a
  non-constant argument first); line and sink intersect when both exist;
  container reads are subscript or .get( only.
- append_from_pair keeps the strongest review tier and accumulates
  provenance tags when a shape is re-seeded.
- CLI: `ousast mechanisms export --slice S [--store P] [--json]`.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:40:15 +02:00
Marius CiepluchandClaude Fable 5.1 2a7d689971 feat(corpus-seeded-mechanisms): corpus writer and additive mechanism fields
Task 1.2 (Req 1.3, 1.4).

- Mechanism gains origin, review_tier, pairs, shape, guard with defaults;
  rows written before this spec load unchanged.
- MechanismStore.load folds the append-only log by id (latest row wins)
  so a re-seeded shape carries every pair that taught it.
- append_from_pair writes origin=corpus rows with a deterministic id
  derived from the shape key; corpus_mechanisms selects searchable rows.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:27:33 +02:00
Marius CiepluchandClaude Fable 5.1 4d56b3c76e feat(corpus-seeded-mechanisms): structural shapes derived from labeled pairs
Task 1.1 (Req 2.1-2.4). Spec approved by the maintainer in session.

- semantic/variants.py: Shape (language, sink trailing name, arity,
  source positions and kinds, closed guard kind, mechanism id) with a
  stable text-free key; derive_shape finds the labeled sink call site in
  the vulnerable FileIR, traces argument identifiers through binds to a
  fact source, a parameter or a container read, and classifies the guard
  the fixed side added from the labeled function's added statements
  against a closed set (none when unknown). No path, line or literal
  enters a shape; a constant-only call teaches nothing.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 14:27:33 +02:00
Marius CiepluchandClaude Fable 5.1 d36a68724f docs(pair-corpus-honesty): record the round 13 feature approval
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:52:23 +02:00
Marius CiepluchandClaude Fable 5.1 8c6598b2e8 docs(pair-corpus-honesty): record round 12 and the key-literal history rewrite
- tasks.md: round-12 verdict and the decision to assemble the redaction
  test's example key at runtime and rewrite the unpushed series so no
  commit carries a contiguous key literal; two dated notes marked as
  superseded by tasks 8.1 and 8.4.
- roadmap: the folded inventory-vs-overlay Youden item is checked.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:47:14 +02:00
Marius CiepluchandClaude Fable 5.1 27f9ec6a92 docs(pair-corpus-honesty): close the spec; escalations resolved, roadmap carries the measured state
- tasks.md: all tasks checked; the two escalations are closed (5.1 by the
  Req 10 pointer rows, 5.3 by the Req 9 review tiers); round 11 recorded
  with the carry-forwards for corpus-seeded-mechanisms and
  overlay-ir-completeness.
- roadmap: measured state after tiers and pointer slices (vibe-py 115,
  agent-vfc 59, gates byte-identical to pre-spec); pair-corpus-honesty
  marked completed.
- spec.json: completed 2026-09-05 after eleven review rounds.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 3c36f13e03 feat(pair-corpus-honesty): LLM-generated Real-Vuln repos and unlicensed agent fixes as pointer pairs
Task 8.4 (Req 10.6, 5.1).

- harvest.merge_recipes appends recipes by name and never rewrites
  existing rows.
- vibe-py/build_recipes.py --pointers: the 40 LLM-generated repositories
  without a license become vendored = false rows (80 pairs, agent,
  seeded) appended to recipes.toml; unlicensed human repos stay skipped.
- agent-vfc/build_recipes.py --from ... --pointers [--cache]: unlicensed
  agent-authored fixes become title-tier pointer rows whose function
  label is derived from the cached excerpt (30 added from a fresh
  662-candidate search); TOML booleans rendered correctly.
- catalogs regenerated: vibe-py 115 rows (35 vendored + 80 pointer),
  agent-vfc 59 (29 + 30); no excerpt is vendored for any pointer row.
- `pairs --slice vibe-py --pointers` scores both provenances (human 35,
  agent 80); the default run skips 80 pairs with pointer_pair_skipped;
  suite and gates unchanged. README/docs name the nightly command.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 4102404442 feat(pair-corpus-honesty): score non-vendored pointer pairs through a local cache
Task 8.3 (Req 10.1-10.5).

- pairs.py: catalog rows with vendored = false carry their harvest recipe
  and no excerpts; evaluate_catalog harvests them into
  OPENULTRASAST_PAIR_CACHE (default ~/.cache/openultrasast/pairs) only
  when `pairs --pointers` or OPENULTRASAST_PAIRS_NETWORK=1 allows the
  network, otherwise records pointer_pair_skipped (a failed fetch is
  pointer_pair_fetch_failed with detail); a warm cache never scores
  without the switch. select_vendored for tests and gates.
- harvest.py: materialize_pointer harvests into the cache without the
  license requirement (nothing is redistributed); redaction applies.
- catalog_gen.py: emits pointer rows with recipe fields; training
  manifests skip them.
- pair_gate and improve/evolve.evaluate_profiles score vendored pairs
  only; cli `pairs --pointers`; .gitignore covers the cache path.
- tests: loader, skip/degradation, cache hit, fetch failure, warm cache
  with network off, profile gate exclusion, harvest and generator paths;
  conftest keeps every test offline whatever the shell exports.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 7d238f2400 docs(specs): kick off corpus-seeded-mechanisms and reachability-flow-model (unapproved)
Two engine specs drafted after the pair-corpus baseline, awaiting owner
approval before implementation:

- corpus-seeded-mechanisms: structural shapes derived from trusted pairs,
  export, variant search merged with overlay flows, leave-one-out
  measurement, and a closed `mechanisms` lever for the improve loop.
- reachability-flow-model: call graph over FunctionIR, reachability from
  entry points to sinks, hunter client preferring HarnessX (task 4.1b).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 3eba6e10a0 docs(pair-corpus-honesty): spec, review record, roadmap; close real-world-vfc-slice as superseded
Task 7.2 and the spec itself (brief, requirements incl. Req 9/10
amendment, research, design, tasks with eight review rounds recorded).

- real-world-vfc-slice: spec.json closed, superseded_by
  pair-corpus-honesty; brief carries the closure note.
- roadmap: Direction section, per-slice baselines (sast 4/11, vibe-py
  13/35, vfc-js 5/17, vfc 0/176, agent-vfc 0/29 title tier), spec order
  pair-corpus-honesty -> corpus-seeded-mechanisms -> reachability-flow-model
  -> overlay-ir-completeness -> guard-dominance-regime.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 25f1512eb9 feat(pair-corpus-honesty): profile gate scores only seeded and reviewed pairs
Task 8.2 (Req 9.3).

- improve/evolve.py: evaluate_profiles filters holdout pairs to
  GATING_TIERS before computing per-profile metrics, so advisory and
  title pairs are scored by `pairs` but never gate a round; a regression
  on reviewed pairs still rejects with profile_regression:<profile>.
- tests: a regression confined to title pairs is accepted; the same
  regression on reviewed pairs is rejected and the title pairs are
  excluded from the gated profile rather than outvoted.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 b1c5f36076 feat(pair-corpus-honesty): review tiers on every pair, agent-vfc loads at tier title
Tasks 8.1, 7.1 (tests) and the re-scoped 5.3.

- pairs.py: review_tier in {seeded, advisory, title, reviewed} with
  per-slice defaults (local reviewed, vibe-py seeded, sast/vfc/vfc-js/
  github advisory, agent-vfc title); reviewer = "pending" means title, a
  named reviewer means reviewed, reviewed without a reviewer is rejected;
  per_tier metrics in the payload; select_tier and GATING_TIERS for the
  improve loop.
- catalog_gen.py: stamps review_tier (and reviewer) on every generated
  row and training manifest row; title rows enter catalog.toml; the
  catalog-candidates.toml queue is retired; precedence matches the loader.
- agent-vfc: 29 title-tier rows load and score (0/29, Youden 0.0, the
  honest unreviewed baseline); local rows name their reviewer.
- Tests: tier defaults, loader rejections, per_tier payload, the Req 8.1
  catalog-on-disk / stage-1 exclusion proof and per-slice CLI checks.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 9e7aef6a6b feat(pair-corpus-honesty): reject improve rounds that regress any provenance profile on holdout
Task 6.3.

- improve/evolve.py: evaluate_profiles and profile_regressions score the
  holdout pair split per provenance profile every round; a drop in pair
  pass rate or Youden beyond --profile-tolerance rejects the round with
  reason profile_regression:<profile>; profiles under
  --min-holdout-pairs are reported, not gated; journal records both.
- cli improve: --pair-catalog, --no-pair-gate, --profile-tolerance,
  --min-holdout-pairs; a missing catalog fails loud instead of skipping
  the gate.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 25fa7aa7e1 feat(pair-corpus-honesty): deterministic provenance fingerprint at scan time
Task 6.1.

- provenance.py: classify a checkout as human / agent / mixed / unknown
  from deterministic signals only (.claude/, AGENTS.md, Lovable meta,
  agent git trailers on a bounded commit sample); no model involved.
- cli scan runs a `provenance` stage; the manifest records the result.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 c0b9e41000 feat(pair-corpus-honesty): function-scoped honest scorer with mechanisms and loss counters
Tasks 1.2, 2.1-2.5 and 6.2 (pair-side filters).

- pairs.py: coverage with a source counts as detection and as leak;
  function-scoped matching by line-range containment from the vulnerable
  side's parse (unresolvable labels are counted loss, never silent
  misses); exact or alias sink matching; weak CWE-only labels never match;
  side-by-side inventory/overlay/hunter scorers; per_profile,
  per_mechanism, achievable, known_limit and loss payload; loader rejects
  unknown mechanism/provenance/split and reserved or missing function
  labels on harvested slices; candidate rulesets thread through for the
  improve loop.
- overlay.py: OverlayRecord.function (additive) filled from the shared
  naming helper in one parse; benchmark.py: ExpectedFinding.mechanism.
- cli pairs: --slice over every slice, --profile, --split, --hunter,
  --hunter-model.
- catalogs migrated to the new schema (provenance, split, function,
  mechanism, known_limit for owasp-java-hash); baseline recorded in the
  spec notes.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:43 +02:00
Marius CiepluchandClaude Fable 5.1 8ab4207618 feat(pair-corpus-honesty): add vibe-py, vfc-js and agent-vfc slices with mechanism vocabulary
Tasks 1.1, 5.1, 5.2, 5.4 and the data half of 5.3.

- mechanisms.toml: closed vocabulary v1 (20 ids) every expected row cites.
- vibe-py: 35 Real-Vuln-Benchmark pairs (Apache-2.0), human provenance only
  because the LLM-generated repositories carry no license (escalated).
- vfc-js: 17 Node fix-commit pairs harvested upstream (MIT/Apache-2.0),
  SecBench.js itself is not vendored (no license); sinks derived on 13/17.
- agent-vfc: 29 agent-trailer fixes as catalog-candidates.toml plus
  REVIEW.md; the loaded catalog stays empty until a human reviews them.
- datasets.toml and README document every slice and its review status.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:42 +02:00
Marius CiepluchandClaude Fable 5.1 c3e841003c fix(pair-corpus-honesty): re-harvest curl/OpenSSL excerpts, restore Juliet fixtures
Tasks 3.3 and 4.1.

- vfc curl and openssl-cve-2021-3449 excerpts re-harvested through the
  shared library: whole functions with upstream_start headers, the
  vendored key redacted code-safely, no truncated bodies.
- vfc/recipes.toml carries mode, fix_path and function anchors;
  training/manifest.jsonl regenerated.
- Juliet CWE-121 strcpy pair gets its buffer declarations back so the
  vulnerable side is a real overflow again.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:42 +02:00
Marius CiepluchandClaude Fable 5.1 071dea4712 feat(pair-corpus-honesty): shared function naming, harvest library, catalog generator
Tasks 3.1, 3.2 (harvest library) and the Scorer-owned naming helper.

- semantic/functions.py: one source of function names for scorer, overlay
  and catalog generator (declarator wins over parser name; JS/TS bare-param
  arrows and undeclared methods are <anon>; C++ Class::method resolves to
  its unqualified tail; Perl sub; statements never name).
- benchmarks/pairs/harvest.py: shared library with name / line_range /
  hunk / enclosing modes, comment-blind masking (triple-quote aware),
  upstream_start headers, code-safe quoted-only redaction.
- benchmarks/pairs/catalog_gen.py: derive function labels and sinks from
  the declarator at the mapped sink location, CWE-family sink tokens,
  --prune with refusal when nothing derived, fails loud without the
  package; vfc/harvest.py and vfc/generate_catalog.py become shims.
- tests/test_pair_harvest.py replaces test_vfc_harvest.py.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-05 10:45:42 +02:00
Marius Ciepluch 0116f9bea6 feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows)
into benchmarks/pairs/vfc with provenance and a JSONL training manifest.
Score the slice as an honesty dashboard (ousast pairs --slice vfc);
keep the pair gate on the local fixtures only.
2026-09-04 16:45:38 +02:00
Marius Ciepluch e9f185da59 feat(tree-sitter-overlay-extra): parse JS/C/Java overlay via optional extra
Add openultrasast[semantic] with official grammar wheels and one CST walker
into FileIR. quick stays extra-free. Host CLI is not overlay-ready. Default CI
stays extra-free; a semantic job runs pytest -m semantic.
2026-09-04 15:07:35 +02:00
Marius Ciepluch 7d3b0eadbe feat: load OpenRouter settings from a local .env
Stdlib parser only; pytest skips it so tests cannot pick up a developer key.
The embedding model is openai/text-embedding-3-small via OpenRouter /embeddings.
2026-09-04 14:06:18 +02:00
Marius Ciepluch 1ae41eea19 feat(propose-adjudicate-prove): overlay adjudicates inventory before prove
Regex inventory stays the proposer. MAP attaches promote/demote/unadjudicated/coverage
from intra-file taint (tree-sitter when a grammar parses, Python ast as last resort).
Deep sandboxes promotions only, ordered by the existing heuristic ranker plus optional
OpenRouter mechanism recall. The SAST pair slice scores overlay outcomes; the stage-1
detection gate and local pair gate stay inventory-only.
2026-09-04 13:57:33 +02:00
Marius Ciepluch 32aa92191a chore(release): 1.1.0
Three-stage scan: static inventory, complexity map with test-gap hints,
and Docker-isolated regression with --fail-on worth-fixing. Split-sink
and mutation corpora gate stage 2 so regex hit-count ranking cannot claim
success.
v1.1.0
2026-09-04 12:00:15 +02:00
Marius Ciepluch ac3da41c95 feat(three-stage-scan): prove split-sink triggerable in sandbox 2026-09-04 11:54:01 +02:00
Marius Ciepluch 9af356797f feat(three-stage-scan): gate stage-2 maps against split-sink ranking 2026-09-04 11:53:06 +02:00