FCS Integration & Status Provenance Design
Problem
The SQL coupling infrastructure (types, DB, coupling engine, extension interface) is in place, but two key automation pieces are missing:
-
The Sql extension requires manually-provided
SqlFactlists — it can't automatically discover[<ReadsFrom>]/[<WritesTo>]attributes in source code. -
The SqlHydra extension has DSL classification and table parsing but doesn't actually
analyze the dependency graph to produce
SqlFactlists from SqlHydra query patterns. -
The
statuscommand doesn't show provenance — users can't see which edge sources (core, sql, falco) contributed to test selection.
Design Principle
Extensions never touch FCS. Core provides all the raw data (symbols, dependencies, attributes), extensions post-process it. FCS stays a core-only concern.
A: Core — Generic Attribute Extraction
New table
|
New SymbolStore query
GetAttributesForSymbol: string -> (string * string) list
Returns (attributeName, argsJson) pairs for a given symbol full name.
Core AstAnalyzer change
During extractResults, for every FSharpMemberOrFunctionOrValue symbol, extract all
attributes and their constructor arguments. Store as
(symbolFullName, attributeName, argsJson) triples. argsJson is a JSON array of
constructor arg values.
Core already iterates all symbols and reads attributes for test detection. This generalizes that to capture all attribute data.
SchemaVersion bumps to 3.
B: Sql Extension — Automatic Attribute-Based Fact Extraction
With attribute data in the DB, SqlExtension.AnalyzeEdges discovers facts automatically:
- Receives
SymbolStore - Queries all symbols with
ReadsFromAttributeorWritesToAttributeattributes - Parses
argsJsonto extract table/column args - Builds
SqlFactlist - Feeds into
SqlCoupling.buildEdges
SqlExtension() takes no constructor arguments. Facts are discovered, not provided.
C: SqlHydra Extension — Graph-Based Fact Extraction
SqlHydra post-processes the existing dependency graph. For each function symbol, checks its outgoing edges:
-
Does it have a
Callsedge to a SqlHydra DSL function (selectTask,insertTask,updateTask,deleteTask)? -
Does it have a
UsesTypeedge to a SqlHydra-generated table type (matchingGenerated.schema.tablepattern)?
If both: create a SqlFact with the function as the symbol, the table from the type
reference, and the access kind from the DSL function name.
Example: If the graph has:
- BriefQueries.getActiveBriefs → Calls → selectTask
- BriefQueries.getActiveBriefs → UsesType → Generated.public.briefs
Produces: { Symbol = "BriefQueries.getActiveBriefs"; Table = "briefs"; Column = "*"; Access = Read }
Column-level tracking deferred — start with table-level (*). Constructor takes a
pattern to identify SqlHydra generated modules (e.g., "Generated" or configurable).
D: Status Provenance
When the status command lists affected tests, show the set of edge sources involved
in the selection path. For each affected test, query all edges in the transitive closure
between changed symbols and the test, collect distinct source values:
Would run 1 test(s):
MyTests:
Tests
- testA [sources: core, sql]
Full path tracing (showing the exact edge chain) is a follow-up.
Implementation Notes
- All three streams (A/B, C, D) are independent and can be implemented in parallel.
- A must land before B (B depends on attribute data in DB).
- C depends only on existing
SymbolStorequeries. - D depends only on the
sourcefield already in thedependenciestable. - Use TDD throughout.
val string: value: 'T -> string
--------------------
type string = System.String
TestPrune