command parity and migration guide

This commit is contained in:
2026-05-14 17:16:39 +02:00
parent 0753c32c1b
commit 3de72eb0d2
10 changed files with 552 additions and 16 deletions

View File

@@ -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/`

View 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
```

View 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.

View File

@@ -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`.

View 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.

View File

@@ -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

View File

@@ -0,0 +1,9 @@
# {{ input.title }} Readiness Summary
Role: {{ macros.successor_role }}
Source artifact: {{ input.artifact_id }}
## Source
{{ input.content }}

View File

@@ -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))

View 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

View File

@@ -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`