xrefkit 0.4.0__tar.gz → 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-0.4.0 → xrefkit-0.4.1}/PKG-INFO +14 -2
- {xrefkit-0.4.0 → xrefkit-0.4.1}/README.md +13 -1
- {xrefkit-0.4.0 → xrefkit-0.4.1}/pyproject.toml +1 -1
- xrefkit-0.4.1/tests/test_instruction_workflow.py +100 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/__init__.py +1 -1
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/cli.py +2 -1
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/operations_cli.py +33 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/skillrun.py +140 -8
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit.egg-info/PKG-INFO +14 -2
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit.egg-info/SOURCES.txt +1 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/LICENSE +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/setup.cfg +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_base_sync_ownership.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_boundary_analysis.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_calibration_lint.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_check_skill_knowledge_xids.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_cli.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_collect_analyzer_sarif.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_convert_to_xrefkit_skill.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_cs_scope_probe.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_csharp_commonality.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_csharp_naming_profile.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_ctx.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_cutover_readiness.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_dashboard.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_error_policy_audit.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_error_policy_locator.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_fm_multiroot.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_gate.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_goal_desired_state.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_knowledge_relations_validator.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_ownership.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_packmeta.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_project_quality_baseline.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_resource_provider.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_runtime_contracts.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_sarif_to_locator.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_skill_runtime_audit.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_skillmeta.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_structure_catalog.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_xref.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_xrefkit_instance.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_xrefkit_tools.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_xrefkit_v2_discovery.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_xrefkit_v2_models.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/tests/test_xrefkit_v2_pipeline.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/__main__.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/boundary_analysis.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/catalog_cli.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/contracts.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/ctx.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/dashboard.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/discovery.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/gate.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/goalstate.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/hashing.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/import_skill.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/instance.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/loaders.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/__init__.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/audit.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/bootstrap.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/catalog.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/cli.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/client_cache.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/context_registry.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/contracts.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/dist.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/ownership.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/repository.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/schemas.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/server.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp/startup_contract_pack.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/mcp_tools.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/__init__.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/common.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/effective_bundle.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/local_manifest.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/package_manifest.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/run_log.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/server_config.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/models/skill_definition.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/ownership.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/packmeta.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/registry.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resolver.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resource_provider.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/contracts.json +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/current.json +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/7a682a5272907354/contracts.json +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/7a682a5272907354/model_body.md +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/9929294385ccb7b0/contracts.json +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/9929294385ccb7b0/model_body.md +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/model_body.md +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/runlog.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/skillmeta.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/structure_catalog.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/tools/__init__.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/tools/__main__.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/v2_cli.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/workspace.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/xref.py +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit.egg-info/dependency_links.txt +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit.egg-info/entry_points.txt +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit.egg-info/requires.txt +0 -0
- {xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xrefkit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit
|
|
5
5
|
Author: synthaicode
|
|
6
6
|
License: MIT License
|
|
@@ -91,7 +91,7 @@ XRefKit makes AI work explicit by separating:
|
|
|
91
91
|
|
|
92
92
|
- Skills: executable work units, each identified by a capability/tuning/responsibility triad and carrying its execution and check contract
|
|
93
93
|
- Knowledge: source-backed domain facts and local rules loaded only when needed
|
|
94
|
-
- Workflow protocol: the generic, deterministic
|
|
94
|
+
- Workflow protocol: the generic, deterministic control for Skill-backed and instruction-backed runs (phases, verification, closure)
|
|
95
95
|
- Semantic routing: selecting the right Skill for a goal from user intent and the Skill catalog
|
|
96
96
|
- Evidence: logs, judgments, concerns, and quality checks
|
|
97
97
|
- XIDs: stable references that survive file movement and restructuring so AI can load targeted context without treating the whole repository as one prompt
|
|
@@ -109,6 +109,18 @@ and handoff records from collapsing into one opaque instruction block.
|
|
|
109
109
|
4. Agents are routed semantically to the right Skill and load only the relevant context.
|
|
110
110
|
5. Evidence and quality gates make incomplete or unsupported work visible.
|
|
111
111
|
|
|
112
|
+
When an instruction has no matching Skill, open an instruction-backed workflow
|
|
113
|
+
run explicitly. The run requires either user-supplied procedural completion
|
|
114
|
+
conditions or an explicit opt-in to the repository defaults:
|
|
115
|
+
|
|
116
|
+
```powershell
|
|
117
|
+
xrefkit workflow run --task "Perform the requested procedure" `
|
|
118
|
+
--use-default-completion-conditions --json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`verify` and `close` determine procedural completion only. Output quality is
|
|
122
|
+
recorded separately after human acceptance with the existing feedback record.
|
|
123
|
+
|
|
112
124
|
## Quick Start
|
|
113
125
|
|
|
114
126
|
Install the package and initialize an instance:
|
|
@@ -52,7 +52,7 @@ XRefKit makes AI work explicit by separating:
|
|
|
52
52
|
|
|
53
53
|
- Skills: executable work units, each identified by a capability/tuning/responsibility triad and carrying its execution and check contract
|
|
54
54
|
- Knowledge: source-backed domain facts and local rules loaded only when needed
|
|
55
|
-
- Workflow protocol: the generic, deterministic
|
|
55
|
+
- Workflow protocol: the generic, deterministic control for Skill-backed and instruction-backed runs (phases, verification, closure)
|
|
56
56
|
- Semantic routing: selecting the right Skill for a goal from user intent and the Skill catalog
|
|
57
57
|
- Evidence: logs, judgments, concerns, and quality checks
|
|
58
58
|
- XIDs: stable references that survive file movement and restructuring so AI can load targeted context without treating the whole repository as one prompt
|
|
@@ -70,6 +70,18 @@ and handoff records from collapsing into one opaque instruction block.
|
|
|
70
70
|
4. Agents are routed semantically to the right Skill and load only the relevant context.
|
|
71
71
|
5. Evidence and quality gates make incomplete or unsupported work visible.
|
|
72
72
|
|
|
73
|
+
When an instruction has no matching Skill, open an instruction-backed workflow
|
|
74
|
+
run explicitly. The run requires either user-supplied procedural completion
|
|
75
|
+
conditions or an explicit opt-in to the repository defaults:
|
|
76
|
+
|
|
77
|
+
```powershell
|
|
78
|
+
xrefkit workflow run --task "Perform the requested procedure" `
|
|
79
|
+
--use-default-completion-conditions --json
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`verify` and `close` determine procedural completion only. Output quality is
|
|
83
|
+
recorded separately after human acceptance with the existing feedback record.
|
|
84
|
+
|
|
73
85
|
## Quick Start
|
|
74
86
|
|
|
75
87
|
Install the package and initialize an instance:
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import io
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from xrefkit.__main__ import main
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _run(root: Path, *args: str) -> int:
|
|
10
|
+
with contextlib.redirect_stdout(io.StringIO()):
|
|
11
|
+
argv = list(args)
|
|
12
|
+
if argv[:2] == ["workflow", "run"]:
|
|
13
|
+
argv.extend(["--root", str(root)])
|
|
14
|
+
return main(argv)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_instruction_workflow_requires_completion_conditions(tmp_path: Path) -> None:
|
|
18
|
+
out = tmp_path / "work" / "sessions" / "run.md"
|
|
19
|
+
assert _run(tmp_path, "workflow", "run", "--task", "Do work", "--out", str(out)) == 1
|
|
20
|
+
assert not out.exists()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_instruction_workflow_uses_default_conditions_and_shared_protocol(tmp_path: Path) -> None:
|
|
24
|
+
out = tmp_path / "work" / "sessions" / "run.md"
|
|
25
|
+
assert _run(
|
|
26
|
+
tmp_path,
|
|
27
|
+
"workflow",
|
|
28
|
+
"run",
|
|
29
|
+
"--task",
|
|
30
|
+
"Do work",
|
|
31
|
+
"--out",
|
|
32
|
+
str(out),
|
|
33
|
+
"--use-default-completion-conditions",
|
|
34
|
+
) == 0
|
|
35
|
+
text = out.read_text(encoding="utf-8")
|
|
36
|
+
assert "# Workflow Run Log" in text
|
|
37
|
+
assert "## Run Load Gate" in text
|
|
38
|
+
assert "- basis: `default`" in text
|
|
39
|
+
assert "- quality_policy: `human_acceptance`" in text
|
|
40
|
+
|
|
41
|
+
assert _run(
|
|
42
|
+
tmp_path,
|
|
43
|
+
"skill",
|
|
44
|
+
"workitem",
|
|
45
|
+
"--log",
|
|
46
|
+
str(out),
|
|
47
|
+
"--item",
|
|
48
|
+
"WI-001",
|
|
49
|
+
"--text",
|
|
50
|
+
"Perform the instruction",
|
|
51
|
+
"--status",
|
|
52
|
+
"done",
|
|
53
|
+
"--role",
|
|
54
|
+
"instruction:executor",
|
|
55
|
+
) == 0
|
|
56
|
+
for artifact_id, kind, target, role in (
|
|
57
|
+
("OUT-001", "output", "output.md", "instruction:executor"),
|
|
58
|
+
("EVD-001", "evidence", "test command", "instruction:checker"),
|
|
59
|
+
):
|
|
60
|
+
assert _run(
|
|
61
|
+
tmp_path,
|
|
62
|
+
"skill",
|
|
63
|
+
"artifact",
|
|
64
|
+
"--log",
|
|
65
|
+
str(out),
|
|
66
|
+
"--artifact",
|
|
67
|
+
artifact_id,
|
|
68
|
+
"--kind",
|
|
69
|
+
kind,
|
|
70
|
+
"--target",
|
|
71
|
+
target,
|
|
72
|
+
"--item",
|
|
73
|
+
"WI-001",
|
|
74
|
+
"--status",
|
|
75
|
+
"done",
|
|
76
|
+
"--role",
|
|
77
|
+
role,
|
|
78
|
+
) == 0
|
|
79
|
+
assert _run(tmp_path, "skill", "phase", "--log", str(out), "--phase", "execution", "--status", "done", "--role", "instruction:executor") == 0
|
|
80
|
+
assert _run(tmp_path, "skill", "phase", "--log", str(out), "--phase", "handoff", "--status", "done", "--role", "instruction:handoff_owner") == 0
|
|
81
|
+
assert _run(tmp_path, "skill", "verify", "--log", str(out)) == 0
|
|
82
|
+
|
|
83
|
+
# Quality is a human decision and is recorded separately from progression.
|
|
84
|
+
assert _run(
|
|
85
|
+
tmp_path,
|
|
86
|
+
"skill",
|
|
87
|
+
"feedback",
|
|
88
|
+
"--log",
|
|
89
|
+
str(out),
|
|
90
|
+
"--kind",
|
|
91
|
+
"human",
|
|
92
|
+
"--status",
|
|
93
|
+
"accepted",
|
|
94
|
+
"--target",
|
|
95
|
+
"OUT-001",
|
|
96
|
+
"--note",
|
|
97
|
+
"human accepted output quality",
|
|
98
|
+
) == 0
|
|
99
|
+
assert _run(tmp_path, "skill", "close", "--log", str(out)) == 0
|
|
100
|
+
assert "## Completion Conditions" in out.read_text(encoding="utf-8")
|
|
@@ -6,7 +6,7 @@ import sys
|
|
|
6
6
|
from collections.abc import Sequence
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
_OPERATIONS = {"xref", "ctx", "goal", "gate", "pack", "dashboard", "analysis", "skill"}
|
|
9
|
+
_OPERATIONS = {"xref", "ctx", "goal", "gate", "pack", "dashboard", "analysis", "skill", "workflow"}
|
|
10
10
|
_V2 = {"package", "show"}
|
|
11
11
|
|
|
12
12
|
|
|
@@ -18,6 +18,7 @@ def _print_help() -> None:
|
|
|
18
18
|
" xref manage XIDs and references\n"
|
|
19
19
|
" ctx build compact context packs\n"
|
|
20
20
|
" skill discover, validate, run, verify, and close Skills\n"
|
|
21
|
+
" workflow run the generic protocol for instructions without a Skill\n"
|
|
21
22
|
" tools list and run XID-backed client tools\n"
|
|
22
23
|
" catalog list and maintain Knowledge and structure catalogs\n"
|
|
23
24
|
" pack validate and build runtime/content packs\n"
|
|
@@ -574,6 +574,33 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
574
574
|
p_skill_verify.add_argument("--note", default=None, help="Optional check event note")
|
|
575
575
|
p_skill_verify.add_argument("--json", action="store_true", help="Emit JSON")
|
|
576
576
|
|
|
577
|
+
workflow = subparsers.add_parser(
|
|
578
|
+
"workflow",
|
|
579
|
+
help="Run the generic workflow protocol for an instruction without a Skill",
|
|
580
|
+
)
|
|
581
|
+
workflow_sub = workflow.add_subparsers(dest="workflow_cmd", required=True)
|
|
582
|
+
p_workflow_run = workflow_sub.add_parser(
|
|
583
|
+
"run",
|
|
584
|
+
help="Open an instruction-backed workflow run with explicit or default completion conditions",
|
|
585
|
+
)
|
|
586
|
+
p_workflow_run.add_argument("--root", default=".", help="Project root (default: .)")
|
|
587
|
+
p_workflow_run.add_argument("--task", default=None, help="Instruction text")
|
|
588
|
+
p_workflow_run.add_argument("--task-file", default=None, help="Read instruction text from a UTF-8 file")
|
|
589
|
+
p_workflow_run.add_argument("--out", default=None, help="Write workflow run log to this path")
|
|
590
|
+
p_workflow_run.add_argument("--run-id", default=None, help="Caller-supplied UUID")
|
|
591
|
+
p_workflow_run.add_argument(
|
|
592
|
+
"--completion-condition",
|
|
593
|
+
action="append",
|
|
594
|
+
default=[],
|
|
595
|
+
help="Explicit procedural completion condition; may be repeated",
|
|
596
|
+
)
|
|
597
|
+
p_workflow_run.add_argument(
|
|
598
|
+
"--use-default-completion-conditions",
|
|
599
|
+
action="store_true",
|
|
600
|
+
help="Use the repository's procedural completion conditions when the instruction omits them",
|
|
601
|
+
)
|
|
602
|
+
p_workflow_run.add_argument("--json", action="store_true", help="Emit JSON")
|
|
603
|
+
|
|
577
604
|
return parser
|
|
578
605
|
|
|
579
606
|
|
|
@@ -675,6 +702,12 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
675
702
|
|
|
676
703
|
return cmd_skill(args)
|
|
677
704
|
|
|
705
|
+
if args.command == "workflow":
|
|
706
|
+
if args.workflow_cmd == "run":
|
|
707
|
+
from xrefkit.skillrun import cmd_workflow_run
|
|
708
|
+
|
|
709
|
+
return cmd_workflow_run(args)
|
|
710
|
+
|
|
678
711
|
if args.command == "pack":
|
|
679
712
|
if args.pack_cmd == "list":
|
|
680
713
|
from xrefkit.packmeta import cmd_pack_list
|
|
@@ -748,6 +748,18 @@ def _log_skill_id(text: str) -> str | None:
|
|
|
748
748
|
return text[start:end]
|
|
749
749
|
|
|
750
750
|
|
|
751
|
+
def _has_opened_run_gate(text: str) -> bool:
|
|
752
|
+
"""Return whether this log was opened by a supported workflow runner.
|
|
753
|
+
|
|
754
|
+
Skill runs retain their historical gate text. Instruction-backed workflow
|
|
755
|
+
runs use the generic gate text, but share the same progression machinery.
|
|
756
|
+
"""
|
|
757
|
+
return (
|
|
758
|
+
"## Skill Load Gate\n\n- status: `opened_by_xrefkit_skill_run`" in text
|
|
759
|
+
or "## Run Load Gate\n\n- status: `opened_by_xrefkit_workflow_run`" in text
|
|
760
|
+
)
|
|
761
|
+
|
|
762
|
+
|
|
751
763
|
def _log_model_tier(text: str) -> str | None:
|
|
752
764
|
prefix = "- model_tier: `"
|
|
753
765
|
start = text.find(prefix)
|
|
@@ -884,7 +896,7 @@ def update_work_item(args) -> SkillRunResult:
|
|
|
884
896
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["missing --role"])
|
|
885
897
|
|
|
886
898
|
text = log_path.read_text(encoding="utf-8")
|
|
887
|
-
if
|
|
899
|
+
if not _has_opened_run_gate(text):
|
|
888
900
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["skill run log is missing an opened Skill Load Gate"])
|
|
889
901
|
|
|
890
902
|
items = _parse_work_items(text)
|
|
@@ -1004,7 +1016,7 @@ def update_artifact(args) -> SkillRunResult:
|
|
|
1004
1016
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["missing --role"])
|
|
1005
1017
|
|
|
1006
1018
|
text = log_path.read_text(encoding="utf-8")
|
|
1007
|
-
if
|
|
1019
|
+
if not _has_opened_run_gate(text):
|
|
1008
1020
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["skill run log is missing an opened Skill Load Gate"])
|
|
1009
1021
|
|
|
1010
1022
|
artifacts = _parse_artifacts(text)
|
|
@@ -1140,7 +1152,7 @@ def update_concern(args) -> SkillRunResult:
|
|
|
1140
1152
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["missing --role"])
|
|
1141
1153
|
|
|
1142
1154
|
text = log_path.read_text(encoding="utf-8")
|
|
1143
|
-
if
|
|
1155
|
+
if not _has_opened_run_gate(text):
|
|
1144
1156
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["skill run log is missing an opened Skill Load Gate"])
|
|
1145
1157
|
|
|
1146
1158
|
concerns = _parse_concerns(text)
|
|
@@ -1388,7 +1400,7 @@ def _validate_handoff_sources(root: Path, source_logs: list[str]) -> tuple[list[
|
|
|
1388
1400
|
errors.append(f"handoff source log not found: {source_path}")
|
|
1389
1401
|
continue
|
|
1390
1402
|
text = source_path.read_text(encoding="utf-8")
|
|
1391
|
-
if
|
|
1403
|
+
if not _has_opened_run_gate(text):
|
|
1392
1404
|
errors.append(f"handoff source log was not opened by xrefkit skill run: {source_path}")
|
|
1393
1405
|
continue
|
|
1394
1406
|
closure_status = _section_status(text, "Closure Gate")
|
|
@@ -1463,7 +1475,7 @@ def verify_progression_run(args) -> SkillRunResult:
|
|
|
1463
1475
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=None, errors=[f"log not found: {log_path}"])
|
|
1464
1476
|
|
|
1465
1477
|
text = log_path.read_text(encoding="utf-8")
|
|
1466
|
-
if
|
|
1478
|
+
if not _has_opened_run_gate(text):
|
|
1467
1479
|
return SkillRunResult(
|
|
1468
1480
|
ok=False,
|
|
1469
1481
|
skill_id=None,
|
|
@@ -1512,7 +1524,7 @@ def close_skill_run(args) -> SkillRunResult:
|
|
|
1512
1524
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=None, errors=[f"log not found: {log_path}"])
|
|
1513
1525
|
|
|
1514
1526
|
text = log_path.read_text(encoding="utf-8")
|
|
1515
|
-
if
|
|
1527
|
+
if not _has_opened_run_gate(text):
|
|
1516
1528
|
return SkillRunResult(
|
|
1517
1529
|
ok=False,
|
|
1518
1530
|
skill_id=None,
|
|
@@ -1663,7 +1675,7 @@ def _validate_observation_log(log_path: Path) -> tuple[str | None, SkillRunResul
|
|
|
1663
1675
|
run_log=str(log_path),
|
|
1664
1676
|
errors=[f"could not read skill run log: {exc}"],
|
|
1665
1677
|
)
|
|
1666
|
-
if
|
|
1678
|
+
if not _has_opened_run_gate(text):
|
|
1667
1679
|
return None, SkillRunResult(
|
|
1668
1680
|
ok=False,
|
|
1669
1681
|
skill_id=None,
|
|
@@ -2003,7 +2015,7 @@ def update_token_usage(args) -> SkillRunResult:
|
|
|
2003
2015
|
)
|
|
2004
2016
|
|
|
2005
2017
|
text = log_path.read_text(encoding="utf-8")
|
|
2006
|
-
if
|
|
2018
|
+
if not _has_opened_run_gate(text):
|
|
2007
2019
|
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=str(log_path), errors=["skill run log is missing an opened Skill Load Gate"])
|
|
2008
2020
|
|
|
2009
2021
|
total_tokens = total_arg if total_arg is not None else (input_tokens or 0) + (output_tokens or 0)
|
|
@@ -2225,6 +2237,126 @@ def run_skill(args) -> SkillRunResult:
|
|
|
2225
2237
|
)
|
|
2226
2238
|
|
|
2227
2239
|
|
|
2240
|
+
DEFAULT_INSTRUCTION_COMPLETION_CONDITIONS = (
|
|
2241
|
+
"all concrete work items are done or escalated",
|
|
2242
|
+
"an output artifact and an evidence artifact are recorded",
|
|
2243
|
+
"unknowns and risks are resolved or escalated",
|
|
2244
|
+
"execution, check, and handoff phases are complete or escalated",
|
|
2245
|
+
)
|
|
2246
|
+
|
|
2247
|
+
|
|
2248
|
+
def run_workflow_instruction(args) -> SkillRunResult:
|
|
2249
|
+
"""Open a generic workflow run for an instruction without a Skill.
|
|
2250
|
+
|
|
2251
|
+
This intentionally creates the same run-log shape consumed by the
|
|
2252
|
+
progression commands. It does not infer business quality; that remains a
|
|
2253
|
+
human acceptance decision recorded separately with ``skill feedback``.
|
|
2254
|
+
"""
|
|
2255
|
+
root = Path(args.root).resolve()
|
|
2256
|
+
task, task_errors = _read_task(args)
|
|
2257
|
+
if task_errors:
|
|
2258
|
+
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=None, errors=task_errors)
|
|
2259
|
+
|
|
2260
|
+
explicit = [str(value).strip() for value in getattr(args, "completion_condition", []) if str(value).strip()]
|
|
2261
|
+
use_default = bool(getattr(args, "use_default_completion_conditions", False))
|
|
2262
|
+
if not explicit and not use_default:
|
|
2263
|
+
return SkillRunResult(
|
|
2264
|
+
ok=False,
|
|
2265
|
+
skill_id=None,
|
|
2266
|
+
skill_doc=None,
|
|
2267
|
+
run_log=None,
|
|
2268
|
+
errors=[
|
|
2269
|
+
"completion conditions are required; provide --completion-condition or explicitly opt into --use-default-completion-conditions"
|
|
2270
|
+
],
|
|
2271
|
+
)
|
|
2272
|
+
conditions = explicit or list(DEFAULT_INSTRUCTION_COMPLETION_CONDITIONS)
|
|
2273
|
+
basis = "explicit" if explicit else "default"
|
|
2274
|
+
|
|
2275
|
+
raw_run_id = str(getattr(args, "run_id", None) or uuid.uuid4())
|
|
2276
|
+
try:
|
|
2277
|
+
run_id = str(uuid.UUID(raw_run_id))
|
|
2278
|
+
except ValueError:
|
|
2279
|
+
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=None, errors=[f"run_id must be a UUID: {raw_run_id}"])
|
|
2280
|
+
|
|
2281
|
+
out_path = Path(args.out) if args.out else _default_log_path(root, "instruction")
|
|
2282
|
+
if not out_path.is_absolute():
|
|
2283
|
+
out_path = root / out_path
|
|
2284
|
+
sessions_dir = root / "work" / "sessions"
|
|
2285
|
+
if sessions_dir.exists():
|
|
2286
|
+
for existing_log in sessions_dir.rglob("*.md"):
|
|
2287
|
+
try:
|
|
2288
|
+
existing_text = existing_log.read_text(encoding="utf-8")
|
|
2289
|
+
except (OSError, UnicodeError):
|
|
2290
|
+
continue
|
|
2291
|
+
if _log_field(existing_text, "run_id") == run_id:
|
|
2292
|
+
return SkillRunResult(ok=False, skill_id=None, skill_doc=None, run_log=None, errors=[f"run_id is already used by an existing workflow run: {existing_log}"])
|
|
2293
|
+
|
|
2294
|
+
assigned_roles = _assign_runtime_roles(skill_id="instruction", execution_mode="local_default", model_tier=None)
|
|
2295
|
+
log = _render_log(
|
|
2296
|
+
run_id=run_id,
|
|
2297
|
+
skill_id="instruction",
|
|
2298
|
+
maturity="not_applicable",
|
|
2299
|
+
meta_path=Path("-") ,
|
|
2300
|
+
skill_doc=Path("-"),
|
|
2301
|
+
execution_mode="local_default",
|
|
2302
|
+
guard_policy="required",
|
|
2303
|
+
capability_layering="not_applicable",
|
|
2304
|
+
workflow_protocol="required",
|
|
2305
|
+
capability="instruction execution",
|
|
2306
|
+
tuning="generic procedural completion",
|
|
2307
|
+
role_responsibilities={"executor": "execute the user instruction"},
|
|
2308
|
+
capability_refs=[],
|
|
2309
|
+
assigned_roles=assigned_roles,
|
|
2310
|
+
task=str(task),
|
|
2311
|
+
os_contract=dict(REQUIRED_OS_CONTRACT),
|
|
2312
|
+
handoff_sources=[],
|
|
2313
|
+
model_tier=None,
|
|
2314
|
+
domain_knowledge={"available": [], "selected": {}, "requirements": []},
|
|
2315
|
+
)
|
|
2316
|
+
log = log.replace("# Skill Run Log", "# Workflow Run Log", 1)
|
|
2317
|
+
log = log.replace("## Skill Load Gate", "## Run Load Gate", 1)
|
|
2318
|
+
log = log.replace("opened_by_xrefkit_skill_run", "opened_by_xrefkit_workflow_run", 1)
|
|
2319
|
+
log = log.replace("- rule: do not open or execute the Skill procedure until this runtime envelope exists", "- rule: do not treat the instruction as procedurally complete until this workflow envelope closes", 1)
|
|
2320
|
+
log = log.replace("## Skill Routing Trace", "## Instruction Routing Trace", 1)
|
|
2321
|
+
condition_lines = [
|
|
2322
|
+
"## Completion Conditions",
|
|
2323
|
+
"",
|
|
2324
|
+
f"- basis: `{basis}`",
|
|
2325
|
+
"- quality_policy: `human_acceptance`",
|
|
2326
|
+
"- rule: workflow verification checks procedural records; a human confirms output quality separately",
|
|
2327
|
+
] + [f"- condition: {condition.replace('`', "'")}" for condition in conditions]
|
|
2328
|
+
marker = "\n## Startup Inputs\n"
|
|
2329
|
+
log = log.replace(marker, "\n" + "\n".join(condition_lines) + "\n" + marker, 1)
|
|
2330
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
2331
|
+
with _LogFileLock(out_path.with_name(f".{out_path.name}.lock")):
|
|
2332
|
+
_atomic_write_text(out_path, log)
|
|
2333
|
+
return SkillRunResult(
|
|
2334
|
+
ok=True,
|
|
2335
|
+
skill_id="instruction",
|
|
2336
|
+
skill_doc=None,
|
|
2337
|
+
run_log=str(out_path),
|
|
2338
|
+
errors=[],
|
|
2339
|
+
assigned_roles=assigned_roles,
|
|
2340
|
+
run_id=run_id,
|
|
2341
|
+
)
|
|
2342
|
+
|
|
2343
|
+
|
|
2344
|
+
def cmd_workflow_run(args) -> int:
|
|
2345
|
+
result = run_workflow_instruction(args)
|
|
2346
|
+
if args.json:
|
|
2347
|
+
print(json.dumps(result.to_dict(), ensure_ascii=False, indent=2))
|
|
2348
|
+
elif result.ok:
|
|
2349
|
+
print(f"ok: {result.run_log}")
|
|
2350
|
+
print(f" run_id: {result.run_id}")
|
|
2351
|
+
print(" run_type: instruction")
|
|
2352
|
+
print(" next: add work items, record artifacts/evidence, verify, human-accept output, then close")
|
|
2353
|
+
else:
|
|
2354
|
+
print("fail: workflow run")
|
|
2355
|
+
for error in result.errors:
|
|
2356
|
+
print(f" error: {error}")
|
|
2357
|
+
return 0 if result.ok else 1
|
|
2358
|
+
|
|
2359
|
+
|
|
2228
2360
|
def cmd_skill_run(args) -> int:
|
|
2229
2361
|
result = run_skill(args)
|
|
2230
2362
|
if args.json:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xrefkit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Portable XID, Skill, Knowledge, workflow, and MCP runtime for XRefKit
|
|
5
5
|
Author: synthaicode
|
|
6
6
|
License: MIT License
|
|
@@ -91,7 +91,7 @@ XRefKit makes AI work explicit by separating:
|
|
|
91
91
|
|
|
92
92
|
- Skills: executable work units, each identified by a capability/tuning/responsibility triad and carrying its execution and check contract
|
|
93
93
|
- Knowledge: source-backed domain facts and local rules loaded only when needed
|
|
94
|
-
- Workflow protocol: the generic, deterministic
|
|
94
|
+
- Workflow protocol: the generic, deterministic control for Skill-backed and instruction-backed runs (phases, verification, closure)
|
|
95
95
|
- Semantic routing: selecting the right Skill for a goal from user intent and the Skill catalog
|
|
96
96
|
- Evidence: logs, judgments, concerns, and quality checks
|
|
97
97
|
- XIDs: stable references that survive file movement and restructuring so AI can load targeted context without treating the whole repository as one prompt
|
|
@@ -109,6 +109,18 @@ and handoff records from collapsing into one opaque instruction block.
|
|
|
109
109
|
4. Agents are routed semantically to the right Skill and load only the relevant context.
|
|
110
110
|
5. Evidence and quality gates make incomplete or unsupported work visible.
|
|
111
111
|
|
|
112
|
+
When an instruction has no matching Skill, open an instruction-backed workflow
|
|
113
|
+
run explicitly. The run requires either user-supplied procedural completion
|
|
114
|
+
conditions or an explicit opt-in to the repository defaults:
|
|
115
|
+
|
|
116
|
+
```powershell
|
|
117
|
+
xrefkit workflow run --task "Perform the requested procedure" `
|
|
118
|
+
--use-default-completion-conditions --json
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`verify` and `close` determine procedural completion only. Output quality is
|
|
122
|
+
recorded separately after human acceptance with the existing feedback record.
|
|
123
|
+
|
|
112
124
|
## Quick Start
|
|
113
125
|
|
|
114
126
|
Install the package and initialize an instance:
|
|
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
|
|
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
|
{xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/7a682a5272907354/contracts.json
RENAMED
|
File without changes
|
{xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/7a682a5272907354/model_body.md
RENAMED
|
File without changes
|
{xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/9929294385ccb7b0/contracts.json
RENAMED
|
File without changes
|
{xrefkit-0.4.0 → xrefkit-0.4.1}/xrefkit/resources/base/generations/9929294385ccb7b0/model_body.md
RENAMED
|
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
|