Commit f0f798f
feat: platform refactor — spec, decomposition, config, managed copier (#90)
* docs: add MAP platform refactor spec with OpenSpec analysis and codebase audit
- Landscape analysis: OpenSpec patterns (schema DAGs, context injection,
multi-tool delivery, verification dimensions, migration) with clear
differentiation from MAP's hard-gate philosophy
- Per-phase codebase analysis with concrete file paths, LOC counts, and
gap tables for all 7 implementation phases
- Artifact inventory: 25 .map/ artifacts catalogued with producer/consumer
and schema coverage assessment
- Claude Code coupling map: portable vs platform-specific components
- Implementation priority graph with dependency ordering and quick wins
- 10 open questions enriched with codebase evidence
* refactor: decompose __init__.py into cli_ui, delivery/, config/ submodules
Extract 1422 lines (53%) from the monolithic __init__.py (2692→1270 lines)
into focused submodules while maintaining full backward compatibility:
- cli_ui.py: StepTracker, interactive selectors, banner display
- delivery/agent_generator.py: 7 fallback agent content generators
- delivery/file_copier.py: file copy/install functions (agents, commands, hooks, etc.)
- config/settings.py: global/project permissions management
- config/mcp.py: MCP server configuration and .mcp.json handling
Quick wins included:
- Add BLUEPRINT_SCHEMA to schemas.py (blueprint.json was parsed without validation)
- Add validate_artifact() and load_and_validate() utilities to schemas.py
- Support jsonschema Draft7/4 fallback for older environments
All re-exports preserved in __init__.py — existing imports continue to work.
Tests updated: mock paths adjusted for new module locations.
24 new decomposition tests + 88 template sync tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add .map/config.yaml project configuration system
Introduce MapConfig dataclass with 23 configurable fields covering
workflow profiles, policy thresholds, safety guardrails, pruner settings,
and delivery options. Config is loaded from .map/config.yaml with
graceful fallback to defaults when file is missing or malformed.
- Add config/project_config.py with MapConfig, load_map_config(),
generate_default_config(), write_default_config()
- Wire write_default_config() into `mapify init` command
- Update safety-guardrails.py hook to read config overrides from
.map/config.yaml (dangerous_file_patterns, dangerous_commands,
safe_path_prefixes) with fallback to hardcoded defaults
- Sync hook template to .claude/hooks/
- Add 13 tests for config system (load, generate, write, edge cases)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add drift-aware managed file copier for upgrade safety
Replace raw shutil.copy2() with copy_managed_file() that injects
metadata headers (generated_by, mapify_version, template_hash) and
detects user modifications during upgrade.
- Add delivery/managed_file_copier.py with metadata injection for
.md (HTML comment), .py (comment), .json (_map_managed key)
- Add drift detection: compares content hash against stored template_hash
- Auto-backup drifted files to .bak before overwriting
- Integrate into all file_copier.py functions (agents, commands,
references, hooks, configs) with optional DriftReport parameter
- Update upgrade() to collect drift reports and show warnings with
backup locations for modified files
- Add 29 tests covering hashing, injection, extraction, roundtrips,
drift detection, and backup creation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: review fixes — correctness bugs, DRY violations, missing tests
- Fix load_and_validate returning data instead of None on invalid input
- Deduplicate get_templates_dir (delegate from __init__.py to file_copier)
- Use timestamped backup names to prevent collision on repeated upgrades
- Unify Console instances (import from cli_ui instead of creating new)
- Fix extract_metadata .py reconstruction (positional split, not search)
- Add MapConfig type validation (wrong YAML types fall back to defaults)
- Simplify no-op setdefault calls in settings.py
- Remove unused mcp_section from create_reflector_content
- Remove duplicate in-function imports from file_copier._copy_map_path
- Add spec link to README docs table
- Add 4 tests: guardrails config override, type coercion, backup
collision, load_and_validate with invalid data
* fix: remove duplicate import and add write error handling
- Remove duplicate `from datetime import datetime, timezone` inside
copy_managed_file() (already imported at module level)
- Add try/except around dest.write_text() to gracefully handle write
failures instead of crashing mid-upgrade
- Add `from __future__ import annotations` to file_copier.py for
consistent Python 3.10 compatibility with union type syntax
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: sanitize control characters in handoff bundle to prevent jq parse errors
build_handoff_bundle and build_review_handoff read markdown/JSON artifacts
that may contain raw control characters (ANSI escapes, null bytes from
test output). These chars pass through Python json.dumps correctly but
can corrupt bash variable expansion before reaching jq.
- Add _sanitize_for_json() to strip U+0000-U+001F (except \n \r \t)
- Use errors="replace" on read_text to handle non-UTF-8 files gracefully
- Add OSError catch to prevent traceback on stdout from corrupted files
- Use ensure_ascii=True in json.dumps for handoff CLI output
* fix: align step_state field names between map-plan and workflow-gate
map-plan created step_state.json with field names "current_state" and
"current_subtask", but workflow-gate.py reads "current_step_phase" and
"current_subtask_id". This mismatch caused the gate to see empty phase
and block all edits after map-plan, requiring manual state patching.
- Fix map-plan.md step_state template: use current_step_phase and
current_subtask_id to match gate expectations
- Fix map-tdd.md: add workflow_status check before resume, explicit
guidance for COMPLETE/INITIALIZED states requiring reinit
- Add _sanitize_for_json to map_step_runner.py handoff functions to
prevent jq parse errors from control chars in artifact content
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>1 parent ae7be28 commit f0f798f
24 files changed
Lines changed: 4591 additions & 1512 deletions
File tree
- .claude
- commands
- hooks
- .map/scripts
- docs
- src/mapify_cli
- config
- delivery
- templates
- commands
- hooks
- map/scripts
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
474 | 474 | | |
475 | 475 | | |
476 | 476 | | |
477 | | - | |
478 | | - | |
| 477 | + | |
| 478 | + | |
479 | 479 | | |
480 | 480 | | |
481 | 481 | | |
| |||
492 | 492 | | |
493 | 493 | | |
494 | 494 | | |
| 495 | + | |
| 496 | + | |
495 | 497 | | |
496 | 498 | | |
497 | 499 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
69 | 72 | | |
70 | 73 | | |
71 | 74 | | |
72 | | - | |
| 75 | + | |
| 76 | + | |
73 | 77 | | |
74 | 78 | | |
75 | 79 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
16 | 17 | | |
17 | 18 | | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
18 | 24 | | |
19 | 25 | | |
20 | | - | |
| 26 | + | |
21 | 27 | | |
22 | 28 | | |
23 | 29 | | |
| |||
31 | 37 | | |
32 | 38 | | |
33 | 39 | | |
34 | | - | |
| 40 | + | |
35 | 41 | | |
36 | 42 | | |
37 | 43 | | |
| |||
46 | 52 | | |
47 | 53 | | |
48 | 54 | | |
49 | | - | |
| 55 | + | |
50 | 56 | | |
51 | 57 | | |
52 | 58 | | |
| |||
64 | 70 | | |
65 | 71 | | |
66 | 72 | | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
67 | 103 | | |
68 | 104 | | |
69 | 105 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
299 | 299 | | |
300 | 300 | | |
301 | 301 | | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
302 | 311 | | |
303 | 312 | | |
304 | 313 | | |
| |||
307 | 316 | | |
308 | 317 | | |
309 | 318 | | |
310 | | - | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
311 | 325 | | |
312 | 326 | | |
313 | 327 | | |
| |||
362 | 376 | | |
363 | 377 | | |
364 | 378 | | |
365 | | - | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
366 | 385 | | |
367 | 386 | | |
368 | 387 | | |
| |||
1019 | 1038 | | |
1020 | 1039 | | |
1021 | 1040 | | |
1022 | | - | |
| 1041 | + | |
1023 | 1042 | | |
1024 | 1043 | | |
1025 | 1044 | | |
1026 | | - | |
| 1045 | + | |
1027 | 1046 | | |
1028 | 1047 | | |
1029 | 1048 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
96 | 97 | | |
97 | 98 | | |
98 | 99 | | |
| |||
0 commit comments