xrefkit-skills-batch-regression 0.4.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.
- xrefkit_skills_batch_regression-0.4.1/PKG-INFO +27 -0
- xrefkit_skills_batch_regression-0.4.1/README.md +19 -0
- xrefkit_skills_batch_regression-0.4.1/pyproject.toml +29 -0
- xrefkit_skills_batch_regression-0.4.1/setup.cfg +4 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/__init__.py +11 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/cli.py +14 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/package_manifest.yaml +42 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/entry.md +24 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/fixtures/config.json +6 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/fixtures/new-results.json +1 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/fixtures/old-results.json +1 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/adapter-contract.md +25 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/code-table-extraction.md +23 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/config-schema.md +25 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/config.template.json +31 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/csharp-sql-analysis.md +17 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/fixture-notes.md +8 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/references/workflow.md +44 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/scripts/batch_regression.py +152 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/scripts/code_tables.py +77 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skills/batch_impact_regression.skill.yaml +44 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/PKG-INFO +27 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/SOURCES.txt +25 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/dependency_links.txt +1 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/entry_points.txt +5 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/requires.txt +1 -0
- xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xrefkit-skills-batch-regression
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: XRefKit Skill Package for C# and SQL Server batch impact analysis and combination regression
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: xrefkit<0.5.0,>=0.4.0
|
|
8
|
+
|
|
9
|
+
# xrefkit-skills-batch-regression
|
|
10
|
+
|
|
11
|
+
XRefKit Skill Package v0.4.1 for impact analysis and combination regression of
|
|
12
|
+
existing C# batches backed by SQL Server stored procedures.
|
|
13
|
+
|
|
14
|
+
The package provides a discoverable XRefKit v2 Skill Package and bundles the
|
|
15
|
+
repository-native Skill procedure, deterministic combination/result tools,
|
|
16
|
+
source condition extraction, configuration references, and synthetic fixtures.
|
|
17
|
+
Real batch and database execution still requires an isolated adapter supplied
|
|
18
|
+
by the consuming project.
|
|
19
|
+
|
|
20
|
+
Install:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
python -m pip install xrefkit-skills-batch-regression==0.4.1
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The package is discovered through the `xrefkit.skill_packages` entry-point
|
|
27
|
+
group and includes the deterministic tools under `skill_assets/scripts/`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# xrefkit-skills-batch-regression
|
|
2
|
+
|
|
3
|
+
XRefKit Skill Package v0.4.1 for impact analysis and combination regression of
|
|
4
|
+
existing C# batches backed by SQL Server stored procedures.
|
|
5
|
+
|
|
6
|
+
The package provides a discoverable XRefKit v2 Skill Package and bundles the
|
|
7
|
+
repository-native Skill procedure, deterministic combination/result tools,
|
|
8
|
+
source condition extraction, configuration references, and synthetic fixtures.
|
|
9
|
+
Real batch and database execution still requires an isolated adapter supplied
|
|
10
|
+
by the consuming project.
|
|
11
|
+
|
|
12
|
+
Install:
|
|
13
|
+
|
|
14
|
+
```powershell
|
|
15
|
+
python -m pip install xrefkit-skills-batch-regression==0.4.1
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The package is discovered through the `xrefkit.skill_packages` entry-point
|
|
19
|
+
group and includes the deterministic tools under `skill_assets/scripts/`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "xrefkit-skills-batch-regression"
|
|
7
|
+
version = "0.4.1"
|
|
8
|
+
description = "XRefKit Skill Package for C# and SQL Server batch impact analysis and combination regression"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"xrefkit>=0.4.0,<0.5.0",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.entry-points."xrefkit.skill_packages"]
|
|
16
|
+
batch_regression = "xrefkit_skills_batch_regression:package_root"
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
xrefkit-batch-regression = "xrefkit_skills_batch_regression.cli:main"
|
|
20
|
+
|
|
21
|
+
[tool.setuptools.packages.find]
|
|
22
|
+
where = ["src"]
|
|
23
|
+
|
|
24
|
+
[tool.setuptools.package-data]
|
|
25
|
+
"xrefkit_skills_batch_regression" = [
|
|
26
|
+
"package_manifest.yaml",
|
|
27
|
+
"skills/*.yaml",
|
|
28
|
+
"skill_assets/**/*",
|
|
29
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""XRefKit Skill Package for batch impact and combination regression."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def package_root() -> Path:
|
|
9
|
+
"""Return the installed package root containing package_manifest.yaml."""
|
|
10
|
+
|
|
11
|
+
return Path(__file__).parent
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Convenience entry point for the bundled deterministic batch tool."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def main() -> int:
|
|
10
|
+
scripts = Path(__file__).parent / "skill_assets" / "scripts"
|
|
11
|
+
sys.path.insert(0, str(scripts))
|
|
12
|
+
from batch_regression import main as run # type: ignore
|
|
13
|
+
|
|
14
|
+
return run()
|
xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/package_manifest.yaml
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package_id: xrefkit.skills.batch_regression
|
|
2
|
+
package_type: skill_package
|
|
3
|
+
version: 0.4.1
|
|
4
|
+
|
|
5
|
+
requires:
|
|
6
|
+
xrefkit_core: ">=2.0.0 <3.0.0"
|
|
7
|
+
|
|
8
|
+
provides:
|
|
9
|
+
skills:
|
|
10
|
+
- id: batch.impact_regression
|
|
11
|
+
xid: xid-skill-batch-impact-regression
|
|
12
|
+
path: skills/batch_impact_regression.skill.yaml
|
|
13
|
+
contract_role: base_skill
|
|
14
|
+
required_outputs:
|
|
15
|
+
- decision_table
|
|
16
|
+
- orthogonal_table
|
|
17
|
+
- regression_report
|
|
18
|
+
- evidence
|
|
19
|
+
- unknowns
|
|
20
|
+
- human_handoffs
|
|
21
|
+
required_knowledge: []
|
|
22
|
+
required_review_axes: []
|
|
23
|
+
must_not:
|
|
24
|
+
- treat_source_conditions_as_business_truth
|
|
25
|
+
- treat_baseline_results_as_business_correctness
|
|
26
|
+
- execute_against_production
|
|
27
|
+
- auto_accept_unexplained_differences
|
|
28
|
+
- claim_dynamic_sql_is_resolved_without_runtime_evidence
|
|
29
|
+
|
|
30
|
+
fragments: []
|
|
31
|
+
knowledge: []
|
|
32
|
+
review_axes: []
|
|
33
|
+
schemas: []
|
|
34
|
+
templates: []
|
|
35
|
+
|
|
36
|
+
contract:
|
|
37
|
+
can_be_extended_by_local_skill: true
|
|
38
|
+
local_skill_can_weaken_contract: false
|
|
39
|
+
local_can_weaken_required_outputs: false
|
|
40
|
+
local_can_override_must_not: false
|
|
41
|
+
requires_unknown_declaration: true
|
|
42
|
+
requires_traceability: true
|
xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression/skill_assets/entry.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Batch Impact Regression
|
|
2
|
+
|
|
3
|
+
Analyze existing C# batches and SQL Server stored-procedure execution paths
|
|
4
|
+
when a requirement changes behavior and the combination space is large.
|
|
5
|
+
|
|
6
|
+
Follow the bundled 15-step workflow in `references/workflow.md`. Inspect C#
|
|
7
|
+
and SQL as one execution path, keep business constraints separate from source
|
|
8
|
+
conditions, and stop when dynamic dispatch, DB side effects, or expected
|
|
9
|
+
differences lack evidence.
|
|
10
|
+
|
|
11
|
+
Use the deterministic tools under `scripts/`:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
python scripts/batch_regression.py extract-tables <source-root> -o tables.json
|
|
15
|
+
python scripts/batch_regression.py report <config.json> <old.json> <new.json> -o report.json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The first command creates source-backed decision-table evidence, inferred
|
|
19
|
+
factors, and a strength-2 pairwise covering-table candidate. The second
|
|
20
|
+
compares old/new adapter records. Neither command connects to a real database;
|
|
21
|
+
use an isolated adapter conforming to `references/adapter-contract.md`.
|
|
22
|
+
|
|
23
|
+
The human remains responsible for business validity, baseline correctness,
|
|
24
|
+
planned differences, unexplained differences, and release disposition.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"combination": {"elements": [{"name":"a","values":[1,2]}, {"name":"b","values":["x","y"]}], "constraints": [{"id":"fixture-ban","kind":"forbidden","when":{"all":[{"field":"a","op":"eq","value":2},{"field":"b","op":"eq","value":"y"}]},"reason":"fixture-only constraint","evidence":["fixtures/config.json"]}]},
|
|
3
|
+
"comparison": {"key_fields":["a","b"],"fields":["status","result","updated_rows"],"ignore_fields":["execution_id"],"normalize_fields":{}},
|
|
4
|
+
"planned_differences": [{"id":"fixture-change","when":{"all":[{"field":"a","op":"eq","value":1},{"field":"b","op":"eq","value":"y"}]},"fields":["result"],"relation":"fixture-only planned difference"}],
|
|
5
|
+
"regression_set":{"max_size":10,"seed":7}
|
|
6
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"input":{"a":1,"b":"x"},"status":"success","result":10,"updated_rows":1,"execution_id":"new-1"},{"input":{"a":1,"b":"y"},"status":"success","result":11,"updated_rows":1,"execution_id":"new-2"},{"input":{"a":2,"b":"x"},"status":"success","result":99,"updated_rows":1,"execution_id":"new-3"}]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"input":{"a":1,"b":"x"},"status":"success","result":10,"updated_rows":1,"execution_id":"old-1"},{"input":{"a":1,"b":"y"},"status":"success","result":10,"updated_rows":1,"execution_id":"old-2"},{"input":{"a":2,"b":"x"},"status":"business_error","result":null,"updated_rows":0,"execution_id":"old-3"}]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!-- xid: F4818190FD09 -->
|
|
2
|
+
<a id="xid-F4818190FD09"></a>
|
|
3
|
+
|
|
4
|
+
# Adapter boundary
|
|
5
|
+
|
|
6
|
+
The Skill does not claim to connect to a real batch or database. An adapter
|
|
7
|
+
must produce versioned JSON records with:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"input": {"dimension": "value"},
|
|
12
|
+
"status": "success|business_error|system_error|not_executed",
|
|
13
|
+
"result": {"field": "value"},
|
|
14
|
+
"error": {"code": "...", "message": "..."},
|
|
15
|
+
"updated_rows": 0,
|
|
16
|
+
"path_refs": ["path-id"],
|
|
17
|
+
"evidence_refs": ["file-or-log"]
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
An implementation may wrap `dotnet`, a test harness, or SQL Server tooling,
|
|
22
|
+
but it must enforce the configured timeout, isolate the DB, capture exit code,
|
|
23
|
+
stdout/stderr, result sets, return values, OUTPUT values, exceptions, and side
|
|
24
|
+
effect checks. The deterministic scripts consume artifacts; they do not invent
|
|
25
|
+
adapter output.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- xid: 8E50930676E2 -->
|
|
2
|
+
<a id="xid-8E50930676E2"></a>
|
|
3
|
+
|
|
4
|
+
# Code table extraction
|
|
5
|
+
|
|
6
|
+
Run:
|
|
7
|
+
|
|
8
|
+
```powershell
|
|
9
|
+
python scripts/batch_regression.py extract-tables <source-root> -o <report.json>
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The scanner reads `.cs` and `.sql` files and emits:
|
|
13
|
+
|
|
14
|
+
- `decision_table`: each statically recognized `if`, `when`, or `case` condition with source path and line
|
|
15
|
+
- `factors`: fields and literal comparison values with evidence references
|
|
16
|
+
- `orthogonal_table`: deterministic strength-2 pairwise covering rows
|
|
17
|
+
- `uncertainties`: expressions that were found but not resolved statically
|
|
18
|
+
|
|
19
|
+
The output is evidence for review. It does not prove that a condition is an
|
|
20
|
+
業務ルール, does not infer branch outcomes, and does not replace compilation,
|
|
21
|
+
Roslyn analysis, SQL Server parsing, or human confirmation. Dynamic SQL,
|
|
22
|
+
reflection, generated code, macros, configuration-driven rules, and complex
|
|
23
|
+
multi-line expressions may remain unresolved.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!-- xid: A0B8B60D3325 -->
|
|
2
|
+
<a id="xid-A0B8B60D3325"></a>
|
|
3
|
+
|
|
4
|
+
# Configuration schema
|
|
5
|
+
|
|
6
|
+
The JSON template is intentionally declarative. Predicates use `all` or
|
|
7
|
+
`any` clauses with `eq`, `neq`, `in`, `not_in`, `exists`, and `missing`.
|
|
8
|
+
`forbidden` excludes a candidate; `business_invalid`, `upstream_absent`, and
|
|
9
|
+
`uncertain` classify it without pretending to prove the business rule.
|
|
10
|
+
|
|
11
|
+
Top-level fields:
|
|
12
|
+
|
|
13
|
+
- `system`: `solution`, `project`, `command`, `test_db`, `old_version`, `new_version`, `timeout_seconds`, `parallelism`, `side_effect_check`
|
|
14
|
+
- `combination.elements`: ordered `{name, values}` dimensions
|
|
15
|
+
- `combination.constraints`: `{id, kind, when, reason, evidence}`
|
|
16
|
+
- `comparison`: `key_fields`, `fields`, `ignore_fields`, `normalize_fields`
|
|
17
|
+
- `planned_differences`: `{id, when, fields, relation, evidence}`
|
|
18
|
+
- `paths`: `{id, description, csharp, stored_procedures, child_stored_procedures, dynamic_sql, dynamic_sp_name}` for trace links
|
|
19
|
+
- `regression_set`: `max_size`, `seed`
|
|
20
|
+
|
|
21
|
+
Source-table extraction is invoked separately with the source root; it does not
|
|
22
|
+
require a comparison result file or a database adapter.
|
|
23
|
+
|
|
24
|
+
Constraint and expectation predicates are data, not Python or SQL. No example
|
|
25
|
+
in this Skill claims an actual business rule; template values are placeholders.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"system": {
|
|
3
|
+
"solution": "path/to/app.sln",
|
|
4
|
+
"project": "path/to/batch.csproj",
|
|
5
|
+
"command": "dotnet run --project path/to/batch.csproj -- ...",
|
|
6
|
+
"test_db": "isolated-test-db-connection-placeholder",
|
|
7
|
+
"old_version": "old-build-or-commit",
|
|
8
|
+
"new_version": "new-build-or-commit",
|
|
9
|
+
"timeout_seconds": 60,
|
|
10
|
+
"parallelism": 1,
|
|
11
|
+
"side_effect_check": "before-after row counts and changed keys; human-approved rollback/restore"
|
|
12
|
+
},
|
|
13
|
+
"combination": {
|
|
14
|
+
"elements": [
|
|
15
|
+
{"name": "dimension_a", "values": ["value_a1", "value_a2"]},
|
|
16
|
+
{"name": "dimension_b", "values": ["value_b1", "value_b2"]}
|
|
17
|
+
],
|
|
18
|
+
"constraints": [
|
|
19
|
+
{"id": "constraint-placeholder", "kind": "forbidden", "when": {"all": [{"field": "dimension_a", "op": "eq", "value": "value_a1"}, {"field": "dimension_b", "op": "eq", "value": "value_b2"}]}, "reason": "REPLACE_WITH_EVIDENCED_RULE", "evidence": ["human-approved-source"]}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"comparison": {
|
|
23
|
+
"key_fields": ["dimension_a", "dimension_b"],
|
|
24
|
+
"fields": ["status", "result", "updated_rows"],
|
|
25
|
+
"ignore_fields": ["execution_id", "started_at", "finished_at"],
|
|
26
|
+
"normalize_fields": {"started_at": "datetime", "finished_at": "datetime"}
|
|
27
|
+
},
|
|
28
|
+
"planned_differences": [],
|
|
29
|
+
"paths": [],
|
|
30
|
+
"regression_set": {"max_size": 20, "seed": 7}
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!-- xid: 9C03927FF35B -->
|
|
2
|
+
<a id="xid-9C03927FF35B"></a>
|
|
3
|
+
|
|
4
|
+
# C# and SQL Server analysis checklist
|
|
5
|
+
|
|
6
|
+
Analyze one execution path across both layers. Record evidence locations for:
|
|
7
|
+
|
|
8
|
+
- C# schedule/CLI entry, command construction, SP name resolution, parameter names/types/size/precision/scale, NULL/empty/default/date/decimal conversion, timeout, retries, cancellation, result-set mapping, return value, OUTPUT parameters, and exceptions.
|
|
9
|
+
- SP definitions and child SPs, functions, views, tables, temp tables, table variables, dynamic SQL, dynamic object names, validation/calculation/update branches, row counts, transaction boundaries, isolation, locks, commits/rollbacks, triggers, and error propagation.
|
|
10
|
+
- Cross-boundary type, precision/scale, rounding, collation, date/time-zone, NULL, empty-string, default-value, and encoding behavior.
|
|
11
|
+
|
|
12
|
+
Do not conclude from C# alone or SQL alone. If dynamic SQL or dynamic SP
|
|
13
|
+
resolution cannot be closed statically, record the unresolved target and the
|
|
14
|
+
affected candidate count as `uncertain` until runtime evidence closes it.
|
|
15
|
+
Never run a write-capable batch against production. Prefer a cloned/snapshot
|
|
16
|
+
DB, isolated schema, disposable database, or transaction rollback, and prove
|
|
17
|
+
the side-effect check with before/after row counts and changed keys.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<!-- xid: B1EDF6CFC6BE -->
|
|
2
|
+
<a id="xid-B1EDF6CFC6BE"></a>
|
|
3
|
+
|
|
4
|
+
# Fixture boundary
|
|
5
|
+
|
|
6
|
+
The files under `fixtures/` contain synthetic values only. They demonstrate
|
|
7
|
+
the adapter record shape and classification mechanics; they are not business
|
|
8
|
+
constraints, production results, or evidence about any real batch.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!-- xid: 427525B4935A -->
|
|
2
|
+
<a id="xid-427525B4935A"></a>
|
|
3
|
+
|
|
4
|
+
# Workflow and decision rules
|
|
5
|
+
|
|
6
|
+
## 15-step sequence
|
|
7
|
+
|
|
8
|
+
1. Confirm system boundary, executable command, versions, isolated DB, and adapter.
|
|
9
|
+
2. Locate C# entry points and every SP invocation and parameter mapping.
|
|
10
|
+
3. Trace child SPs, functions, views, tables, temp objects, table variables, dynamic SQL, transactions, outputs, result sets, and exceptions.
|
|
11
|
+
4. Extract combination dimensions and values from evidence; mark missing values unknown.
|
|
12
|
+
5. Record business, technical, and upstream constraints in separate ledgers.
|
|
13
|
+
6. Compute Cartesian candidate count and post-constraint count deterministically.
|
|
14
|
+
7. Prove safe execution with a small input and verify DB side effects.
|
|
15
|
+
8. Decide full-run feasibility from measured duration, timeout, parallelism, and side effects.
|
|
16
|
+
9. Capture the old version as observed baseline, never as business truth.
|
|
17
|
+
10. Define the new requirement predicate and allowed differences with evidence and owner.
|
|
18
|
+
11. Run old and new on identical serialized inputs through an isolated adapter.
|
|
19
|
+
12. Normalize and classify each result; retain traceability for every difference.
|
|
20
|
+
13. Select a deterministic daily reduced regression set covering dimensions, constraints, paths, and difference classes.
|
|
21
|
+
14. Generate a release-time full-run procedure with rollback/restore and stop gates.
|
|
22
|
+
15. Escalate unresolved decisions; do not close while material unknowns remain unowned.
|
|
23
|
+
|
|
24
|
+
## Classification precedence
|
|
25
|
+
|
|
26
|
+
`system_error` > `uncertain` > `business_invalid` > `upstream_absent` >
|
|
27
|
+
result comparison. An explicitly configured `business_invalid` or
|
|
28
|
+
`upstream_absent` predicate is evidence for classification, not a substitute
|
|
29
|
+
for human approval. A missing predicate or unresolved dynamic path is
|
|
30
|
+
`uncertain`, not valid.
|
|
31
|
+
|
|
32
|
+
## Result comparison
|
|
33
|
+
|
|
34
|
+
Compare configured fields after removing or normalizing only configured
|
|
35
|
+
non-deterministic fields. `planned_difference` requires a matching expected
|
|
36
|
+
difference rule. Any other changed value is `unexplained_difference`.
|
|
37
|
+
Unchanged successful outcomes are `baseline_match`. Missing execution records
|
|
38
|
+
are `not_executed`.
|
|
39
|
+
|
|
40
|
+
## Human decisions
|
|
41
|
+
|
|
42
|
+
Present the candidate input, counts, evidence, and impact of each option for:
|
|
43
|
+
business validity, baseline defects, expected differences, upstream absence,
|
|
44
|
+
and release disposition. Do not fill these decisions by inference.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Deterministic combination and old/new batch-result analysis.
|
|
3
|
+
|
|
4
|
+
This module deliberately has no database or process adapter. Adapters emit the
|
|
5
|
+
JSON record contract in references/adapter-contract.md; this tool consumes it.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
import argparse, csv, hashlib, itertools, json, random, sys
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from code_tables import extract_source_tables, pairwise_table
|
|
12
|
+
|
|
13
|
+
STATUSES = {"success", "business_error", "system_error", "not_executed"}
|
|
14
|
+
|
|
15
|
+
def predicate(value, spec):
|
|
16
|
+
if not spec: return False
|
|
17
|
+
clauses = spec.get("all", spec.get("any", []))
|
|
18
|
+
matched = [clause(value, c) for c in clauses]
|
|
19
|
+
return all(matched) if "all" in spec else any(matched)
|
|
20
|
+
|
|
21
|
+
def clause(row, c):
|
|
22
|
+
field, op, expected = c["field"], c["op"], c.get("value")
|
|
23
|
+
present = field in row and row[field] is not None
|
|
24
|
+
actual = row.get(field)
|
|
25
|
+
if op == "eq": return actual == expected
|
|
26
|
+
if op == "neq": return actual != expected
|
|
27
|
+
if op == "in": return actual in expected if isinstance(expected, (list, tuple, set)) else False
|
|
28
|
+
if op == "not_in": return actual not in expected if isinstance(expected, (list, tuple, set)) else False
|
|
29
|
+
if op == "exists": return present
|
|
30
|
+
if op == "missing": return not present
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
def generate_candidates(config):
|
|
34
|
+
elements = config["combination"]["elements"]
|
|
35
|
+
names = [e["name"] for e in elements]
|
|
36
|
+
candidates = [dict(zip(names, values)) for values in itertools.product(*(e["values"] for e in elements))]
|
|
37
|
+
all_count = len(candidates)
|
|
38
|
+
kept, classifications = [], []
|
|
39
|
+
for row in candidates:
|
|
40
|
+
excluded = None
|
|
41
|
+
for c in config["combination"].get("constraints", []):
|
|
42
|
+
kind = c["kind"]
|
|
43
|
+
matched = predicate(row, c.get("when"))
|
|
44
|
+
missing_required = kind in ("required", "required_if") and matched and not row.get(c.get("field"))
|
|
45
|
+
if matched and (kind in ("forbidden", "business_invalid", "upstream_absent", "uncertain") or missing_required):
|
|
46
|
+
excluded = c
|
|
47
|
+
break
|
|
48
|
+
if excluded:
|
|
49
|
+
kind = excluded["kind"]
|
|
50
|
+
classification = {"forbidden": "business_invalid", "business_invalid": "business_invalid", "upstream_absent": "upstream_absent", "uncertain": "uncertain"}.get(kind, "business_invalid")
|
|
51
|
+
classifications.append({"input": row, "classification": classification, "constraint": excluded})
|
|
52
|
+
else:
|
|
53
|
+
kept.append(row)
|
|
54
|
+
classifications.append({"input": row, "classification": "candidate"})
|
|
55
|
+
return {"all_candidate_count": all_count, "post_constraint_count": len(kept), "candidates": kept, "classifications": classifications}
|
|
56
|
+
|
|
57
|
+
def analyze_paths(paths):
|
|
58
|
+
"""Summarize static execution-path evidence without pretending to resolve dynamic dispatch."""
|
|
59
|
+
result = {"path_count": len(paths), "dual_layer_paths": 0, "child_sp_paths": 0, "dynamic_unknowns": []}
|
|
60
|
+
for path in paths:
|
|
61
|
+
if path.get("csharp") and path.get("stored_procedures"): result["dual_layer_paths"] += 1
|
|
62
|
+
if path.get("child_stored_procedures"): result["child_sp_paths"] += 1
|
|
63
|
+
if path.get("dynamic_sql") or path.get("dynamic_sp_name"):
|
|
64
|
+
result["dynamic_unknowns"].append({"path_id": path.get("id"), "reason": "dynamic SQL or stored-procedure target requires runtime evidence"})
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
def normalize(record, config):
|
|
68
|
+
record = json.loads(json.dumps(record, ensure_ascii=False))
|
|
69
|
+
for field in config.get("comparison", {}).get("ignore_fields", []): record.pop(field, None)
|
|
70
|
+
for field, kind in config.get("comparison", {}).get("normalize_fields", {}).items():
|
|
71
|
+
if field not in record: continue
|
|
72
|
+
if kind == "datetime":
|
|
73
|
+
try: record[field] = datetime.fromisoformat(str(record[field]).replace("Z", "+00:00")).isoformat()
|
|
74
|
+
except ValueError: record[field] = "<invalid-datetime>"
|
|
75
|
+
elif kind == "number":
|
|
76
|
+
try: record[field] = float(record[field])
|
|
77
|
+
except (TypeError, ValueError): record[field] = "<invalid-number>"
|
|
78
|
+
return record
|
|
79
|
+
|
|
80
|
+
def compare(old_records, new_records, config):
|
|
81
|
+
key = lambda r: tuple(r.get("input", {}).get(k) for k in config["comparison"]["key_fields"])
|
|
82
|
+
old, new = {key(r): r for r in old_records}, {key(r): r for r in new_records}
|
|
83
|
+
expected = config.get("planned_differences", [])
|
|
84
|
+
rows = []
|
|
85
|
+
for k in sorted(set(old) | set(new), key=str):
|
|
86
|
+
o, n = old.get(k), new.get(k)
|
|
87
|
+
if not o or not n: cls = "not_executed"
|
|
88
|
+
elif n.get("status") == "system_error" or o.get("status") == "system_error": cls = "system_error"
|
|
89
|
+
elif n.get("status") == "not_executed": cls = "not_executed"
|
|
90
|
+
elif n.get("status") == "business_error" and o.get("status") != "business_error": cls = "business_invalid"
|
|
91
|
+
elif n.get("status") not in STATUSES or o.get("status") not in STATUSES: cls = "uncertain"
|
|
92
|
+
else:
|
|
93
|
+
on, nn = normalize(o, config), normalize(n, config)
|
|
94
|
+
fields = config["comparison"].get("fields", [])
|
|
95
|
+
changed = [f for f in fields if on.get(f) != nn.get(f)]
|
|
96
|
+
if not changed: cls = "baseline_match"
|
|
97
|
+
else:
|
|
98
|
+
hit = next((p for p in expected if predicate(n.get("input", {}), p.get("when")) and set(changed).issubset(set(p.get("fields", [])))), None)
|
|
99
|
+
cls = "planned_difference" if hit else "unexplained_difference"
|
|
100
|
+
rows.append({"input": (n or o).get("input", {}), "old": o, "new": n, "classification": cls,
|
|
101
|
+
"path_refs": sorted(set((o or {}).get("path_refs", []) + (n or {}).get("path_refs", []))),
|
|
102
|
+
"planned_relation": next((p.get("relation") for p in expected if predicate((n or o).get("input", {}), p.get("when"))), None)})
|
|
103
|
+
return rows
|
|
104
|
+
|
|
105
|
+
def summarize(candidate_report, comparisons, config):
|
|
106
|
+
counts = {k: 0 for k in ["baseline_match", "business_invalid", "system_error", "planned_difference", "unexplained_difference", "uncertain", "not_executed", "upstream_absent"]}
|
|
107
|
+
for row in candidate_report["classifications"]:
|
|
108
|
+
if row["classification"] == "business_invalid": counts["business_invalid"] += 1
|
|
109
|
+
for row in comparisons: counts[row["classification"]] = counts.get(row["classification"], 0) + 1
|
|
110
|
+
old_records = [row["old"] for row in comparisons if row.get("old")]
|
|
111
|
+
new_records = [row["new"] for row in comparisons if row.get("new")]
|
|
112
|
+
paths = {}
|
|
113
|
+
for row in comparisons:
|
|
114
|
+
for path in row.get("path_refs", []) or ["unattributed"]: paths[path] = paths.get(path, 0) + 1
|
|
115
|
+
return {**counts, "all_candidate_count": candidate_report["all_candidate_count"], "post_constraint_count": candidate_report["post_constraint_count"],
|
|
116
|
+
"current_normal_count": sum(r.get("status") == "success" for r in old_records),
|
|
117
|
+
"business_error_count": sum(r.get("status") == "business_error" for r in old_records),
|
|
118
|
+
"new_system_error_count": sum(r.get("status") == "system_error" for r in new_records),
|
|
119
|
+
"unexecuted_count": counts.get("not_executed", 0),
|
|
120
|
+
"processed_count": len(comparisons), "path_counts": paths, "representative_regression_set_count": len(select_regression_set(comparisons, config)),
|
|
121
|
+
"analysis": analyze_paths(config.get("paths", [])),
|
|
122
|
+
"human_judgments_required": ["business validity", "baseline defects", "planned differences", "unexplained differences", "release disposition"]}
|
|
123
|
+
|
|
124
|
+
def select_regression_set(rows, config):
|
|
125
|
+
limit, seed = config.get("regression_set", {}).get("max_size", 100), config.get("regression_set", {}).get("seed", 0)
|
|
126
|
+
by_class = {}
|
|
127
|
+
for row in rows: by_class.setdefault(row["classification"], []).append(row)
|
|
128
|
+
selected = []
|
|
129
|
+
for cls in sorted(by_class): selected.append(sorted(by_class[cls], key=lambda r: json.dumps(r["input"], sort_keys=True))[0])
|
|
130
|
+
rest = [r for r in rows if r not in selected]; random.Random(seed).shuffle(rest)
|
|
131
|
+
return (selected + rest)[:limit]
|
|
132
|
+
|
|
133
|
+
def load(path): return json.loads(Path(path).read_text(encoding="utf-8"))
|
|
134
|
+
def main(argv=None):
|
|
135
|
+
p = argparse.ArgumentParser(); sub = p.add_subparsers(dest="cmd", required=True)
|
|
136
|
+
g = sub.add_parser("generate"); g.add_argument("config"); g.add_argument("-o", "--output", required=True)
|
|
137
|
+
c = sub.add_parser("compare"); c.add_argument("config"); c.add_argument("old"); c.add_argument("new"); c.add_argument("-o", "--output", required=True)
|
|
138
|
+
r = sub.add_parser("report"); r.add_argument("config"); r.add_argument("old"); r.add_argument("new"); r.add_argument("-o", "--output", required=True)
|
|
139
|
+
t = sub.add_parser("extract-tables"); t.add_argument("root"); t.add_argument("-o", "--output", required=True)
|
|
140
|
+
args = p.parse_args(argv)
|
|
141
|
+
if args.cmd == "extract-tables":
|
|
142
|
+
out = extract_source_tables(args.root)
|
|
143
|
+
out["orthogonal_table"] = pairwise_table(out["factors"])
|
|
144
|
+
else:
|
|
145
|
+
config = load(args.config); candidates = generate_candidates(config)
|
|
146
|
+
if args.cmd == "generate": out = candidates
|
|
147
|
+
else:
|
|
148
|
+
comparisons = compare(load(args.old), load(args.new), config)
|
|
149
|
+
if args.cmd == "compare": out = comparisons
|
|
150
|
+
else: out = {"summary": summarize(candidates, comparisons, config), "comparisons": comparisons, "regression_set": select_regression_set(comparisons, config)}
|
|
151
|
+
Path(args.output).write_text(json.dumps(out, ensure_ascii=False, indent=2), encoding="utf-8"); return 0
|
|
152
|
+
if __name__ == "__main__": sys.exit(main())
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Conservative, evidence-preserving extraction of decision and pairwise tables.
|
|
3
|
+
|
|
4
|
+
This is a syntax scanner, not a C# or T-SQL compiler. Unresolved expressions
|
|
5
|
+
remain explicit in ``uncertainties`` and must not be promoted to business rules.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
import itertools, re
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
CONDITION_RE = re.compile(r"\b(if|when|case)\b(?P<expr>[^\r\n]*)", re.I)
|
|
12
|
+
COMPARISON_RE = re.compile(r"(?P<field>[\[\]A-Za-z_][\w.\[\]]*)\s*(?P<op>==|!=|>=|<=|>|<|=|\bIN\b|\bIS\b)\s*(?P<value>\([^\)]*\)|[^,;\s\)]+)", re.I)
|
|
13
|
+
STRING_RE = re.compile(r"'(?:''|[^'])*'|\"(?:\\.|[^\"])*\"")
|
|
14
|
+
IDENTIFIER_RE = re.compile(r"^[\[\]A-Za-z_][\w.\[\]]*$")
|
|
15
|
+
KEYWORDS = {"if", "when", "case", "then", "else", "and", "or", "not", "is", "null", "true", "false"}
|
|
16
|
+
|
|
17
|
+
def _clean(value):
|
|
18
|
+
value = value.strip().strip("[]")
|
|
19
|
+
return value
|
|
20
|
+
|
|
21
|
+
def _literal_values(value):
|
|
22
|
+
value = value.strip()
|
|
23
|
+
if value.startswith("(") and value.endswith(")"):
|
|
24
|
+
parts = value[1:-1].split(",")
|
|
25
|
+
return [_clean(p).strip("'\"") for p in parts if p.strip()]
|
|
26
|
+
if STRING_RE.fullmatch(value): return [value[1:-1].replace("''", "'").replace('\\"', '"')]
|
|
27
|
+
if re.fullmatch(r"-?\d+(?:\.\d+)?", value): return [value]
|
|
28
|
+
if value.upper() in {"NULL", "TRUE", "FALSE"}: return [value.upper()]
|
|
29
|
+
return []
|
|
30
|
+
|
|
31
|
+
def _language(path): return "csharp" if path.suffix.lower() == ".cs" else "sql"
|
|
32
|
+
|
|
33
|
+
def extract_source_tables(root):
|
|
34
|
+
root = Path(root)
|
|
35
|
+
rows, factors, uncertainties, files = [], {}, [], []
|
|
36
|
+
paths = sorted(p for p in root.rglob("*") if p.is_file() and p.suffix.lower() in {".cs", ".sql"})
|
|
37
|
+
for path in paths:
|
|
38
|
+
rel = str(path.relative_to(root)).replace("\\", "/")
|
|
39
|
+
files.append(rel)
|
|
40
|
+
for line_no, line in enumerate(path.read_text(encoding="utf-8", errors="replace").splitlines(), 1):
|
|
41
|
+
for match in CONDITION_RE.finditer(line):
|
|
42
|
+
expr = match.group("expr").strip()
|
|
43
|
+
expr = re.sub(r"^\(?\s*(?:when|case)\b", "", expr, flags=re.I).strip()
|
|
44
|
+
expr = re.split(r"\bthen\b", expr, maxsplit=1, flags=re.I)[0].strip()
|
|
45
|
+
expr = expr.rstrip("{").strip().rstrip(")").strip()
|
|
46
|
+
comparisons = []
|
|
47
|
+
for comp in COMPARISON_RE.finditer(expr):
|
|
48
|
+
field, op, raw = _clean(comp.group("field")), comp.group("op").upper(), comp.group("value")
|
|
49
|
+
if field.lower() in KEYWORDS: continue
|
|
50
|
+
values = _literal_values(raw)
|
|
51
|
+
if not values:
|
|
52
|
+
uncertainties.append({"source": f"{rel}:{line_no}", "expression": expr, "reason": "comparison value or expression is not statically literal"})
|
|
53
|
+
values = ["<unknown>"]
|
|
54
|
+
comparisons.append({"field": field, "operator": op, "values": values})
|
|
55
|
+
factors.setdefault(field, {"values": set(), "evidence": []})["values"].update(values)
|
|
56
|
+
factors[field]["evidence"].append(f"{rel}:{line_no}")
|
|
57
|
+
if comparisons:
|
|
58
|
+
rows.append({"id": f"DT-{len(rows)+1:04d}", "source": f"{rel}:{line_no}", "language": _language(path), "construct": match.group(1).lower(), "condition": expr, "conditions": comparisons, "outcome": "<human-confirmation-required>"})
|
|
59
|
+
elif expr and not IDENTIFIER_RE.fullmatch(expr):
|
|
60
|
+
uncertainties.append({"source": f"{rel}:{line_no}", "expression": expr, "reason": "condition found but no deterministic comparison extracted"})
|
|
61
|
+
factor_list = [{"name": name, "values": sorted(data["values"], key=str), "evidence": sorted(set(data["evidence"]))} for name, data in sorted(factors.items())]
|
|
62
|
+
return {"source_root": str(root), "files": files, "factors": factor_list, "decision_table": rows, "uncertainties": uncertainties}
|
|
63
|
+
|
|
64
|
+
def pairwise_table(factors):
|
|
65
|
+
"""Create a deterministic strength-2 covering table from extracted factors."""
|
|
66
|
+
if not factors: return {"strength": 2, "rows": [], "uncovered_pairs": []}
|
|
67
|
+
names, domains = [f["name"] for f in factors], [f["values"] or ["<unknown>"] for f in factors]
|
|
68
|
+
if len(names) == 1: return {"strength": 2, "rows": [{names[0]: v} for v in domains[0]], "uncovered_pairs": []}
|
|
69
|
+
required = {(i, j, a, b) for i in range(len(names)) for j in range(i+1, len(names)) for a in domains[i] for b in domains[j]}
|
|
70
|
+
candidates = [dict(zip(names, values)) for values in itertools.product(*domains)]
|
|
71
|
+
selected = []
|
|
72
|
+
while required:
|
|
73
|
+
best = max(candidates, key=lambda row: sum((i, j, row[names[i]], row[names[j]]) in required for i in range(len(names)) for j in range(i+1, len(names))))
|
|
74
|
+
selected.append(best)
|
|
75
|
+
required -= {(i, j, best[names[i]], best[names[j]]) for i in range(len(names)) for j in range(i+1, len(names))}
|
|
76
|
+
candidates.remove(best)
|
|
77
|
+
return {"strength": 2, "rows": selected, "uncovered_pairs": sorted([list(x) for x in required], key=str)}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
skill_id: batch.impact_regression
|
|
2
|
+
xid: xid-skill-batch-impact-regression
|
|
3
|
+
role: base_skill_contract
|
|
4
|
+
|
|
5
|
+
entry:
|
|
6
|
+
xid: xid-entry-batch-impact-regression
|
|
7
|
+
path: skill_assets/entry.md
|
|
8
|
+
load_policy: required_inline
|
|
9
|
+
|
|
10
|
+
required_fragments:
|
|
11
|
+
- id: batch_regression_workflow
|
|
12
|
+
xid: xid-fragment-batch-regression-workflow
|
|
13
|
+
path: skill_assets/references/workflow.md
|
|
14
|
+
load_policy: required_inline
|
|
15
|
+
- id: batch_regression_adapter_boundary
|
|
16
|
+
xid: xid-fragment-batch-regression-adapter-boundary
|
|
17
|
+
path: skill_assets/references/adapter-contract.md
|
|
18
|
+
load_policy: required_inline
|
|
19
|
+
|
|
20
|
+
branches: []
|
|
21
|
+
|
|
22
|
+
required_outputs:
|
|
23
|
+
- decision_table
|
|
24
|
+
- orthogonal_table
|
|
25
|
+
- regression_report
|
|
26
|
+
- evidence
|
|
27
|
+
- unknowns
|
|
28
|
+
- human_handoffs
|
|
29
|
+
|
|
30
|
+
required_knowledge: []
|
|
31
|
+
review_axes: []
|
|
32
|
+
schemas: []
|
|
33
|
+
|
|
34
|
+
must_not:
|
|
35
|
+
- treat_source_conditions_as_business_truth
|
|
36
|
+
- treat_baseline_results_as_business_correctness
|
|
37
|
+
- execute_against_production
|
|
38
|
+
- auto_accept_unexplained_differences
|
|
39
|
+
- claim_dynamic_sql_is_resolved_without_runtime_evidence
|
|
40
|
+
|
|
41
|
+
extension_policy:
|
|
42
|
+
can_be_extended_by_local_skill: true
|
|
43
|
+
local_can_weaken_required_outputs: false
|
|
44
|
+
local_can_override_must_not: false
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: xrefkit-skills-batch-regression
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: XRefKit Skill Package for C# and SQL Server batch impact analysis and combination regression
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: xrefkit<0.5.0,>=0.4.0
|
|
8
|
+
|
|
9
|
+
# xrefkit-skills-batch-regression
|
|
10
|
+
|
|
11
|
+
XRefKit Skill Package v0.4.1 for impact analysis and combination regression of
|
|
12
|
+
existing C# batches backed by SQL Server stored procedures.
|
|
13
|
+
|
|
14
|
+
The package provides a discoverable XRefKit v2 Skill Package and bundles the
|
|
15
|
+
repository-native Skill procedure, deterministic combination/result tools,
|
|
16
|
+
source condition extraction, configuration references, and synthetic fixtures.
|
|
17
|
+
Real batch and database execution still requires an isolated adapter supplied
|
|
18
|
+
by the consuming project.
|
|
19
|
+
|
|
20
|
+
Install:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
python -m pip install xrefkit-skills-batch-regression==0.4.1
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The package is discovered through the `xrefkit.skill_packages` entry-point
|
|
27
|
+
group and includes the deterministic tools under `skill_assets/scripts/`.
|
xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/SOURCES.txt
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/xrefkit_skills_batch_regression/__init__.py
|
|
4
|
+
src/xrefkit_skills_batch_regression/cli.py
|
|
5
|
+
src/xrefkit_skills_batch_regression/package_manifest.yaml
|
|
6
|
+
src/xrefkit_skills_batch_regression.egg-info/PKG-INFO
|
|
7
|
+
src/xrefkit_skills_batch_regression.egg-info/SOURCES.txt
|
|
8
|
+
src/xrefkit_skills_batch_regression.egg-info/dependency_links.txt
|
|
9
|
+
src/xrefkit_skills_batch_regression.egg-info/entry_points.txt
|
|
10
|
+
src/xrefkit_skills_batch_regression.egg-info/requires.txt
|
|
11
|
+
src/xrefkit_skills_batch_regression.egg-info/top_level.txt
|
|
12
|
+
src/xrefkit_skills_batch_regression/skill_assets/entry.md
|
|
13
|
+
src/xrefkit_skills_batch_regression/skill_assets/fixtures/config.json
|
|
14
|
+
src/xrefkit_skills_batch_regression/skill_assets/fixtures/new-results.json
|
|
15
|
+
src/xrefkit_skills_batch_regression/skill_assets/fixtures/old-results.json
|
|
16
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/adapter-contract.md
|
|
17
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/code-table-extraction.md
|
|
18
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/config-schema.md
|
|
19
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/config.template.json
|
|
20
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/csharp-sql-analysis.md
|
|
21
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/fixture-notes.md
|
|
22
|
+
src/xrefkit_skills_batch_regression/skill_assets/references/workflow.md
|
|
23
|
+
src/xrefkit_skills_batch_regression/skill_assets/scripts/batch_regression.py
|
|
24
|
+
src/xrefkit_skills_batch_regression/skill_assets/scripts/code_tables.py
|
|
25
|
+
src/xrefkit_skills_batch_regression/skills/batch_impact_regression.skill.yaml
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/requires.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
xrefkit<0.5.0,>=0.4.0
|
xrefkit_skills_batch_regression-0.4.1/src/xrefkit_skills_batch_regression.egg-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
xrefkit_skills_batch_regression
|