mapify-cli 3.31.3__py3-none-any.whl → 3.32.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapify_cli/__init__.py +1 -1
- mapify_cli/templates/codex/hooks/context-meter.py +3 -3
- mapify_cli/templates/codex/hooks/detect-clarification-triggers.py +3 -3
- mapify_cli/templates/codex/hooks/map-memory-capture.py +3 -3
- mapify_cli/templates/codex/hooks/map-memory-endmark.py +3 -3
- mapify_cli/templates/codex/hooks/map-memory-recall.py +3 -3
- mapify_cli/templates/codex/hooks/map-memory-session.py +3 -3
- mapify_cli/templates/codex/hooks/map-stop.py +3 -3
- mapify_cli/templates/codex/hooks/map-token-meter.py +3 -3
- mapify_cli/templates/codex/hooks/post-compact-context.py +3 -3
- mapify_cli/templates/codex/hooks/pre-compact-save-transcript.py +3 -3
- mapify_cli/templates/codex/hooks/ralph-context-pruner.py +3 -3
- mapify_cli/templates/codex/hooks/ralph-iteration-logger.py +3 -3
- mapify_cli/templates/codex/hooks/safety-guardrails.py +3 -3
- mapify_cli/templates/codex/hooks/scrub-internal-ids.py +27 -17
- mapify_cli/templates/codex/hooks/workflow-context-injector.py +3 -3
- mapify_cli/templates/codex/hooks/workflow-gate.py +3 -3
- mapify_cli/templates/codex/skills/map-efficient/SKILL.md +1 -1
- mapify_cli/templates/codex/skills/map-efficient/efficient-reference.md +7 -19
- mapify_cli/templates/codex/skills/map-plan/SKILL.md +13 -6
- mapify_cli/templates/codex/skills/map-release/SKILL.md +23 -30
- mapify_cli/templates/codex/skills/map-release/release-reference.md +145 -44
- mapify_cli/templates/codex/skills/map-review/SKILL.md +543 -256
- mapify_cli/templates/codex/skills/map-review/adversarial-reference.md +87 -128
- mapify_cli/templates/codex/skills/map-review/review-reference.md +239 -337
- mapify_cli/templates/codex/skills/map-task/SKILL.md +1 -1
- mapify_cli/templates/codex/skills/map-wayfind/SKILL.md +20 -8
- mapify_cli/templates/codex/skills/map-wayfind/wayfind-reference.md +131 -3
- mapify_cli/templates/hooks/context-meter.py +3 -3
- mapify_cli/templates/hooks/detect-clarification-triggers.py +3 -3
- mapify_cli/templates/hooks/map-memory-capture.py +3 -3
- mapify_cli/templates/hooks/map-memory-endmark.py +3 -3
- mapify_cli/templates/hooks/map-memory-finalize.py +3 -3
- mapify_cli/templates/hooks/map-memory-recall.py +3 -3
- mapify_cli/templates/hooks/map-statusline.py +3 -3
- mapify_cli/templates/hooks/map-token-meter.py +3 -3
- mapify_cli/templates/hooks/post-compact-context.py +3 -3
- mapify_cli/templates/hooks/pre-compact-save-transcript.py +3 -3
- mapify_cli/templates/hooks/ralph-context-pruner.py +3 -3
- mapify_cli/templates/hooks/ralph-iteration-logger.py +3 -3
- mapify_cli/templates/hooks/safety-guardrails.py +3 -3
- mapify_cli/templates/hooks/scrub-internal-ids.py +27 -17
- mapify_cli/templates/hooks/workflow-context-injector.py +3 -3
- mapify_cli/templates/hooks/workflow-gate.py +3 -3
- mapify_cli/templates/map/scripts/map_orchestrator.py +3 -3
- mapify_cli/templates/map/scripts/map_step_runner.py +289 -66
- mapify_cli/templates/map/scripts/scrub_internal_ids.py +23 -9
- mapify_cli/templates/map/scripts/validate_spec_citations.py +3 -3
- mapify_cli/templates/map/scripts/wayfind_runner.py +575 -4
- mapify_cli/templates/skills/map-efficient/SKILL.md +1 -1
- mapify_cli/templates/skills/map-efficient/efficient-reference.md +7 -19
- mapify_cli/templates/skills/map-plan/SKILL.md +4 -7
- mapify_cli/templates/skills/map-release/SKILL.md +23 -30
- mapify_cli/templates/skills/map-release/release-reference.md +147 -43
- mapify_cli/templates/skills/map-review/SKILL.md +62 -63
- mapify_cli/templates/skills/map-review/adversarial-reference.md +39 -41
- mapify_cli/templates/skills/map-review/review-reference.md +32 -22
- mapify_cli/templates/skills/map-task/SKILL.md +1 -1
- mapify_cli/templates/skills/map-wayfind/SKILL.md +19 -7
- mapify_cli/templates/skills/map-wayfind/wayfind-reference.md +131 -3
- mapify_cli/templates_src/_partials/python-version-guard.py.jinja +3 -3
- mapify_cli/templates_src/codex/skills/map-auto/auto-reference.md.jinja +1 -78
- mapify_cli/templates_src/codex/skills/map-efficient/SKILL.md.jinja +1 -1
- mapify_cli/templates_src/codex/skills/map-efficient/efficient-reference.md.jinja +7 -19
- mapify_cli/templates_src/codex/skills/map-plan/SKILL.md.jinja +13 -6
- mapify_cli/templates_src/codex/skills/map-release/SKILL.md.jinja +1 -177
- mapify_cli/templates_src/codex/skills/map-release/release-reference.md.jinja +1 -456
- mapify_cli/templates_src/codex/skills/map-review/SKILL.md.jinja +1 -412
- mapify_cli/templates_src/codex/skills/map-review/adversarial-reference.md.jinja +1 -224
- mapify_cli/templates_src/codex/skills/map-review/review-reference.md.jinja +1 -477
- mapify_cli/templates_src/codex/skills/map-task/SKILL.md.jinja +1 -1
- mapify_cli/templates_src/codex/skills/map-wayfind/SKILL.md.jinja +1 -129
- mapify_cli/templates_src/codex/skills/map-wayfind/wayfind-reference.md.jinja +1 -134
- mapify_cli/templates_src/hooks/scrub-internal-ids.py.jinja +24 -14
- mapify_cli/templates_src/map/scripts/map_step_runner.py.jinja +286 -63
- mapify_cli/templates_src/map/scripts/scrub_internal_ids.py.jinja +23 -9
- mapify_cli/templates_src/map/scripts/wayfind_runner.py.jinja +575 -4
- mapify_cli/templates_src/skills/map-auto/auto-reference.md.jinja +9 -8
- mapify_cli/templates_src/skills/map-efficient/SKILL.md.jinja +1 -1
- mapify_cli/templates_src/skills/map-efficient/efficient-reference.md.jinja +7 -19
- mapify_cli/templates_src/skills/map-plan/SKILL.md.jinja +4 -7
- mapify_cli/templates_src/skills/map-release/SKILL.md.jinja +34 -34
- mapify_cli/templates_src/skills/map-release/release-reference.md.jinja +163 -47
- mapify_cli/templates_src/skills/map-review/SKILL.md.jinja +115 -65
- mapify_cli/templates_src/skills/map-review/adversarial-reference.md.jinja +62 -41
- mapify_cli/templates_src/skills/map-review/review-reference.md.jinja +39 -28
- mapify_cli/templates_src/skills/map-task/SKILL.md.jinja +1 -1
- mapify_cli/templates_src/skills/map-wayfind/SKILL.md.jinja +36 -21
- mapify_cli/templates_src/skills/map-wayfind/wayfind-reference.md.jinja +148 -14
- mapify_cli/tools/validate_dependencies.py +57 -32
- {mapify_cli-3.31.3.dist-info → mapify_cli-3.32.0.dist-info}/METADATA +3 -3
- {mapify_cli-3.31.3.dist-info → mapify_cli-3.32.0.dist-info}/RECORD +95 -95
- {mapify_cli-3.31.3.dist-info → mapify_cli-3.32.0.dist-info}/WHEEL +0 -0
- {mapify_cli-3.31.3.dist-info → mapify_cli-3.32.0.dist-info}/entry_points.txt +0 -0
- {mapify_cli-3.31.3.dist-info → mapify_cli-3.32.0.dist-info}/licenses/LICENSE +0 -0
mapify_cli/__init__.py
CHANGED
|
@@ -23,7 +23,7 @@ Or install globally:
|
|
|
23
23
|
mapify check
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
__version__ = "3.
|
|
26
|
+
__version__ = "3.32.0"
|
|
27
27
|
|
|
28
28
|
# MUST stay the first import: it turns "this interpreter is older than 3.11" into
|
|
29
29
|
# a message that says so, instead of the ImportError raised by `from datetime
|
|
@@ -36,13 +36,13 @@ import sys
|
|
|
36
36
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
37
37
|
# Name the real cause instead. Kept in sync with
|
|
38
38
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
39
|
-
#
|
|
40
|
-
#
|
|
39
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
40
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
41
41
|
#
|
|
42
42
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
43
43
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
44
44
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
45
|
-
if sys.version_info < (3, 11):
|
|
45
|
+
if tuple(sys.version_info) < (3, 11):
|
|
46
46
|
_MAP_PYTHON_PROBLEM = (
|
|
47
47
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
48
48
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -37,13 +37,13 @@ import sys
|
|
|
37
37
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
38
38
|
# Name the real cause instead. Kept in sync with
|
|
39
39
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
40
|
-
#
|
|
41
|
-
#
|
|
40
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
41
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
42
42
|
#
|
|
43
43
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
44
44
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
45
45
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
46
|
-
if sys.version_info < (3, 11):
|
|
46
|
+
if tuple(sys.version_info) < (3, 11):
|
|
47
47
|
_MAP_PYTHON_PROBLEM = (
|
|
48
48
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
49
49
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -10,13 +10,13 @@ import sys
|
|
|
10
10
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
11
11
|
# Name the real cause instead. Kept in sync with
|
|
12
12
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
14
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
15
15
|
#
|
|
16
16
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
17
17
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
18
18
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
19
|
-
if sys.version_info < (3, 11):
|
|
19
|
+
if tuple(sys.version_info) < (3, 11):
|
|
20
20
|
_MAP_PYTHON_PROBLEM = (
|
|
21
21
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
22
22
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -10,13 +10,13 @@ import sys
|
|
|
10
10
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
11
11
|
# Name the real cause instead. Kept in sync with
|
|
12
12
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
14
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
15
15
|
#
|
|
16
16
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
17
17
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
18
18
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
19
|
-
if sys.version_info < (3, 11):
|
|
19
|
+
if tuple(sys.version_info) < (3, 11):
|
|
20
20
|
_MAP_PYTHON_PROBLEM = (
|
|
21
21
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
22
22
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -10,13 +10,13 @@ import sys
|
|
|
10
10
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
11
11
|
# Name the real cause instead. Kept in sync with
|
|
12
12
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
14
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
15
15
|
#
|
|
16
16
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
17
17
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
18
18
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
19
|
-
if sys.version_info < (3, 11):
|
|
19
|
+
if tuple(sys.version_info) < (3, 11):
|
|
20
20
|
_MAP_PYTHON_PROBLEM = (
|
|
21
21
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
22
22
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -10,13 +10,13 @@ import sys
|
|
|
10
10
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
11
11
|
# Name the real cause instead. Kept in sync with
|
|
12
12
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
14
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
15
15
|
#
|
|
16
16
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
17
17
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
18
18
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
19
|
-
if sys.version_info < (3, 11):
|
|
19
|
+
if tuple(sys.version_info) < (3, 11):
|
|
20
20
|
_MAP_PYTHON_PROBLEM = (
|
|
21
21
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
22
22
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -10,13 +10,13 @@ import sys
|
|
|
10
10
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
11
11
|
# Name the real cause instead. Kept in sync with
|
|
12
12
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
14
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
15
15
|
#
|
|
16
16
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
17
17
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
18
18
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
19
|
-
if sys.version_info < (3, 11):
|
|
19
|
+
if tuple(sys.version_info) < (3, 11):
|
|
20
20
|
_MAP_PYTHON_PROBLEM = (
|
|
21
21
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
22
22
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -41,13 +41,13 @@ import sys
|
|
|
41
41
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
42
42
|
# Name the real cause instead. Kept in sync with
|
|
43
43
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
44
|
-
#
|
|
45
|
-
#
|
|
44
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
45
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
46
46
|
#
|
|
47
47
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
48
48
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
49
49
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
50
|
-
if sys.version_info < (3, 11):
|
|
50
|
+
if tuple(sys.version_info) < (3, 11):
|
|
51
51
|
_MAP_PYTHON_PROBLEM = (
|
|
52
52
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
53
53
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -20,13 +20,13 @@ import sys
|
|
|
20
20
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
21
21
|
# Name the real cause instead. Kept in sync with
|
|
22
22
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
23
|
-
#
|
|
24
|
-
#
|
|
23
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
24
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
25
25
|
#
|
|
26
26
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
27
27
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
28
28
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
29
|
-
if sys.version_info < (3, 11):
|
|
29
|
+
if tuple(sys.version_info) < (3, 11):
|
|
30
30
|
_MAP_PYTHON_PROBLEM = (
|
|
31
31
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
32
32
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -20,13 +20,13 @@ import sys
|
|
|
20
20
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
21
21
|
# Name the real cause instead. Kept in sync with
|
|
22
22
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
23
|
-
#
|
|
24
|
-
#
|
|
23
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
24
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
25
25
|
#
|
|
26
26
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
27
27
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
28
28
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
29
|
-
if sys.version_info < (3, 11):
|
|
29
|
+
if tuple(sys.version_info) < (3, 11):
|
|
30
30
|
_MAP_PYTHON_PROBLEM = (
|
|
31
31
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
32
32
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -25,13 +25,13 @@ import sys
|
|
|
25
25
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
26
26
|
# Name the real cause instead. Kept in sync with
|
|
27
27
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
28
|
-
#
|
|
29
|
-
#
|
|
28
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
29
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
30
30
|
#
|
|
31
31
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
32
32
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
33
33
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
34
|
-
if sys.version_info < (3, 11):
|
|
34
|
+
if tuple(sys.version_info) < (3, 11):
|
|
35
35
|
_MAP_PYTHON_PROBLEM = (
|
|
36
36
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
37
37
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -19,13 +19,13 @@ import sys
|
|
|
19
19
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
20
20
|
# Name the real cause instead. Kept in sync with
|
|
21
21
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
22
|
-
#
|
|
23
|
-
#
|
|
22
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
23
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
24
24
|
#
|
|
25
25
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
26
26
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
27
27
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
28
|
-
if sys.version_info < (3, 11):
|
|
28
|
+
if tuple(sys.version_info) < (3, 11):
|
|
29
29
|
_MAP_PYTHON_PROBLEM = (
|
|
30
30
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
31
31
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -24,8 +24,8 @@ import sys
|
|
|
24
24
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
25
25
|
# Name the real cause instead. Kept in sync with
|
|
26
26
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
27
|
-
#
|
|
28
|
-
#
|
|
27
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
28
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
29
29
|
#
|
|
30
30
|
# FAIL-CLOSED mode. This file is a blocking PreToolUse gate whose only job is to
|
|
31
31
|
# refuse unsafe tool calls, so an interpreter it cannot run on must not degrade
|
|
@@ -34,7 +34,7 @@ import sys
|
|
|
34
34
|
# how a PreToolUse hook blocks), so the call stops and the reason -- version,
|
|
35
35
|
# interpreter, fix -- reaches the operator. Fix python3 in another terminal;
|
|
36
36
|
# tool calls stay blocked until `python3 --version` reports 3.11+.
|
|
37
|
-
if sys.version_info < (3, 11):
|
|
37
|
+
if tuple(sys.version_info) < (3, 11):
|
|
38
38
|
_MAP_PYTHON_PROBLEM = (
|
|
39
39
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
40
40
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -14,12 +14,16 @@ Gating (no-op in ~all turns):
|
|
|
14
14
|
1. ``MAP_INVOKED_BY`` set -> exit (don't run inside a sub-agent).
|
|
15
15
|
2. no ``.map/<branch>/step_state.json`` OR ``workflow_status`` is not
|
|
16
16
|
``WORKFLOW_COMPLETE`` -> exit (run not finished).
|
|
17
|
-
3.
|
|
18
|
-
|
|
17
|
+
3. no ``.map/<branch>/run_health_report.json`` -> exit (final verification
|
|
18
|
+
not yet complete; ``workflow_status`` transitions to ``WORKFLOW_COMPLETE``
|
|
19
|
+
before the final-verifier step, so we gate on the health report instead).
|
|
20
|
+
4. marker ``.map/<branch>/.scrub_done`` present -> exit (already ran once).
|
|
21
|
+
5. ``scrub_internal_ids: false`` in ``.map/config.yaml`` -> exit (opt-out).
|
|
19
22
|
|
|
20
|
-
When it does run: calls the engine in ``clean`` mode,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
When it does run: calls the engine in ``clean`` mode, leaves any cleaned files
|
|
24
|
+
unstaged, prints a short ``stderr`` reminder to the operator, and writes the
|
|
25
|
+
marker so it fires exactly once. The operator decides how and whether to commit
|
|
26
|
+
the changes (preserving the host repository's commit conventions).
|
|
23
27
|
|
|
24
28
|
Synchronous by design (justified exception to the async-hook rule): the scrub
|
|
25
29
|
must finish and commit before the run is considered done; a detached run would
|
|
@@ -39,13 +43,13 @@ import sys
|
|
|
39
43
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
40
44
|
# Name the real cause instead. Kept in sync with
|
|
41
45
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
42
|
-
#
|
|
43
|
-
#
|
|
46
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
47
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
44
48
|
#
|
|
45
49
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
46
50
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
47
51
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
48
|
-
if sys.version_info < (3, 11):
|
|
52
|
+
if tuple(sys.version_info) < (3, 11):
|
|
49
53
|
_MAP_PYTHON_PROBLEM = (
|
|
50
54
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
51
55
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -135,6 +139,13 @@ def main() -> None:
|
|
|
135
139
|
if status != "WORKFLOW_COMPLETE":
|
|
136
140
|
_silent()
|
|
137
141
|
|
|
142
|
+
# Gate on run_health_report.json: written after the final-verifier step.
|
|
143
|
+
# workflow_status becomes WORKFLOW_COMPLETE before final verification, so
|
|
144
|
+
# we wait for the health report to avoid scrubbing while the verifier is
|
|
145
|
+
# reading HEAD.
|
|
146
|
+
if not (branch_dir / "run_health_report.json").exists():
|
|
147
|
+
_silent()
|
|
148
|
+
|
|
138
149
|
marker = branch_dir / ".scrub_done"
|
|
139
150
|
if marker.exists():
|
|
140
151
|
_silent()
|
|
@@ -162,17 +173,16 @@ def main() -> None:
|
|
|
162
173
|
report = {}
|
|
163
174
|
|
|
164
175
|
modified = report.get("files_modified") or []
|
|
176
|
+
# Leave cleaned files unstaged so the operator can review and commit them
|
|
177
|
+
# using the host repository's conventions (ticket ID, sign-off, etc.).
|
|
178
|
+
# Never auto-commit with a fixed message.
|
|
165
179
|
if modified:
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
["git", "commit", "-m", "chore(map): strip internal workflow IDs"],
|
|
171
|
-
cwd=PROJECT_DIR, env=env, capture_output=True, text=True, timeout=30,
|
|
172
|
-
check=False,
|
|
180
|
+
sys.stderr.write(
|
|
181
|
+
"[scrub-internal-ids] cleaned {} file(s) — review and commit with "
|
|
182
|
+
"your project's conventions:\n git add -- {}\n".format(
|
|
183
|
+
len(modified), " ".join(modified)
|
|
173
184
|
)
|
|
174
|
-
|
|
175
|
-
pass # leave the cleaned working tree in place; never block
|
|
185
|
+
)
|
|
176
186
|
|
|
177
187
|
# Mark done so the scrub fires exactly once for this completed run.
|
|
178
188
|
try:
|
|
@@ -25,13 +25,13 @@ import sys
|
|
|
25
25
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
26
26
|
# Name the real cause instead. Kept in sync with
|
|
27
27
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
28
|
-
#
|
|
29
|
-
#
|
|
28
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
29
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
30
30
|
#
|
|
31
31
|
# FAIL-OPEN mode. Exit 1 is a non-blocking hook error for Claude Code (only
|
|
32
32
|
# exit 2, or a JSON deny, blocks a tool call), so the reason reaches the user
|
|
33
33
|
# and the session continues -- a broken interpreter is not a policy decision.
|
|
34
|
-
if sys.version_info < (3, 11):
|
|
34
|
+
if tuple(sys.version_info) < (3, 11):
|
|
35
35
|
_MAP_PYTHON_PROBLEM = (
|
|
36
36
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
37
37
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -45,8 +45,8 @@ import sys
|
|
|
45
45
|
# evaluated annotations) fails with a message that never mentions the version.
|
|
46
46
|
# Name the real cause instead. Kept in sync with
|
|
47
47
|
# mapify_cli/python_runtime.MINIMUM_PYTHON.
|
|
48
|
-
#
|
|
49
|
-
#
|
|
48
|
+
# Compare the runtime tuple: the executing interpreter is the user's `python3`,
|
|
49
|
+
# not necessarily the Python version targeted by the project's static checker.
|
|
50
50
|
#
|
|
51
51
|
# FAIL-CLOSED mode. This file is a blocking PreToolUse gate whose only job is to
|
|
52
52
|
# refuse unsafe tool calls, so an interpreter it cannot run on must not degrade
|
|
@@ -55,7 +55,7 @@ import sys
|
|
|
55
55
|
# how a PreToolUse hook blocks), so the call stops and the reason -- version,
|
|
56
56
|
# interpreter, fix -- reaches the operator. Fix python3 in another terminal;
|
|
57
57
|
# tool calls stay blocked until `python3 --version` reports 3.11+.
|
|
58
|
-
if sys.version_info < (3, 11):
|
|
58
|
+
if tuple(sys.version_info) < (3, 11):
|
|
59
59
|
_MAP_PYTHON_PROBLEM = (
|
|
60
60
|
f"MAP requires Python 3.11 or newer, but {sys.executable} is "
|
|
61
61
|
f"Python {sys.version_info[0]}.{sys.version_info[1]}.\n"
|
|
@@ -96,7 +96,7 @@ Resolve pending approval holds before `resume_from_plan` initializes any executi
|
|
|
96
96
|
python3 .map/scripts/map_step_runner.py list_approval_holds --state pending
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
A
|
|
99
|
+
A ready plan needs no approval. A pending `plan_approval` (left by an older `$map-plan`) is not a gate: do not ask — close it via `decide_approval_hold <hold-id> approved --note "plan_approval no longer gates execution"` and continue into Step 0. A pending `dangerous_action`/`safety_guardrail` hold refuses to proceed instead — surface the hold's `reason` and stop.
|
|
100
100
|
|
|
101
101
|
## Step 0: Resume Existing State Or Plan
|
|
102
102
|
|
|
@@ -6,9 +6,8 @@ Load only the section needed by the active phase.
|
|
|
6
6
|
## Approval-Hold Preflight
|
|
7
7
|
|
|
8
8
|
Resolve any pending approval hold BEFORE Step 0's `resume_from_plan`
|
|
9
|
-
bootstraps execution state
|
|
10
|
-
|
|
11
|
-
`step_state.json` exists.
|
|
9
|
+
bootstraps execution state. A ready plan itself needs no approval —
|
|
10
|
+
`$map-plan` no longer opens a hold.
|
|
12
11
|
|
|
13
12
|
```bash
|
|
14
13
|
python3 .map/scripts/map_step_runner.py list_approval_holds --state pending
|
|
@@ -16,31 +15,20 @@ python3 .map/scripts/map_step_runner.py list_approval_holds --state pending
|
|
|
16
15
|
|
|
17
16
|
Each pending hold's `kind` decides the branch:
|
|
18
17
|
|
|
19
|
-
- **`plan_approval`**
|
|
20
|
-
|
|
18
|
+
- **`plan_approval`** (left by an older `$map-plan`) — not a gate. Do not
|
|
19
|
+
ask the operator; close it and continue:
|
|
21
20
|
```bash
|
|
22
21
|
python3 .map/scripts/map_step_runner.py decide_approval_hold \
|
|
23
|
-
<hold-id> approved --note "
|
|
24
|
-
# or:
|
|
25
|
-
python3 .map/scripts/map_step_runner.py decide_approval_hold \
|
|
26
|
-
<hold-id> denied --note "<why the plan was denied>"
|
|
22
|
+
<hold-id> approved --note "plan_approval no longer gates execution"
|
|
27
23
|
```
|
|
28
|
-
- **Approved** — continue into the pre-flight test baseline below.
|
|
29
|
-
- **Denied** — STOP. Tell the operator to revise the plan and re-run
|
|
30
|
-
`$map-plan`; there is no staleness re-check against the denied blueprint
|
|
31
|
-
— the operator who denied it is the same operator re-running
|
|
32
|
-
`$map-efficient`.
|
|
33
24
|
- **`dangerous_action` / `safety_guardrail`** (hard stops) — never decide
|
|
34
25
|
these from inside the preflight. Refuse to proceed: surface the hold's
|
|
35
26
|
`reason` and `request_summary`, and stop. The operator resolves the
|
|
36
27
|
underlying issue out of band and decides the hold via `decide_approval_hold`
|
|
37
28
|
before retrying.
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
starts, so the preflight here finds nothing pending. If the operator
|
|
42
|
-
already decided the hold manually (CLI) before starting `$map-efficient`, the
|
|
43
|
-
preflight likewise finds nothing pending and proceeds without asking.
|
|
30
|
+
If the operator already decided a hold manually (CLI) before starting
|
|
31
|
+
`$map-efficient`, the preflight finds nothing pending and proceeds.
|
|
44
32
|
|
|
45
33
|
## Pre-Monitor Gates
|
|
46
34
|
|
|
@@ -130,6 +130,18 @@ that the PRD became ready.
|
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
+
## Pre-flight: Wayfinding Handoff (optional)
|
|
134
|
+
|
|
135
|
+
A handoff seeds a fresh plan ONLY after Resume Detection returns `no_plan` (or after operator-confirmed archival resolves `goal_mismatch`). On `resume`, existing spec/task-plan wins and the handoff is NOT re-consumed; never overwrite an in-progress plan by re-seeding.
|
|
136
|
+
|
|
137
|
+
- For explicit `--wayfind <slug>`, select `.map/wayfind/<slug>/handoff.json` (repo-level).
|
|
138
|
+
- Otherwise run `python3 .map/scripts/wayfind_runner.py list_handoffs`; exactly one completed handoff may be offered, but consume only on an explicit user yes. Never guess a match; zero/multiple handoffs means skip.
|
|
139
|
+
- For BOTH explicit and user-accepted offered handoffs, run `python3 .map/scripts/wayfind_runner.py validate_wayfind_handoff <slug>` immediately before seeding. Non-success → STOP: stale, tampered, missing or actively corrected managed evidence is not settled input. Success with `evidence_status: legacy_unrecorded` → surface the provenance warning, never call it verified. Validation is read-only and proves integrity, not truth; do not repair or migrate the map on read.
|
|
140
|
+
|
|
141
|
+
When a handoff is used, pre-seed the spec: `decisions[]` → **Decisions Made** (settled; do not re-ask), `out_of_scope[]` → **Out of Scope**, `remaining_risks[]` → **Open Questions**. Unresolved research and corrections in risks are not decisions. Continue for anything the handoff did not settle; never modify the wayfinding map.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
133
145
|
## Pre-flight: Workflow-Fit Gate
|
|
134
146
|
|
|
135
147
|
Assess whether MAP planning is warranted. Evaluate these signals:
|
|
@@ -773,13 +785,9 @@ Record artifacts in the manifest:
|
|
|
773
785
|
```
|
|
774
786
|
exec_command:
|
|
775
787
|
cmd: |
|
|
776
|
-
|
|
777
|
-
printf '%s\n' "$PLAN_ARTIFACTS_RESULT"
|
|
778
|
-
PLAN_APPROVAL_HOLD_ID=$(printf '%s' "$PLAN_ARTIFACTS_RESULT" | jq -r '.plan_approval_hold_id // empty')
|
|
788
|
+
python3 .map/scripts/map_step_runner.py record_plan_artifacts
|
|
779
789
|
```
|
|
780
790
|
|
|
781
|
-
`record_plan_artifacts` also opens a `plan_approval` hold at the plan-ready boundary and returns it as `plan_approval_hold_id` (idempotent — re-running finds the same pending hold instead of spamming a new one). Capture `PLAN_APPROVAL_HOLD_ID` for the Step 8 checkpoint. This hold does **not** block `$map-plan` itself: planning artifacts are written and Step 8 prints its checkpoint regardless of whether the hold is still pending. The decision (`decide_approval_hold <hold-id> approved|denied`) happens later, at the `$map-efficient` approval-hold preflight — or automatically via an autonomous chain's `auto_decide_holds` poll. If the result instead carries `plan_approval_hold_error: true`, the hold store failed — say so in the Step 8 checkpoint and have the operator create/decide the hold manually (`create_approval_hold --kind plan_approval ...`).
|
|
782
|
-
|
|
783
791
|
---
|
|
784
792
|
|
|
785
793
|
## Step 8: Output Checkpoint
|
|
@@ -804,7 +812,6 @@ exec_command:
|
|
|
804
812
|
echo "[ok] Plan written to .map/${BRANCH}/task_plan_${BRANCH}.md"
|
|
805
813
|
echo "[ok] artifact_manifest.json updated"
|
|
806
814
|
echo "[ok] Mode: [standard | light | deep]"
|
|
807
|
-
echo "[ok] Plan approval hold: ${PLAN_APPROVAL_HOLD_ID:-none} — decide via decide_approval_hold <hold-id> <approved|denied> --note \"<operator note>\" before \$map-efficient will proceed"
|
|
808
815
|
echo ""
|
|
809
816
|
echo "Next steps:"
|
|
810
817
|
echo " 1. Review .map/${BRANCH}/task_plan_${BRANCH}.md"
|
|
@@ -73,7 +73,7 @@ Execute all 12 gates. Read the full gate scripts in [release-reference.md § Pha
|
|
|
73
73
|
- **Gates 5–6:** Build + twine check
|
|
74
74
|
- **Gate 7:** Security audit (`pip-audit`)
|
|
75
75
|
- **Gates 8–10:** Git state — main branch, clean working directory, up-to-date with origin
|
|
76
|
-
- **Gate 11:**
|
|
76
|
+
- **Gate 11:** CI run for `git merge-base HEAD origin/main` must have `conclusion: "success"`; unpushed commits may touch only release metadata
|
|
77
77
|
- **Gate 12:** CHANGELOG.md completeness (Unreleased section exists and has content; commit/entry gap check)
|
|
78
78
|
|
|
79
79
|
**If any gate fails:** ABORT. Fix issues, re-run Phase 1.
|
|
@@ -81,27 +81,21 @@ Execute all 12 gates. Read the full gate scripts in [release-reference.md § Pha
|
|
|
81
81
|
## Phase 2: Version Determination
|
|
82
82
|
|
|
83
83
|
Read CHANGELOG.md `[Unreleased]` section to determine bump type (MAJOR/MINOR/PATCH/EXPLICIT).
|
|
84
|
-
Get current version from `pyproject.toml`.
|
|
84
|
+
Get current version from `pyproject.toml`.
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## Phase 3: Execute Version Bump Script
|
|
86
|
+
Ask the user directly for PATCH / MINOR / MAJOR / EXPLICIT, and wait for their answer.
|
|
89
87
|
|
|
90
|
-
|
|
88
|
+
For EXPLICIT, ask separately for the exact version. Carry only the user's approved
|
|
89
|
+
`BUMP_TYPE` and exact `NEW_VERSION` into Phase 3; each command runs in a fresh shell.
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
# Verify tag points to HEAD
|
|
94
|
-
TAG_COMMIT=$(git rev-list -n 1 "$LAST_TAG")
|
|
95
|
-
HEAD_COMMIT=$(git rev-parse HEAD)
|
|
96
|
-
[[ "$TAG_COMMIT" != "$HEAD_COMMIT" ]] && echo "❌ Tag mismatch" && exit 1
|
|
91
|
+
See [release-reference.md § Phase 2](release-reference.md#phase-2-version-determination) for the full question/option block.
|
|
97
92
|
|
|
98
|
-
|
|
99
|
-
INIT_VERSION=$(grep -m1 -E '^__version__ = ' src/mapify_cli/__init__.py | sed -E 's/__version__ = "(.*)"/\1/')
|
|
100
|
-
TAG_VERSION="${LAST_TAG#v}"
|
|
101
|
-
[[ "$INIT_VERSION" != "$TAG_VERSION" ]] && echo "❌ __version__ mismatch — fix manually, see reference" && exit 1
|
|
93
|
+
## Phase 3: Execute Version Bump Script
|
|
102
94
|
|
|
103
|
-
|
|
104
|
-
|
|
95
|
+
Show the exact approved version and bump type, then execute the Phase 3 reference
|
|
96
|
+
blocks with those values explicitly supplied in each invocation. Never rely on
|
|
97
|
+
variables left by a previous shell. Verify the version-derived `vX.Y.Z` tag points
|
|
98
|
+
to HEAD and both version fields match it using the Phase 3.3 reference block.
|
|
105
99
|
|
|
106
100
|
If `__version__` mismatches, follow the fix procedure in [release-reference.md § Phase 3 workaround](release-reference.md#phase-3-execute-version-bump-script).
|
|
107
101
|
|
|
@@ -109,25 +103,24 @@ If `__version__` mismatches, follow the fix procedure in [release-reference.md
|
|
|
109
103
|
|
|
110
104
|
**⚠️ CRITICAL PHASE:** Once the tag is pushed the release workflow triggers and publishes to PyPI.
|
|
111
105
|
|
|
112
|
-
Re-verify: on main branch,
|
|
106
|
+
Re-verify: on main branch, exact merge-base CI completed successfully with matching
|
|
107
|
+
`headSha`, only the three allowed metadata files changed, version-derived tag
|
|
108
|
+
points to HEAD and does not already exist on remote. Then request **explicit user
|
|
109
|
+
confirmation** (YES / NO / REVIEW options).
|
|
113
110
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
Ask the user directly and wait; only an unambiguous YES authorizes pushing.
|
|
112
|
+
|
|
113
|
+
Read [release-reference.md § Phase 4](release-reference.md#phase-4-push-commit-and-tag-irreversible)
|
|
114
|
+
for the confirmation and push blocks. Recompute the tag in the push invocation;
|
|
115
|
+
consent for an earlier version or commit does not authorize a changed release.
|
|
118
116
|
|
|
119
117
|
If user aborts: stop workflow, exit gracefully. Tag remains local only.
|
|
120
118
|
|
|
121
119
|
## Phase 5: CI/CD Monitoring
|
|
122
120
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
gh run list --workflow=release.yml --limit 1 --json databaseId,status,conclusion,createdAt
|
|
127
|
-
gh run watch "$RUN_ID"
|
|
128
|
-
FINAL_STATUS=$(gh run view "$RUN_ID" --json conclusion --jq '.conclusion')
|
|
129
|
-
[[ "$FINAL_STATUS" != "success" ]] && echo "❌ Release workflow failed — see reference for rollback" && exit 1
|
|
130
|
-
```
|
|
121
|
+
Use the Phase 5 reference block: recompute the version-derived tag and release
|
|
122
|
+
commit, select `release.yml` for that exact commit (not latest-main), derive
|
|
123
|
+
`RUN_ID` in the same shell, then watch and validate the final status and `headSha`.
|
|
131
124
|
|
|
132
125
|
The GitHub Release is created automatically by the workflow (no manual step).
|
|
133
126
|
|