From 3de72eb0d28e10eb8665464e5187c9d454b907db Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 14 May 2026 17:16:39 +0200 Subject: [PATCH] command parity and migration guide --- README.md | 3 + docs/legacy-command-parity.md | 89 ++++++++++ docs/legacy-infospace-migration-guide.md | 78 +++++++++ docs/replacement-acceptance-matrix.md | 9 +- docs/replacement-readiness-decision.md | 52 ++++++ infospaces/bootstrap-pilot/infospace.yaml | 27 ++- .../templates/bootstrap-readiness.md | 9 + src/infospace_bench/cli.py | 113 +++++++++++- tests/test_replacement_readiness.py | 161 ++++++++++++++++++ ...P-0012-replacement-readiness-cli-parity.md | 27 ++- 10 files changed, 552 insertions(+), 16 deletions(-) create mode 100644 docs/legacy-command-parity.md create mode 100644 docs/legacy-infospace-migration-guide.md create mode 100644 docs/replacement-readiness-decision.md create mode 100644 infospaces/bootstrap-pilot/workflows/templates/bootstrap-readiness.md create mode 100644 tests/test_replacement_readiness.py diff --git a/README.md b/README.md index c68d39a..375a1f7 100644 --- a/README.md +++ b/README.md @@ -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/` diff --git a/docs/legacy-command-parity.md b/docs/legacy-command-parity.md new file mode 100644 index 0000000..4f92a5d --- /dev/null +++ b/docs/legacy-command-parity.md @@ -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 --name "" --topic-domain ""` | Creates the file-backed `infospaces//` layout and manifest. | +| `markitect infospace status` | replaced | `infospace-bench status ` | JSON summary of config, artifact counts, parsed entities/relations, metrics, viability, history, and graph counts. | +| `markitect infospace entities` | replaced | `infospace-bench entities ` 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 ` 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 ` 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 --metric per_artifact_mean` and `infospace-bench status ` | Evaluation results are structured artifacts plus metrics history, not a one-off text table. | +| `markitect infospace relations` | replaced | `infospace-bench relations ` | Relation triplets resolve endpoints against parsed entity artifacts. | +| `markitect infospace classify` | deferred | `infospace-bench workflow plan/run ` | 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 ` | Evaluates configured thresholds from persisted metrics. | +| `markitect infospace check` | replaced | `infospace-bench check ` | Runs deterministic collection checks, persists metrics, appends history, and writes viability output. | +| `markitect infospace history` | replaced | `infospace-bench history ` or `infospace-bench history --metric ` | Reads file-backed metric snapshots. | +| `markitect infospace history-diff` | replaced | `infospace-bench history-diff ` | 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 ` | 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 --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 +``` + diff --git a/docs/legacy-infospace-migration-guide.md b/docs/legacy-infospace-migration-guide.md new file mode 100644 index 0000000..bbd3487 --- /dev/null +++ b/docs/legacy-infospace-migration-guide.md @@ -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 +infospace-bench validate +infospace-bench entities +infospace-bench relations +infospace-bench check +infospace-bench viability +infospace-bench history +infospace-bench graph --format mermaid +infospace-bench engine plan-sync +``` + +## 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. + diff --git a/docs/replacement-acceptance-matrix.md b/docs/replacement-acceptance-matrix.md index 72e2c1a..5a4cb46 100644 --- a/docs/replacement-acceptance-matrix.md +++ b/docs/replacement-acceptance-matrix.md @@ -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`. diff --git a/docs/replacement-readiness-decision.md b/docs/replacement-readiness-decision.md new file mode 100644 index 0000000..24b4175 --- /dev/null +++ b/docs/replacement-readiness-decision.md @@ -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. diff --git a/infospaces/bootstrap-pilot/infospace.yaml b/infospaces/bootstrap-pilot/infospace.yaml index cf04f70..349aa87 100644 --- a/infospaces/bootstrap-pilot/infospace.yaml +++ b/infospaces/bootstrap-pilot/infospace.yaml @@ -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 diff --git a/infospaces/bootstrap-pilot/workflows/templates/bootstrap-readiness.md b/infospaces/bootstrap-pilot/workflows/templates/bootstrap-readiness.md new file mode 100644 index 0000000..2fd6456 --- /dev/null +++ b/infospaces/bootstrap-pilot/workflows/templates/bootstrap-readiness.md @@ -0,0 +1,9 @@ +# {{ input.title }} Readiness Summary + +Role: {{ macros.successor_role }} + +Source artifact: {{ input.artifact_id }} + +## Source + +{{ input.content }} diff --git a/src/infospace_bench/cli.py b/src/infospace_bench/cli.py index 266eca7..838efa5 100644 --- a/src/infospace_bench/cli.py +++ b/src/infospace_bench/cli.py @@ -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)) diff --git a/tests/test_replacement_readiness.py b/tests/test_replacement_readiness.py new file mode 100644 index 0000000..1ce7c99 --- /dev/null +++ b/tests/test_replacement_readiness.py @@ -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 diff --git a/workplans/IB-WP-0012-replacement-readiness-cli-parity.md b/workplans/IB-WP-0012-replacement-readiness-cli-parity.md index a7bd625..31ab7f1 100644 --- a/workplans/IB-WP-0012-replacement-readiness-cli-parity.md +++ b/workplans/IB-WP-0012-replacement-readiness-cli-parity.md @@ -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`