generated from coulomb/repo-seed
command parity and migration guide
This commit is contained in:
@@ -27,6 +27,9 @@ Start with:
|
||||
- `docs/legacy-infospace-feature-inventory.md`
|
||||
- `docs/successor-boundary-interface-map.md`
|
||||
- `docs/replacement-acceptance-matrix.md`
|
||||
- `docs/legacy-command-parity.md`
|
||||
- `docs/legacy-infospace-migration-guide.md`
|
||||
- `docs/replacement-readiness-decision.md`
|
||||
- `infospaces/bootstrap-pilot/`
|
||||
- `infospaces/wealth-vsm-legacy-slice/`
|
||||
- `workplans/`
|
||||
|
||||
89
docs/legacy-command-parity.md
Normal file
89
docs/legacy-command-parity.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Legacy Command Parity
|
||||
|
||||
Date: 2026-05-14
|
||||
|
||||
## Purpose
|
||||
|
||||
This guide maps the legacy `markitect infospace` command surface to the
|
||||
successor shape in `infospace-bench`, `markitect-tool`, and
|
||||
`kontextual-engine`.
|
||||
|
||||
The goal is replacement readiness for in-scope infospace work, not a
|
||||
name-for-name CLI clone. `infospace-bench` keeps concrete infospaces,
|
||||
application semantics, evaluation history, and file-backed workflow fixtures.
|
||||
`markitect-tool` owns markdown parsing and validation primitives.
|
||||
`kontextual-engine` owns durable asset, graph, retrieval, audit, and workflow
|
||||
runtime concerns when those move beyond file-backed operation.
|
||||
|
||||
## Status Values
|
||||
|
||||
- `replaced`: use the successor command directly.
|
||||
- `reframed`: the behavior exists, but the user flow has a cleaner successor
|
||||
shape.
|
||||
- `delegated`: the behavior belongs in a sibling repo and is consumed through
|
||||
an adapter or contract.
|
||||
- `deferred`: still in scope, but not required for the current replacement
|
||||
gate.
|
||||
- `retired`: the legacy behavior should not be rebuilt.
|
||||
|
||||
## Command Map
|
||||
|
||||
| Legacy command | Status | Successor command or API | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| `markitect infospace init` | replaced | `infospace-bench create <workspace> <slug> --name "<name>" --topic-domain "<domain>"` | Creates the file-backed `infospaces/<slug>/` layout and manifest. |
|
||||
| `markitect infospace status` | replaced | `infospace-bench status <root>` | JSON summary of config, artifact counts, parsed entities/relations, metrics, viability, history, and graph counts. |
|
||||
| `markitect infospace entities` | replaced | `infospace-bench entities <root>` or `infospace_bench.semantics.list_entities(root)` | Entity semantics are bench-owned and markdown parsing is delegated to `markitect-tool`. |
|
||||
| `markitect infospace chapters` | reframed | `infospace-bench export <root>` plus workflow/source artifact inspection | The successor tracks sources as manifest artifacts instead of a chapter-only table. A richer source triage command is deferred. |
|
||||
| `markitect infospace evaluate` | reframed | `infospace-bench workflow plan <root> <workflow_id>` and explicit assisted adapters | Provider-specific LLM calls are no longer hidden in the app CLI. Assisted stages are auditable and require an explicit adapter. |
|
||||
| `markitect infospace eval-summary` | reframed | `infospace-bench history <root> --metric per_artifact_mean` and `infospace-bench status <root>` | Evaluation results are structured artifacts plus metrics history, not a one-off text table. |
|
||||
| `markitect infospace relations` | replaced | `infospace-bench relations <root>` | Relation triplets resolve endpoints against parsed entity artifacts. |
|
||||
| `markitect infospace classify` | deferred | `infospace-bench workflow plan/run <root> <classification_workflow>` | Classification remains in scope as an explicit workflow, but provider execution is not part of this readiness gate. |
|
||||
| `markitect infospace viability` | replaced | `infospace-bench viability <root>` | Evaluates configured thresholds from persisted metrics. |
|
||||
| `markitect infospace check` | replaced | `infospace-bench check <root>` | Runs deterministic collection checks, persists metrics, appends history, and writes viability output. |
|
||||
| `markitect infospace history` | replaced | `infospace-bench history <root>` or `infospace-bench history <root> --metric <name>` | Reads file-backed metric snapshots. |
|
||||
| `markitect infospace history-diff` | replaced | `infospace-bench history-diff <root> <before> <after>` | Diffs snapshots by ID or date reference. |
|
||||
| `markitect infospace bind-discipline` | deferred | Edit `infospace.yaml` `disciplines` or add a later composition command | The config model supports discipline bindings; operational composition checks are a follow-up in `infospace-bench`. |
|
||||
| `markitect infospace process` | reframed | `infospace-bench workflow inspect|plan|run <root> <workflow_id>` | Workflows are explicit declarations with deterministic template stages and auditable assisted stages. |
|
||||
| `markitect infospace stale-mappings` | deferred | Future workflow/engine provenance comparison | Digest and provenance data now exist; stale mapping policy needs a dedicated follow-up. |
|
||||
| `markitect infospace graph` | replaced | `infospace-bench graph <root> --format json` or `--format mermaid` | Exports the artifact relationship graph from manifest relationships. |
|
||||
|
||||
## Retired Legacy Shapes
|
||||
|
||||
- Direct provider-specific LLM execution hidden behind a generic app command.
|
||||
- Automatic git commits from infospace processing commands.
|
||||
- Legacy output-directory conventions that bypass the artifact manifest.
|
||||
- Parser and schema code duplicated inside the application repo.
|
||||
|
||||
## Replacement Examples
|
||||
|
||||
Create and inspect an infospace:
|
||||
|
||||
```bash
|
||||
infospace-bench create . wealth-vsm --name "Wealth through VSM" --topic-domain "Classical Economics"
|
||||
infospace-bench status infospaces/wealth-vsm
|
||||
```
|
||||
|
||||
Validate, check, and view viability:
|
||||
|
||||
```bash
|
||||
infospace-bench validate infospaces/wealth-vsm-legacy-slice
|
||||
infospace-bench check infospaces/wealth-vsm-legacy-slice
|
||||
infospace-bench viability infospaces/wealth-vsm-legacy-slice
|
||||
```
|
||||
|
||||
Inspect semantic artifacts and graph:
|
||||
|
||||
```bash
|
||||
infospace-bench entities infospaces/wealth-vsm-legacy-slice
|
||||
infospace-bench relations infospaces/wealth-vsm-legacy-slice
|
||||
infospace-bench graph infospaces/wealth-vsm-legacy-slice --format mermaid
|
||||
```
|
||||
|
||||
Run explicit workflows:
|
||||
|
||||
```bash
|
||||
infospace-bench workflow inspect infospaces/bootstrap-pilot
|
||||
infospace-bench workflow plan infospaces/bootstrap-pilot bootstrap-readiness
|
||||
infospace-bench workflow run infospaces/bootstrap-pilot bootstrap-readiness
|
||||
```
|
||||
|
||||
78
docs/legacy-infospace-migration-guide.md
Normal file
78
docs/legacy-infospace-migration-guide.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Legacy Infospace Migration Guide
|
||||
|
||||
Date: 2026-05-14
|
||||
|
||||
## Purpose
|
||||
|
||||
Use this guide when moving an in-scope legacy MarkiTect infospace into
|
||||
`infospace-bench`.
|
||||
|
||||
The successor split is intentionally orthogonal:
|
||||
|
||||
- `markitect-tool`: markdown parsing, section extraction, contracts, templates.
|
||||
- `infospace-bench`: concrete infospace layout, manifests, semantic entity and
|
||||
relation models, checks, viability, evaluation history, pilots, and reports.
|
||||
- `kontextual-engine`: durable assets, relationship indexes, retrieval,
|
||||
workflow runtime, permissions, and audit when file-backed operation is no
|
||||
longer enough.
|
||||
|
||||
## Migration Path
|
||||
|
||||
1. Create a successor workspace with `infospace-bench create`.
|
||||
2. Copy source material into `artifacts/sources/`.
|
||||
3. Register each source in `artifacts/index.yaml` with a stable artifact ID.
|
||||
4. Move only in-scope generated entities and relations into
|
||||
`artifacts/entities/` and `artifacts/relations/`.
|
||||
5. Add markdown contracts under `contracts/` when validation is needed, then
|
||||
point `infospace.yaml` `schemas` at those contracts.
|
||||
6. Convert legacy entity evaluation files to use `artifact_id` rather than
|
||||
entity-only slugs.
|
||||
7. Move metrics snapshots into `output/metrics/history.yaml` and current values
|
||||
into `output/metrics/metrics.yaml`.
|
||||
8. Express generation or review work as explicit workflow declarations in
|
||||
`infospace.yaml`.
|
||||
9. Use `infospace-bench engine plan-sync` to check the optional engine asset
|
||||
boundary before applying any durable sync.
|
||||
10. Write a migration report under `reports/` that names replaced, delegated,
|
||||
deferred, and retired behavior.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
```bash
|
||||
infospace-bench status <root>
|
||||
infospace-bench validate <root>
|
||||
infospace-bench entities <root>
|
||||
infospace-bench relations <root>
|
||||
infospace-bench check <root>
|
||||
infospace-bench viability <root>
|
||||
infospace-bench history <root>
|
||||
infospace-bench graph <root> --format mermaid
|
||||
infospace-bench engine plan-sync <root>
|
||||
```
|
||||
|
||||
## What Moves Where
|
||||
|
||||
| Legacy concern | Successor home | Migration note |
|
||||
| --- | --- | --- |
|
||||
| Markdown headings, frontmatter, contract checks | `markitect-tool` | Keep access through `infospace_bench.markdown_adapter`. |
|
||||
| Entity and relation semantics | `infospace-bench` | Keep domain concepts in file-backed artifacts and manifests. |
|
||||
| Evaluation files and metrics history | `infospace-bench` | Preserve history with `artifact_id` and deterministic metrics. |
|
||||
| LLM prompt execution | `infospace-bench` workflow boundary plus adapters | Plans must be dry-runnable; provider calls require explicit adapters. |
|
||||
| Durable asset identity and graph indexes | `kontextual-engine` | Use `engine plan-sync` and `engine sync --apply` when needed. |
|
||||
| Retrieval, permissions, audit | `kontextual-engine` | Do not recreate these inside `infospace-bench`. |
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Migrating every legacy generated file just because it exists.
|
||||
- Preserving legacy output directory names when manifest IDs are clearer.
|
||||
- Rebuilding provider-specific LLM wiring inside `infospace-bench`.
|
||||
- Recreating prompt/runtime infrastructure that belongs to `kontextual-engine`.
|
||||
- Treating `infospace-bench` as a markdown parser library.
|
||||
|
||||
## Pilot Pattern
|
||||
|
||||
The `infospaces/wealth-vsm-legacy-slice/` pilot is the reference pattern for a
|
||||
small legacy migration. It keeps a pruned source excerpt, two entities, one
|
||||
relation, one migrated evaluation, metrics/history fixtures, validation
|
||||
contracts, and a report that explains what was intentionally left behind.
|
||||
|
||||
@@ -29,7 +29,7 @@ considered a replacement for each in-scope legacy infospace behavior from
|
||||
| Track stale outputs | Digest/provenance comparison | Tests after workflow provenance exists | `IB-WP-0009` | deferred |
|
||||
| Persist durable assets | Optional engine-backed repository adapter | Dry-run sync tests and integration design | `IB-WP-0010` | boundary done |
|
||||
| Run a legacy-derived pilot | Pruned `infospace-with-history` migration | Pilot corpus, migration report, parity comparison | `IB-WP-0011` | done |
|
||||
| Provide command migration path | Legacy command parity guide | Command table and examples | `IB-WP-0012` | planned |
|
||||
| Provide command migration path | Legacy command parity guide | Command table, examples, migration guide, decision record, acceptance tests | `IB-WP-0012` | done |
|
||||
|
||||
## Replacement Gates
|
||||
|
||||
@@ -91,6 +91,7 @@ Required workplans:
|
||||
|
||||
## Readiness Statement
|
||||
|
||||
`infospace-bench` is a replacement candidate today, not a full replacement. It
|
||||
becomes replacement-ready only after the gates above produce committed tests,
|
||||
docs, pilots, and State Hub decisions.
|
||||
`infospace-bench` is replacement-ready for new in-scope infospace work. It is
|
||||
not a name-for-name clone of the old `markitect infospace` CLI; remaining gaps
|
||||
are explicitly owned by `infospace-bench`, `markitect-tool`, or
|
||||
`kontextual-engine` in `docs/replacement-readiness-decision.md`.
|
||||
|
||||
52
docs/replacement-readiness-decision.md
Normal file
52
docs/replacement-readiness-decision.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: IB-DR-0012
|
||||
title: Replacement Readiness Decision
|
||||
date: "2026-05-14"
|
||||
decision: replacement-ready-for-new-in-scope-infospace-work
|
||||
status: accepted
|
||||
workplan: IB-WP-0012
|
||||
---
|
||||
|
||||
# Replacement Readiness Decision
|
||||
|
||||
## Decision
|
||||
|
||||
`infospace-bench` is replacement-ready for new in-scope infospace work that was
|
||||
previously attempted inside `markitect-project` / `markitect-main`.
|
||||
|
||||
Not a name-for-name CLI clone: replacement readiness means the successor stack
|
||||
has an evidence-backed migration path, tests, pilots, and explicit ownership for
|
||||
remaining gaps.
|
||||
|
||||
## Evidence
|
||||
|
||||
- Lifecycle, manifest, validation, entity/relation parsing, checks, viability,
|
||||
history, workflows, engine sync planning, and CLI behavior are covered by the
|
||||
test suite.
|
||||
- `infospaces/bootstrap-pilot/` proves the repo-native lifecycle and workflow
|
||||
baseline.
|
||||
- `infospaces/wealth-vsm-legacy-slice/` proves a pruned legacy migration from
|
||||
the old Wealth/VSM experiment.
|
||||
- `docs/legacy-command-parity.md` gives users a command and API migration path.
|
||||
- `docs/legacy-infospace-migration-guide.md` gives a repeatable migration
|
||||
process.
|
||||
|
||||
## Residual Gaps And Owners
|
||||
|
||||
| Gap | Owner | Decision |
|
||||
| --- | --- | --- |
|
||||
| Rich source/chapter triage view | `infospace-bench` | Deferred; use manifest export and workflows meanwhile. |
|
||||
| Classification workflow fixtures | `infospace-bench` | Deferred; implement as explicit workflows, not hidden provider calls. |
|
||||
| Discipline composition command | `infospace-bench` | Deferred; config support exists, operational checks need a focused follow-up. |
|
||||
| Stale mapping detection | `infospace-bench` + `kontextual-engine` | Deferred until provenance policy and durable asset comparison are settled. |
|
||||
| Durable graph/retrieval/runtime | `kontextual-engine` | Delegated by design. |
|
||||
| Markdown parser/schema engine | `markitect-tool` | Delegated by design. |
|
||||
|
||||
## Consequences
|
||||
|
||||
- New in-scope infospace work should start in `infospace-bench`.
|
||||
- Low-level markdown behavior should be added to `markitect-tool`.
|
||||
- Durable runtime concerns should be integrated through `kontextual-engine`
|
||||
boundaries rather than built into this repo.
|
||||
- Legacy bulk generated output should be migrated only when it has a current,
|
||||
scoped use and can be covered by tests.
|
||||
@@ -9,8 +9,31 @@ disciplines:
|
||||
path: artifacts/generated/lifecycle-baseline.md
|
||||
schemas: {}
|
||||
workflows:
|
||||
- name: baseline-inspection
|
||||
report: reports/baseline-inspection.md
|
||||
- id: baseline-inspection
|
||||
description: Existing committed inspection report for the bootstrap pilot.
|
||||
inputs: {}
|
||||
stages: []
|
||||
expected_evaluations:
|
||||
- metrics
|
||||
- id: bootstrap-readiness
|
||||
description: Deterministically render replacement-readiness summaries for source artifacts.
|
||||
inputs:
|
||||
source:
|
||||
kind: source
|
||||
static_macros:
|
||||
successor_role: application-layer successor for in-scope infospace work
|
||||
stages:
|
||||
- id: render-readiness-summary
|
||||
kind: template
|
||||
input: source
|
||||
template: workflows/templates/bootstrap-readiness.md
|
||||
output:
|
||||
path: artifacts/generated/{{ input.slug }}-readiness.md
|
||||
artifact_id: generated/{{ input.slug }}-readiness.md
|
||||
kind: generated
|
||||
title: "{{ input.title }} Readiness Summary"
|
||||
expected_evaluations:
|
||||
- metrics
|
||||
viability:
|
||||
redundancy_ratio:
|
||||
max: 0
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# {{ input.title }} Readiness Summary
|
||||
|
||||
Role: {{ macros.successor_role }}
|
||||
|
||||
Source artifact: {{ input.artifact_id }}
|
||||
|
||||
## Source
|
||||
|
||||
{{ input.content }}
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from collections import Counter
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -8,7 +9,15 @@ from pathlib import Path
|
||||
from .checks import run_collection_checks
|
||||
from .engine import engine_capability_contract, plan_asset_sync, sync_assets
|
||||
from .errors import InfospaceError
|
||||
from .history import find_snapshot, get_history, metric_trend, record_check_results
|
||||
from .history import (
|
||||
build_viability_report,
|
||||
find_snapshot,
|
||||
get_history,
|
||||
metric_trend,
|
||||
read_metrics_file,
|
||||
record_check_results,
|
||||
)
|
||||
from .inspection import export_mermaid, relationship_summary
|
||||
from .lifecycle import add_artifact, create_infospace, load_infospace
|
||||
from .markdown_adapter import validate_infospace_artifacts
|
||||
from .semantics import list_entities, list_relations
|
||||
@@ -28,6 +37,9 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
inspect = sub.add_parser("inspect", help="Inspect an infospace")
|
||||
inspect.add_argument("root")
|
||||
|
||||
status = sub.add_parser("status", help="Summarize replacement readiness state")
|
||||
status.add_argument("root")
|
||||
|
||||
add = sub.add_parser("add-artifact", help="Add an artifact to an infospace")
|
||||
add.add_argument("root")
|
||||
add.add_argument("source")
|
||||
@@ -64,6 +76,19 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
)
|
||||
metrics.add_argument("root")
|
||||
|
||||
check = sub.add_parser(
|
||||
"check",
|
||||
help="Run collection checks and persist metrics/history",
|
||||
)
|
||||
check.add_argument("root")
|
||||
|
||||
viability = sub.add_parser("viability", help="Evaluate configured thresholds")
|
||||
viability.add_argument("root")
|
||||
|
||||
graph = sub.add_parser("graph", help="Export the artifact relationship graph")
|
||||
graph.add_argument("root")
|
||||
graph.add_argument("--format", choices=["json", "mermaid"], default="json")
|
||||
|
||||
workflow = sub.add_parser("workflow", help="Inspect, plan, and run workflows")
|
||||
workflow_sub = workflow.add_subparsers(dest="workflow_command", required=True)
|
||||
|
||||
@@ -126,6 +151,8 @@ def main(argv: list[str] | None = None) -> int:
|
||||
_write_json({"slug": infospace.config.slug, "root": str(infospace.root)})
|
||||
elif args.command == "inspect":
|
||||
_write_json(load_infospace(Path(args.root)).to_dict())
|
||||
elif args.command == "status":
|
||||
_write_json(_status_payload(Path(args.root)))
|
||||
elif args.command == "add-artifact":
|
||||
artifact = add_artifact(
|
||||
Path(args.root),
|
||||
@@ -191,12 +218,26 @@ def main(argv: list[str] | None = None) -> int:
|
||||
)
|
||||
_write_json({"diff": before.diff(after).to_dict()})
|
||||
elif args.command == "metrics":
|
||||
_write_json(_record_checks(Path(args.root)).to_dict())
|
||||
elif args.command == "check":
|
||||
infospace = load_infospace(Path(args.root))
|
||||
result = record_check_results(
|
||||
infospace.root,
|
||||
run_collection_checks(infospace.artifacts),
|
||||
report = run_collection_checks(infospace.artifacts)
|
||||
result = record_check_results(infospace.root, report)
|
||||
_write_json(
|
||||
{
|
||||
**result.to_dict(),
|
||||
"details": report.details,
|
||||
}
|
||||
)
|
||||
_write_json(result.to_dict())
|
||||
elif args.command == "viability":
|
||||
_write_json(build_viability_report(Path(args.root)))
|
||||
elif args.command == "graph":
|
||||
infospace = load_infospace(Path(args.root))
|
||||
summary = relationship_summary(infospace.artifacts)
|
||||
if args.format == "mermaid":
|
||||
print(export_mermaid(summary), end="")
|
||||
else:
|
||||
_write_json(_relationship_summary_payload(summary))
|
||||
elif args.command == "workflow":
|
||||
if args.workflow_command == "inspect":
|
||||
_write_json(
|
||||
@@ -241,5 +282,67 @@ def main(argv: list[str] | None = None) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _status_payload(root: Path) -> dict:
|
||||
infospace = load_infospace(root)
|
||||
validation = validate_infospace_artifacts(infospace.root)
|
||||
entities = list_entities(infospace.root)
|
||||
relations = list_relations(infospace.root)
|
||||
history = get_history(infospace.root)
|
||||
metrics = read_metrics_file(
|
||||
infospace.root / "output" / "metrics" / "metrics.yaml"
|
||||
)
|
||||
viability = (
|
||||
build_viability_report(infospace.root) if infospace.config.viability else None
|
||||
)
|
||||
graph = relationship_summary(infospace.artifacts)
|
||||
return {
|
||||
"slug": infospace.config.slug,
|
||||
"name": infospace.config.name,
|
||||
"topic": infospace.config.topic.to_dict(),
|
||||
"artifact_count": len(infospace.artifacts),
|
||||
"artifact_kinds": dict(
|
||||
sorted(Counter(item.kind for item in infospace.artifacts).items())
|
||||
),
|
||||
"entity_count": len(entities),
|
||||
"relation_count": len(relations),
|
||||
"validation": {
|
||||
"checked_artifact_count": len(validation),
|
||||
"valid": all(result.valid for result in validation),
|
||||
},
|
||||
"history": {
|
||||
"snapshot_count": len(history),
|
||||
"latest_snapshot_id": history[-1].snapshot_id if history else "",
|
||||
},
|
||||
"metrics": metrics,
|
||||
"viability": viability,
|
||||
"graph": {
|
||||
"node_count": graph.node_count,
|
||||
"edge_count": graph.edge_count,
|
||||
"relationship_types": graph.relationship_types,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def _record_checks(root: Path):
|
||||
infospace = load_infospace(root)
|
||||
return record_check_results(
|
||||
infospace.root,
|
||||
run_collection_checks(infospace.artifacts),
|
||||
)
|
||||
|
||||
|
||||
def _relationship_summary_payload(summary) -> dict:
|
||||
return {
|
||||
"node_count": summary.node_count,
|
||||
"edge_count": summary.edge_count,
|
||||
"nodes": summary.nodes,
|
||||
"edges": [
|
||||
{"source": edge.source, "target": edge.target, "type": edge.type}
|
||||
for edge in summary.edges
|
||||
],
|
||||
"relationship_types": summary.relationship_types,
|
||||
}
|
||||
|
||||
|
||||
def _write_json(payload: dict) -> None:
|
||||
print(json.dumps(payload, indent=2))
|
||||
|
||||
161
tests/test_replacement_readiness.py
Normal file
161
tests/test_replacement_readiness.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from infospace_bench import load_infospace
|
||||
from infospace_bench.engine import plan_asset_sync
|
||||
from infospace_bench.evaluation_io import read_history
|
||||
from infospace_bench.history import read_metrics_file
|
||||
from infospace_bench.markdown_adapter import validate_infospace_artifacts
|
||||
from infospace_bench.semantics import list_entities, list_relations
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
BOOTSTRAP = REPO_ROOT / "infospaces" / "bootstrap-pilot"
|
||||
LEGACY_SLICE = REPO_ROOT / "infospaces" / "wealth-vsm-legacy-slice"
|
||||
|
||||
|
||||
LEGACY_COMMANDS = {
|
||||
"init",
|
||||
"status",
|
||||
"entities",
|
||||
"chapters",
|
||||
"evaluate",
|
||||
"eval-summary",
|
||||
"relations",
|
||||
"classify",
|
||||
"viability",
|
||||
"check",
|
||||
"history",
|
||||
"history-diff",
|
||||
"bind-discipline",
|
||||
"process",
|
||||
"stale-mappings",
|
||||
"graph",
|
||||
}
|
||||
|
||||
|
||||
def cli_env() -> dict[str, str]:
|
||||
env = os.environ.copy()
|
||||
env["PYTHONPATH"] = str(REPO_ROOT / "src") + ":/home/worsch/markitect-tool/src"
|
||||
return env
|
||||
|
||||
|
||||
def run_cli(*args: str, cwd: Path | None = None) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
[sys.executable, "-m", "infospace_bench", *args],
|
||||
check=False,
|
||||
cwd=cwd or REPO_ROOT,
|
||||
env=cli_env(),
|
||||
text=True,
|
||||
capture_output=True,
|
||||
)
|
||||
|
||||
|
||||
def copy_infospace(source: Path, tmp_path: Path) -> Path:
|
||||
target = tmp_path / source.name
|
||||
shutil.copytree(source, target)
|
||||
return target
|
||||
|
||||
|
||||
def test_legacy_command_parity_guide_covers_required_commands() -> None:
|
||||
guide = REPO_ROOT / "docs" / "legacy-command-parity.md"
|
||||
text = guide.read_text(encoding="utf-8")
|
||||
|
||||
for command in sorted(LEGACY_COMMANDS):
|
||||
assert f"`markitect infospace {command}`" in text
|
||||
|
||||
assert "replaced" in text
|
||||
assert "reframed" in text
|
||||
assert "delegated" in text
|
||||
assert "deferred" in text
|
||||
assert "retired" in text
|
||||
|
||||
|
||||
def test_bootstrap_pilot_replacement_gate_cli_round_trip(tmp_path: Path) -> None:
|
||||
root = copy_infospace(BOOTSTRAP, tmp_path)
|
||||
|
||||
status = run_cli("status", str(root))
|
||||
validation = run_cli("validate", str(root))
|
||||
check = run_cli("check", str(root))
|
||||
viability = run_cli("viability", str(root))
|
||||
graph = run_cli("graph", str(root), "--format", "mermaid")
|
||||
exported = run_cli("export", str(root))
|
||||
workflow = run_cli("workflow", "run", str(root), "bootstrap-readiness")
|
||||
|
||||
assert status.returncode == 0, status.stderr
|
||||
assert validation.returncode == 0, validation.stderr
|
||||
assert check.returncode == 0, check.stderr
|
||||
assert viability.returncode == 0, viability.stderr
|
||||
assert graph.returncode == 0, graph.stderr
|
||||
assert exported.returncode == 0, exported.stderr
|
||||
assert workflow.returncode == 0, workflow.stderr
|
||||
|
||||
status_payload = json.loads(status.stdout)
|
||||
check_payload = json.loads(check.stdout)
|
||||
viability_payload = json.loads(viability.stdout)
|
||||
workflow_payload = json.loads(workflow.stdout)
|
||||
|
||||
assert status_payload["slug"] == "bootstrap-pilot"
|
||||
assert status_payload["artifact_count"] == 4
|
||||
assert status_payload["artifact_kinds"] == {"generated": 2, "source": 2}
|
||||
assert check_payload["metrics"]["coverage_ratio"] == 1.0
|
||||
assert viability_payload["passed"] is True
|
||||
assert "source/prd-scope.md -->|supports| generated/lifecycle-baseline.md" in (
|
||||
graph.stdout
|
||||
)
|
||||
assert json.loads(exported.stdout)["config"]["slug"] == "bootstrap-pilot"
|
||||
assert workflow_payload["status"] == "completed"
|
||||
assert workflow_payload["outputs"][0]["artifact_id"] == (
|
||||
"generated/prd-scope-readiness.md"
|
||||
)
|
||||
|
||||
metrics = read_metrics_file(root / "output" / "metrics" / "metrics.yaml")
|
||||
history = read_history(root / "output" / "metrics" / "history.yaml")
|
||||
assert metrics["coverage_ratio"] == 1.0
|
||||
assert history[-1].artifact_count == 4
|
||||
|
||||
|
||||
def test_legacy_slice_replacement_gate_exercises_semantics_and_engine() -> None:
|
||||
infospace = load_infospace(LEGACY_SLICE)
|
||||
validation = validate_infospace_artifacts(LEGACY_SLICE)
|
||||
entities = list_entities(LEGACY_SLICE)
|
||||
relations = list_relations(LEGACY_SLICE)
|
||||
metrics = read_metrics_file(LEGACY_SLICE / "output" / "metrics" / "metrics.yaml")
|
||||
history = read_history(LEGACY_SLICE / "output" / "metrics" / "history.yaml")
|
||||
plan = plan_asset_sync(LEGACY_SLICE)
|
||||
|
||||
assert infospace.config.slug == "wealth-vsm-legacy-slice"
|
||||
assert all(result.valid for result in validation)
|
||||
assert [entity.slug for entity in entities] == [
|
||||
"division-of-labour",
|
||||
"market-extent",
|
||||
]
|
||||
assert relations[0].subject_entity_id == "entity/division-of-labour.md"
|
||||
assert metrics["per_artifact_mean"] == 4.6
|
||||
assert history[0].snapshot_id == "legacy-slice"
|
||||
assert [action.action for action in plan.actions] == [
|
||||
"create",
|
||||
"create",
|
||||
"create",
|
||||
"create",
|
||||
]
|
||||
|
||||
|
||||
def test_replacement_decision_record_names_residual_owners() -> None:
|
||||
decision = REPO_ROOT / "docs" / "replacement-readiness-decision.md"
|
||||
data = yaml.safe_load(
|
||||
decision.read_text(encoding="utf-8").split("---", maxsplit=2)[1]
|
||||
)
|
||||
text = decision.read_text(encoding="utf-8")
|
||||
|
||||
assert data["decision"] == "replacement-ready-for-new-in-scope-infospace-work"
|
||||
assert "markitect-tool" in text
|
||||
assert "kontextual-engine" in text
|
||||
assert "infospace-bench" in text
|
||||
assert "Not a name-for-name CLI clone" in text
|
||||
@@ -4,7 +4,7 @@ type: workplan
|
||||
title: "Replacement Readiness And CLI Parity Gate"
|
||||
domain: markitect
|
||||
repo: infospace-bench
|
||||
status: planned
|
||||
status: completed
|
||||
owner: markitect
|
||||
topic_slug: markitect
|
||||
created: "2026-05-14"
|
||||
@@ -26,7 +26,7 @@ in-scope infospace features from `markitect-project`.
|
||||
|
||||
```task
|
||||
id: IB-WP-0012-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "b48edb8e-b0af-4d46-9714-9830725d0773"
|
||||
```
|
||||
@@ -41,7 +41,7 @@ state_hub_task_id: "b48edb8e-b0af-4d46-9714-9830725d0773"
|
||||
|
||||
```task
|
||||
id: IB-WP-0012-T02
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "12eb0f88-4483-48ad-b156-79fa7c2171b7"
|
||||
```
|
||||
@@ -55,7 +55,7 @@ state_hub_task_id: "12eb0f88-4483-48ad-b156-79fa7c2171b7"
|
||||
|
||||
```task
|
||||
id: IB-WP-0012-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "cd4ee529-1ca0-4214-80fc-000af5c16b11"
|
||||
```
|
||||
@@ -69,7 +69,7 @@ state_hub_task_id: "cd4ee529-1ca0-4214-80fc-000af5c16b11"
|
||||
|
||||
```task
|
||||
id: IB-WP-0012-T04
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
state_hub_task_id: "ca88d1c5-b83f-47c9-90d0-58cedc7ca6f7"
|
||||
```
|
||||
@@ -83,3 +83,20 @@ state_hub_task_id: "ca88d1c5-b83f-47c9-90d0-58cedc7ca6f7"
|
||||
- Replacement readiness is evidence-based, not aspirational
|
||||
- Users have a command/API migration path
|
||||
- Remaining gaps are explicitly owned by the correct repo
|
||||
|
||||
## Implementation
|
||||
|
||||
- Added `docs/legacy-command-parity.md` with the legacy command migration table
|
||||
and replacement examples.
|
||||
- Added `docs/legacy-infospace-migration-guide.md` and
|
||||
`docs/replacement-readiness-decision.md`.
|
||||
- Added replacement gate CLI commands: `status`, `check`, `viability`, and
|
||||
`graph`.
|
||||
- Added deterministic `bootstrap-readiness` workflow fixture.
|
||||
- Added `tests/test_replacement_readiness.py` covering both pilots, the CLI
|
||||
gate, migration docs, and the decision record.
|
||||
|
||||
## Verification
|
||||
|
||||
- `python3 -m pytest tests/test_replacement_readiness.py`
|
||||
- `python3 -m pytest`
|
||||
|
||||
Reference in New Issue
Block a user