agentic-project-kit 1.0.1__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.
- agentic_project_kit/__init__.py +1 -0
- agentic_project_kit/absolute_path_portability_audit.py +241 -0
- agentic_project_kit/access_level_policy.py +14 -0
- agentic_project_kit/access_levels.py +22 -0
- agentic_project_kit/action_registry.py +195 -0
- agentic_project_kit/action_specs.py +286 -0
- agentic_project_kit/agent_command_runner.py +516 -0
- agentic_project_kit/audit_test_matrix.py +36 -0
- agentic_project_kit/audit_test_matrix_cli.py +43 -0
- agentic_project_kit/chat_bootloader.py +257 -0
- agentic_project_kit/chat_entrypoint_contract.py +297 -0
- agentic_project_kit/checks.py +511 -0
- agentic_project_kit/ci_readiness.py +211 -0
- agentic_project_kit/cli.py +147 -0
- agentic_project_kit/cli_commands/__init__.py +1 -0
- agentic_project_kit/cli_commands/absolute_path_audit.py +25 -0
- agentic_project_kit/cli_commands/actions.py +21 -0
- agentic_project_kit/cli_commands/artifact_gc.py +240 -0
- agentic_project_kit/cli_commands/boot.py +55 -0
- agentic_project_kit/cli_commands/chat.py +34 -0
- agentic_project_kit/cli_commands/checks.py +305 -0
- agentic_project_kit/cli_commands/cockpit.py +103 -0
- agentic_project_kit/cli_commands/command_taxonomy.py +25 -0
- agentic_project_kit/cli_commands/commands.py +129 -0
- agentic_project_kit/cli_commands/dev.py +23 -0
- agentic_project_kit/cli_commands/direction.py +92 -0
- agentic_project_kit/cli_commands/doc_currency_audit.py +25 -0
- agentic_project_kit/cli_commands/doc_registry.py +126 -0
- agentic_project_kit/cli_commands/docs.py +223 -0
- agentic_project_kit/cli_commands/dpa.py +1338 -0
- agentic_project_kit/cli_commands/evidence.py +251 -0
- agentic_project_kit/cli_commands/github.py +34 -0
- agentic_project_kit/cli_commands/governance.py +14 -0
- agentic_project_kit/cli_commands/gui.py +23 -0
- agentic_project_kit/cli_commands/gui_readiness_gate.py +27 -0
- agentic_project_kit/cli_commands/handoff.py +183 -0
- agentic_project_kit/cli_commands/human_workflows.py +430 -0
- agentic_project_kit/cli_commands/init.py +132 -0
- agentic_project_kit/cli_commands/instruction.py +75 -0
- agentic_project_kit/cli_commands/mutation_lock_audit.py +24 -0
- agentic_project_kit/cli_commands/ns_legacy_audit.py +25 -0
- agentic_project_kit/cli_commands/pass_already_done.py +66 -0
- agentic_project_kit/cli_commands/patch_failure_discipline_audit.py +26 -0
- agentic_project_kit/cli_commands/patch_preflight.py +37 -0
- agentic_project_kit/cli_commands/path_literal_audit.py +39 -0
- agentic_project_kit/cli_commands/patterns.py +40 -0
- agentic_project_kit/cli_commands/planning_docs_audit.py +25 -0
- agentic_project_kit/cli_commands/pr.py +133 -0
- agentic_project_kit/cli_commands/pr_hygiene.py +27 -0
- agentic_project_kit/cli_commands/profiles.py +26 -0
- agentic_project_kit/cli_commands/program_redundancy_audit.py +25 -0
- agentic_project_kit/cli_commands/project_direction.py +25 -0
- agentic_project_kit/cli_commands/release.py +392 -0
- agentic_project_kit/cli_commands/release_publish_orchestration.py +36 -0
- agentic_project_kit/cli_commands/remote_branch_hygiene.py +152 -0
- agentic_project_kit/cli_commands/remote_next.py +57 -0
- agentic_project_kit/cli_commands/removed_ns_commands.py +65 -0
- agentic_project_kit/cli_commands/rule_registry.py +129 -0
- agentic_project_kit/cli_commands/rules.py +222 -0
- agentic_project_kit/cli_commands/scaffold.py +46 -0
- agentic_project_kit/cli_commands/slice.py +21 -0
- agentic_project_kit/cli_commands/standard_gates_audit_suite.py +27 -0
- agentic_project_kit/cli_commands/state.py +51 -0
- agentic_project_kit/cli_commands/status_current_state_audit.py +30 -0
- agentic_project_kit/cli_commands/todo.py +53 -0
- agentic_project_kit/cli_commands/transfer.py +19 -0
- agentic_project_kit/cli_commands/transfer_context_flow.py +398 -0
- agentic_project_kit/cli_commands/transfer_context_helpers.py +398 -0
- agentic_project_kit/cli_commands/transfer_diagnostics.py +767 -0
- agentic_project_kit/cli_commands/transfer_evidence_flow.py +368 -0
- agentic_project_kit/cli_commands/transfer_handoff_flow.py +594 -0
- agentic_project_kit/cli_commands/transfer_order_contract.py +74 -0
- agentic_project_kit/cli_commands/transfer_post_merge_complete.py +442 -0
- agentic_project_kit/cli_commands/transfer_post_merge_settle.py +171 -0
- agentic_project_kit/cli_commands/transfer_pr_closeout_complete.py +124 -0
- agentic_project_kit/cli_commands/transfer_pr_create_flow.py +743 -0
- agentic_project_kit/cli_commands/transfer_pr_merge_flow.py +547 -0
- agentic_project_kit/cli_commands/transfer_repo_after_pr.py +160 -0
- agentic_project_kit/cli_commands/transfer_repo_pre_pr.py +664 -0
- agentic_project_kit/cli_commands/transfer_runner_flow.py +131 -0
- agentic_project_kit/cli_commands/transfer_runtime_initial.py +194 -0
- agentic_project_kit/cli_commands/transfer_shared.py +274 -0
- agentic_project_kit/cli_commands/validation.py +200 -0
- agentic_project_kit/cli_commands/version.py +27 -0
- agentic_project_kit/cli_commands/work_orders.py +219 -0
- agentic_project_kit/cli_commands/workflow.py +471 -0
- agentic_project_kit/cli_commands/workflow_guard.py +26 -0
- agentic_project_kit/cli_commands/workspace.py +252 -0
- agentic_project_kit/cockpit.py +608 -0
- agentic_project_kit/cockpit_readiness.py +67 -0
- agentic_project_kit/command_authority_audit.py +192 -0
- agentic_project_kit/command_inbox_check.py +103 -0
- agentic_project_kit/command_manifest.py +591 -0
- agentic_project_kit/command_queue_contract.py +161 -0
- agentic_project_kit/command_selector.py +245 -0
- agentic_project_kit/command_taxonomy.py +264 -0
- agentic_project_kit/commit_guard.py +67 -0
- agentic_project_kit/communication_artifact_gc.py +495 -0
- agentic_project_kit/communication_rule_context.py +437 -0
- agentic_project_kit/communication_state.py +115 -0
- agentic_project_kit/composed_wrapper_invariants.py +97 -0
- agentic_project_kit/composite_short_circuit.py +140 -0
- agentic_project_kit/contract.py +251 -0
- agentic_project_kit/control_state.py +83 -0
- agentic_project_kit/doc_currency_audit.py +536 -0
- agentic_project_kit/doc_lifecycle.py +1179 -0
- agentic_project_kit/doc_lifecycle_signals.py +446 -0
- agentic_project_kit/doc_lifecycle_sweep.py +639 -0
- agentic_project_kit/doc_mesh.py +491 -0
- agentic_project_kit/doctor.py +379 -0
- agentic_project_kit/documentation_registry.py +1122 -0
- agentic_project_kit/documentation_system_audit.py +310 -0
- agentic_project_kit/dpa_current_handoff_lifecycle.py +549 -0
- agentic_project_kit/dpa_dp2_decision_readiness.py +362 -0
- agentic_project_kit/dpa_dp3_dp4_adjudication.py +604 -0
- agentic_project_kit/dpa_dp5_block_new_gate.py +294 -0
- agentic_project_kit/dpa_dp5_stage_adoption.py +615 -0
- agentic_project_kit/dpa_dp5_strict_gate.py +187 -0
- agentic_project_kit/dpa_final_closeout.py +627 -0
- agentic_project_kit/dpa_fixture_evidence.py +680 -0
- agentic_project_kit/dpa_maintainer_record_check.py +711 -0
- agentic_project_kit/dpa_post_dp2_scope_assessment.py +734 -0
- agentic_project_kit/dpa_probe_002_readiness.py +509 -0
- agentic_project_kit/dpa_probe_003_readiness.py +417 -0
- agentic_project_kit/dpa_probe_004_readiness.py +437 -0
- agentic_project_kit/dpa_readiness.py +505 -0
- agentic_project_kit/dpa_readonly_probe_execution.py +500 -0
- agentic_project_kit/dpa_registry_contracts.py +312 -0
- agentic_project_kit/dpa_renderer_readiness.py +407 -0
- agentic_project_kit/dpa_repo_adoption_assessment.py +574 -0
- agentic_project_kit/dpa_stable_readiness.py +743 -0
- agentic_project_kit/dpa_successor_projection.py +168 -0
- agentic_project_kit/dpa_workspace_init_projection.py +93 -0
- agentic_project_kit/dpa_wrt_ch001_evidence.py +327 -0
- agentic_project_kit/entrypoint_slice_runner.py +153 -0
- agentic_project_kit/evidence_clean.py +152 -0
- agentic_project_kit/evidence_commit_paths.py +214 -0
- agentic_project_kit/evidence_finalize_log.py +204 -0
- agentic_project_kit/evidence_guard.py +114 -0
- agentic_project_kit/evidence_inspector.py +507 -0
- agentic_project_kit/evidence_state_contract.py +99 -0
- agentic_project_kit/execution_mode_state.py +148 -0
- agentic_project_kit/final_summary_contract.py +85 -0
- agentic_project_kit/finalize_guard.py +139 -0
- agentic_project_kit/gatekeeper_core.py +232 -0
- agentic_project_kit/github.py +25 -0
- agentic_project_kit/governance.py +59 -0
- agentic_project_kit/gui_action_execution.py +105 -0
- agentic_project_kit/gui_action_renderer.py +81 -0
- agentic_project_kit/gui_action_run_intent.py +98 -0
- agentic_project_kit/gui_action_views.py +195 -0
- agentic_project_kit/gui_activity_log.py +76 -0
- agentic_project_kit/gui_button_catalog.py +605 -0
- agentic_project_kit/gui_cockpit.py +365 -0
- agentic_project_kit/gui_cockpit_actions.py +695 -0
- agentic_project_kit/gui_cockpit_common.py +172 -0
- agentic_project_kit/gui_cockpit_header.py +501 -0
- agentic_project_kit/gui_cockpit_sidebar.py +387 -0
- agentic_project_kit/gui_cockpit_task.py +748 -0
- agentic_project_kit/gui_command_projection.py +355 -0
- agentic_project_kit/gui_communication_modes.py +130 -0
- agentic_project_kit/gui_dry_run.py +219 -0
- agentic_project_kit/gui_gatekeeper_status.py +259 -0
- agentic_project_kit/gui_layout_plan.py +148 -0
- agentic_project_kit/gui_open_folder.py +18 -0
- agentic_project_kit/gui_output_status_panel.py +61 -0
- agentic_project_kit/gui_panel_state.py +47 -0
- agentic_project_kit/gui_presenter.py +62 -0
- agentic_project_kit/gui_readiness_gate.py +206 -0
- agentic_project_kit/gui_release_flow.py +59 -0
- agentic_project_kit/gui_task_editor.py +1077 -0
- agentic_project_kit/gui_tk_widgets.py +177 -0
- agentic_project_kit/gui_tkinter_renderer.py +87 -0
- agentic_project_kit/gui_tkinter_shell.py +1176 -0
- agentic_project_kit/gui_transfer_contract.py +28 -0
- agentic_project_kit/gui_viewmodel.py +698 -0
- agentic_project_kit/gui_window_guard.py +46 -0
- agentic_project_kit/handoff_freshness.py +390 -0
- agentic_project_kit/handoff_prompt.py +180 -0
- agentic_project_kit/handoff_state.py +254 -0
- agentic_project_kit/instruction_lint.py +455 -0
- agentic_project_kit/llm_context_carriers.py +66 -0
- agentic_project_kit/llm_execution_context.py +285 -0
- agentic_project_kit/local_command_stack.py +133 -0
- agentic_project_kit/local_feature_gate.py +82 -0
- agentic_project_kit/local_garbage_collector.py +269 -0
- agentic_project_kit/models.py +18 -0
- agentic_project_kit/mutation_lock_audit.py +421 -0
- agentic_project_kit/next_turn_evidence.py +253 -0
- agentic_project_kit/next_turn_merge_if_green.py +459 -0
- agentic_project_kit/next_turn_pr_status.py +255 -0
- agentic_project_kit/next_turn_result.py +183 -0
- agentic_project_kit/next_turn_runner.py +159 -0
- agentic_project_kit/next_turn_slot.py +107 -0
- agentic_project_kit/next_turn_status.py +274 -0
- agentic_project_kit/ns_legacy_reference_audit.py +258 -0
- agentic_project_kit/ns_slice_runner.py +16 -0
- agentic_project_kit/operational_handoff_projection.py +124 -0
- agentic_project_kit/output_contract.py +80 -0
- agentic_project_kit/output_repair.py +61 -0
- agentic_project_kit/pass_already_done.py +216 -0
- agentic_project_kit/patch_artifact_preflight.py +147 -0
- agentic_project_kit/patch_cycle_workflow.py +440 -0
- agentic_project_kit/patch_failure_discipline_audit.py +223 -0
- agentic_project_kit/patch_preflight.py +215 -0
- agentic_project_kit/path_literal_audit.py +612 -0
- agentic_project_kit/patterns.py +99 -0
- agentic_project_kit/planning_docs_consolidation_audit.py +313 -0
- agentic_project_kit/portability_shell_gate.py +40 -0
- agentic_project_kit/post_merge_handoff_refresh.py +56 -0
- agentic_project_kit/post_release.py +252 -0
- agentic_project_kit/post_release_closeout.py +616 -0
- agentic_project_kit/pr_cleanup.py +172 -0
- agentic_project_kit/pr_closeout.py +50 -0
- agentic_project_kit/pr_closeout_complete.py +344 -0
- agentic_project_kit/pr_create_or_skip.py +71 -0
- agentic_project_kit/pr_hygiene.py +210 -0
- agentic_project_kit/program_redundancy_audit.py +251 -0
- agentic_project_kit/project_direction.py +840 -0
- agentic_project_kit/protected_change_planner.py +194 -0
- agentic_project_kit/release.py +401 -0
- agentic_project_kit/release_doi_safety.py +24 -0
- agentic_project_kit/release_gate_core.py +174 -0
- agentic_project_kit/release_metadata_authority_gate.py +328 -0
- agentic_project_kit/release_metadata_prep.py +43 -0
- agentic_project_kit/release_notes.py +823 -0
- agentic_project_kit/release_prep_core.py +204 -0
- agentic_project_kit/release_prepare.py +369 -0
- agentic_project_kit/release_process_guardrails.py +247 -0
- agentic_project_kit/release_publish_core.py +114 -0
- agentic_project_kit/release_publish_orchestration.py +469 -0
- agentic_project_kit/release_state.py +552 -0
- agentic_project_kit/release_verify_core.py +175 -0
- agentic_project_kit/remote_branch_hygiene.py +223 -0
- agentic_project_kit/remote_next.py +89 -0
- agentic_project_kit/remote_next_closeout.py +101 -0
- agentic_project_kit/remote_next_order_contract.py +391 -0
- agentic_project_kit/removed_ns_commands.py +458 -0
- agentic_project_kit/removed_source_audit.py +225 -0
- agentic_project_kit/rendering.py +13 -0
- agentic_project_kit/repair_report.py +79 -0
- agentic_project_kit/repo_identity.py +59 -0
- agentic_project_kit/result_report_classifier.py +57 -0
- agentic_project_kit/rule_ack.py +105 -0
- agentic_project_kit/rule_preservation.py +58 -0
- agentic_project_kit/rule_refresh.py +174 -0
- agentic_project_kit/rule_registry_registration.py +322 -0
- agentic_project_kit/rule_registry_report.py +206 -0
- agentic_project_kit/rule_registry_validator.py +704 -0
- agentic_project_kit/rule_snapshot.py +98 -0
- agentic_project_kit/rule_source_validator.py +133 -0
- agentic_project_kit/run_summary.py +68 -0
- agentic_project_kit/run_summary_renderer.py +238 -0
- agentic_project_kit/runtime_validator.py +68 -0
- agentic_project_kit/safe_file_replace.py +35 -0
- agentic_project_kit/safe_patch.py +47 -0
- agentic_project_kit/safe_push.py +218 -0
- agentic_project_kit/safe_remove_diagnostic.py +51 -0
- agentic_project_kit/scaffold.py +69 -0
- agentic_project_kit/site_claims.py +444 -0
- agentic_project_kit/site_generator.py +1140 -0
- agentic_project_kit/slice_gate.py +225 -0
- agentic_project_kit/slice_runner.py +75 -0
- agentic_project_kit/standard_gates_audit_suite.py +167 -0
- agentic_project_kit/state_freshness.py +135 -0
- agentic_project_kit/status_current_state_audit.py +762 -0
- agentic_project_kit/successor_handoff_package.py +1763 -0
- agentic_project_kit/templates.py +292 -0
- agentic_project_kit/terminal_block_guard.py +166 -0
- agentic_project_kit/terminal_logging.py +275 -0
- agentic_project_kit/todo.py +97 -0
- agentic_project_kit/transfer_closeout.py +136 -0
- agentic_project_kit/transfer_continue.py +215 -0
- agentic_project_kit/transfer_local_runner.py +101 -0
- agentic_project_kit/transfer_operation_monitor.py +236 -0
- agentic_project_kit/transfer_post_merge_lifecycle.py +356 -0
- agentic_project_kit/transfer_post_merge_settle.py +383 -0
- agentic_project_kit/transfer_pr_actions.py +164 -0
- agentic_project_kit/transfer_remote_next.py +959 -0
- agentic_project_kit/transfer_repo_actions.py +2253 -0
- agentic_project_kit/transfer_runner.py +347 -0
- agentic_project_kit/transfer_safety_context.py +291 -0
- agentic_project_kit/transfer_state.py +483 -0
- agentic_project_kit/transfer_uplink.py +471 -0
- agentic_project_kit/transfer_workflow_next.py +148 -0
- agentic_project_kit/typed_work_order_evidence.py +58 -0
- agentic_project_kit/typed_work_order_queue.py +166 -0
- agentic_project_kit/typed_work_order_runner.py +168 -0
- agentic_project_kit/work_cycle.py +317 -0
- agentic_project_kit/work_discard_changes.py +129 -0
- agentic_project_kit/work_order_patch.py +199 -0
- agentic_project_kit/work_order_runner.py +120 -0
- agentic_project_kit/work_order_uploader.py +220 -0
- agentic_project_kit/work_order_validator.py +185 -0
- agentic_project_kit/work_orders.py +246 -0
- agentic_project_kit/workflow_guard.py +262 -0
- agentic_project_kit/workflow_summary_runner.py +124 -0
- agentic_project_kit/workspace.py +665 -0
- agentic_project_kit/workspace_adopt.py +471 -0
- agentic_project_kit/workspace_dpa_intake.py +406 -0
- agentic_project_kit/workspace_init.py +487 -0
- agentic_project_kit/workspace_lock.py +129 -0
- agentic_project_kit/workspace_remove.py +381 -0
- agentic_project_kit/workspace_upgrade.py +324 -0
- agentic_project_kit/wrapper_live_status.py +104 -0
- agentic_project_kit-1.0.1.dist-info/METADATA +724 -0
- agentic_project_kit-1.0.1.dist-info/RECORD +310 -0
- agentic_project_kit-1.0.1.dist-info/WHEEL +4 -0
- agentic_project_kit-1.0.1.dist-info/entry_points.txt +3 -0
- agentic_project_kit-1.0.1.dist-info/licenses/LICENSE +10 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.1"
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import asdict, dataclass
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
ABSOLUTE_PATH_PATTERNS = (
|
|
9
|
+
re.compile(r"/Users/[A-Za-z0-9._-]+/[^\s`\"')]+"),
|
|
10
|
+
re.compile(r"/home/[A-Za-z0-9._-]+/[^\s`\"')]+"),
|
|
11
|
+
re.compile(r"(?<![\w.-])/tmp/[^\s`\"')]+"),
|
|
12
|
+
re.compile(r"/var/folders/[^\s`\"')]+"),
|
|
13
|
+
re.compile(r"/mnt/data/[^\s`\"')]+"),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
TEXT_SUFFIXES = {
|
|
17
|
+
".md",
|
|
18
|
+
".rst",
|
|
19
|
+
".txt",
|
|
20
|
+
".py",
|
|
21
|
+
".toml",
|
|
22
|
+
".yaml",
|
|
23
|
+
".yml",
|
|
24
|
+
".json",
|
|
25
|
+
".cff",
|
|
26
|
+
".sh",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
SKIP_DIR_PARTS = {
|
|
30
|
+
".git",
|
|
31
|
+
".venv",
|
|
32
|
+
"__pycache__",
|
|
33
|
+
".pytest_cache",
|
|
34
|
+
".ruff_cache",
|
|
35
|
+
".mypy_cache",
|
|
36
|
+
"node_modules",
|
|
37
|
+
"tmp",
|
|
38
|
+
"dist",
|
|
39
|
+
"build",
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
SKIP_DIR_PREFIXES = (
|
|
43
|
+
".venv",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
SKIP_FILENAMES = {
|
|
47
|
+
"Screen-Control_Output.txt",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
SKIP_PATH_PREFIXES = (
|
|
51
|
+
"docs/reports/",
|
|
52
|
+
".agentic/transfer/outbox/",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
SAFE_PATH_PREFIXES = (
|
|
56
|
+
"tests/",
|
|
57
|
+
"docs/reports/",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
SAFE_PATHS = {
|
|
61
|
+
"README.md",
|
|
62
|
+
"docs/STATUS.md",
|
|
63
|
+
"docs/handoff/CURRENT_HANDOFF.md",
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
HISTORICAL_MARKERS = (
|
|
67
|
+
"historical",
|
|
68
|
+
"legacy",
|
|
69
|
+
"obsolete",
|
|
70
|
+
"removed",
|
|
71
|
+
"deprecated",
|
|
72
|
+
"archived",
|
|
73
|
+
"archive",
|
|
74
|
+
"example",
|
|
75
|
+
"fixture",
|
|
76
|
+
"test",
|
|
77
|
+
"log",
|
|
78
|
+
"evidence",
|
|
79
|
+
"sandbox",
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True)
|
|
84
|
+
class AbsolutePathReference:
|
|
85
|
+
path: str
|
|
86
|
+
line: int
|
|
87
|
+
text: str
|
|
88
|
+
match: str
|
|
89
|
+
classification: str
|
|
90
|
+
reason: str
|
|
91
|
+
|
|
92
|
+
def as_dict(self) -> dict[str, object]:
|
|
93
|
+
return asdict(self)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass(frozen=True)
|
|
97
|
+
class AbsolutePathAuditResult:
|
|
98
|
+
root: str
|
|
99
|
+
references: tuple[AbsolutePathReference, ...]
|
|
100
|
+
blockers: tuple[AbsolutePathReference, ...]
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def ok(self) -> bool:
|
|
104
|
+
return not self.blockers
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def status(self) -> str:
|
|
108
|
+
return "PASS" if self.ok else "FAIL"
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def returncode(self) -> int:
|
|
112
|
+
return 0 if self.ok else 1
|
|
113
|
+
|
|
114
|
+
def as_dict(self) -> dict[str, object]:
|
|
115
|
+
return {
|
|
116
|
+
"schema_version": 1,
|
|
117
|
+
"kind": "absolute_path_portability_audit",
|
|
118
|
+
"root": self.root,
|
|
119
|
+
"status": self.status,
|
|
120
|
+
"reference_count": len(self.references),
|
|
121
|
+
"blocker_count": len(self.blockers),
|
|
122
|
+
"references": [item.as_dict() for item in self.references],
|
|
123
|
+
"blockers": [item.as_dict() for item in self.blockers],
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _is_text_file(path: Path) -> bool:
|
|
128
|
+
return path.suffix in TEXT_SUFFIXES
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _iter_candidate_files(root: Path) -> list[Path]:
|
|
132
|
+
files: list[Path] = []
|
|
133
|
+
for path in root.rglob("*"):
|
|
134
|
+
if not path.is_file():
|
|
135
|
+
continue
|
|
136
|
+
relative = path.relative_to(root).as_posix()
|
|
137
|
+
relative_parts = path.relative_to(root).parts
|
|
138
|
+
if path.name in SKIP_FILENAMES:
|
|
139
|
+
continue
|
|
140
|
+
if any(part in SKIP_DIR_PARTS for part in relative_parts):
|
|
141
|
+
continue
|
|
142
|
+
if any(part.startswith(prefix) for part in relative_parts for prefix in SKIP_DIR_PREFIXES):
|
|
143
|
+
continue
|
|
144
|
+
if any(relative.startswith(prefix) for prefix in SKIP_PATH_PREFIXES):
|
|
145
|
+
continue
|
|
146
|
+
if not _is_text_file(path):
|
|
147
|
+
continue
|
|
148
|
+
files.append(path)
|
|
149
|
+
return sorted(files)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _classify(relative: str, line: str, match: str) -> tuple[str, str]:
|
|
153
|
+
lowered = line.lower()
|
|
154
|
+
|
|
155
|
+
if relative == "src/agentic_project_kit/absolute_path_portability_audit.py":
|
|
156
|
+
return "audit_implementation", "absolute path tokens are classifier patterns, not user-facing paths"
|
|
157
|
+
|
|
158
|
+
if relative.startswith(SAFE_PATH_PREFIXES):
|
|
159
|
+
return "safe_generated_or_test_context", "test/generated context"
|
|
160
|
+
|
|
161
|
+
if relative.startswith("tests/"):
|
|
162
|
+
return "test_fixture", "test fixture"
|
|
163
|
+
|
|
164
|
+
if relative.startswith(("src/", "tools/")):
|
|
165
|
+
return "absolute_path_blocker", (
|
|
166
|
+
"source/tool files must not contain user-specific absolute paths; "
|
|
167
|
+
"line-level historical words are not enough to downgrade this"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
if relative in SAFE_PATHS and any(marker in lowered for marker in HISTORICAL_MARKERS):
|
|
171
|
+
return "historical_or_example_context", "stable doc with historical/example marker"
|
|
172
|
+
|
|
173
|
+
if any(marker in lowered for marker in HISTORICAL_MARKERS):
|
|
174
|
+
return "historical_or_example_context", "line contains historical/example/evidence marker"
|
|
175
|
+
|
|
176
|
+
if match.startswith("/tmp/") or match.startswith("/mnt/data/") or match.startswith("/var/folders/"):
|
|
177
|
+
return "transient_path_reference", "transient local path should not be current repo contract"
|
|
178
|
+
|
|
179
|
+
return "absolute_path_blocker", "absolute local path may break portability"
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def audit_absolute_path_portability(root: Path = Path(".")) -> AbsolutePathAuditResult:
|
|
183
|
+
root = root.resolve()
|
|
184
|
+
references: list[AbsolutePathReference] = []
|
|
185
|
+
|
|
186
|
+
for path in _iter_candidate_files(root):
|
|
187
|
+
relative = path.relative_to(root).as_posix()
|
|
188
|
+
try:
|
|
189
|
+
lines = path.read_text(encoding="utf-8").splitlines()
|
|
190
|
+
except UnicodeDecodeError:
|
|
191
|
+
continue
|
|
192
|
+
|
|
193
|
+
for number, line in enumerate(lines, start=1):
|
|
194
|
+
for pattern in ABSOLUTE_PATH_PATTERNS:
|
|
195
|
+
for match in pattern.finditer(line):
|
|
196
|
+
matched = match.group(0)
|
|
197
|
+
classification, reason = _classify(relative, line, matched)
|
|
198
|
+
references.append(
|
|
199
|
+
AbsolutePathReference(
|
|
200
|
+
path=relative,
|
|
201
|
+
line=number,
|
|
202
|
+
text=line.strip(),
|
|
203
|
+
match=matched,
|
|
204
|
+
classification=classification,
|
|
205
|
+
reason=reason,
|
|
206
|
+
)
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
blockers = tuple(
|
|
210
|
+
ref
|
|
211
|
+
for ref in references
|
|
212
|
+
if ref.classification in {"absolute_path_blocker", "transient_path_reference"}
|
|
213
|
+
)
|
|
214
|
+
return AbsolutePathAuditResult(
|
|
215
|
+
root=root.as_posix(),
|
|
216
|
+
references=tuple(references),
|
|
217
|
+
blockers=blockers,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def render_absolute_path_portability_audit(result: AbsolutePathAuditResult) -> str:
|
|
222
|
+
lines = [
|
|
223
|
+
"ABSOLUTE_PATH_PORTABILITY_AUDIT",
|
|
224
|
+
f"STATUS={result.status}",
|
|
225
|
+
f"REFERENCE_COUNT={len(result.references)}",
|
|
226
|
+
f"BLOCKER_COUNT={len(result.blockers)}",
|
|
227
|
+
]
|
|
228
|
+
|
|
229
|
+
for ref in result.blockers:
|
|
230
|
+
lines.append(
|
|
231
|
+
"BLOCKER="
|
|
232
|
+
f"{ref.classification}|{ref.path}:{ref.line}|{ref.match}|{ref.text}"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
for ref in result.references:
|
|
236
|
+
lines.append(
|
|
237
|
+
"REFERENCE="
|
|
238
|
+
f"{ref.classification}|{ref.path}:{ref.line}|{ref.match}|{ref.text}"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
return "\n".join(lines) + "\n"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
|
|
5
|
+
from agentic_project_kit.access_levels import AccessLevel, meets_min_access
|
|
6
|
+
from agentic_project_kit.cockpit import CockpitAction
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def can_show_action(action: CockpitAction, level: AccessLevel) -> bool:
|
|
10
|
+
return meets_min_access(level, action.min_access_level)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def visible_actions(actions: Iterable[CockpitAction], level: AccessLevel) -> list[CockpitAction]:
|
|
14
|
+
return [action for action in actions if can_show_action(action, level)]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
AccessLevel = Literal["basic", "advanced", "maintainer"]
|
|
6
|
+
|
|
7
|
+
ACCESS_LEVEL_ORDER: tuple[AccessLevel, ...] = ("basic", "advanced", "maintainer")
|
|
8
|
+
DEFAULT_ACCESS_LEVEL: AccessLevel = "basic"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def access_level_rank(level: AccessLevel) -> int:
|
|
12
|
+
return ACCESS_LEVEL_ORDER.index(level)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def meets_min_access(current: AccessLevel, required: AccessLevel) -> bool:
|
|
16
|
+
return access_level_rank(current) >= access_level_rank(required)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def normalize_access_level(value: str | None) -> AccessLevel:
|
|
20
|
+
if value in ACCESS_LEVEL_ORDER:
|
|
21
|
+
return value
|
|
22
|
+
return DEFAULT_ACCESS_LEVEL
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""Static action metadata for local workflow and cockpit readiness.
|
|
2
|
+
|
|
3
|
+
This module is intentionally read-only: it describes known local actions but
|
|
4
|
+
does not execute shell commands, mutate git state, call GitHub, or publish releases.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class SafetyClass(str, Enum):
|
|
14
|
+
"""Coarse safety class for a local action."""
|
|
15
|
+
|
|
16
|
+
READ_ONLY = "read-only"
|
|
17
|
+
LOCAL_ONLY = "local-only"
|
|
18
|
+
REMOTE_MUTATION = "remote-mutation"
|
|
19
|
+
RELEASE_TAG_PUBLISH = "release-tag-publish"
|
|
20
|
+
MERGE_DELETE_CLOSE = "merge-delete-close"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class ActionMetadata:
|
|
25
|
+
"""Static metadata for one repo-local action."""
|
|
26
|
+
|
|
27
|
+
name: str
|
|
28
|
+
safety_class: SafetyClass
|
|
29
|
+
mutation_scope: str
|
|
30
|
+
dry_run_supported: bool
|
|
31
|
+
outcome_contract: tuple[str, ...]
|
|
32
|
+
summary: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
ACTIONS: tuple[ActionMetadata, ...] = (
|
|
36
|
+
ActionMetadata(
|
|
37
|
+
name="dev",
|
|
38
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
39
|
+
mutation_scope="none",
|
|
40
|
+
dry_run_supported=True,
|
|
41
|
+
outcome_contract=("PASS", "FAIL"),
|
|
42
|
+
summary="Run local deterministic development gates.",
|
|
43
|
+
),
|
|
44
|
+
ActionMetadata(
|
|
45
|
+
name="pr-cleanup",
|
|
46
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
47
|
+
mutation_scope="none",
|
|
48
|
+
dry_run_supported=True,
|
|
49
|
+
outcome_contract=("PASS", "FAIL"),
|
|
50
|
+
summary="Classify open pull requests without mutating them.",
|
|
51
|
+
),
|
|
52
|
+
ActionMetadata(
|
|
53
|
+
name="release-verify",
|
|
54
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
55
|
+
mutation_scope="none",
|
|
56
|
+
dry_run_supported=True,
|
|
57
|
+
outcome_contract=("PASS", "FAIL"),
|
|
58
|
+
summary="Verify an existing release and metadata state.",
|
|
59
|
+
),
|
|
60
|
+
ActionMetadata(
|
|
61
|
+
name="clean-evidence",
|
|
62
|
+
safety_class=SafetyClass.LOCAL_ONLY,
|
|
63
|
+
mutation_scope="working-tree-files",
|
|
64
|
+
dry_run_supported=False,
|
|
65
|
+
outcome_contract=("PASS", "FAIL"),
|
|
66
|
+
summary="Clean local evidence or generated files according to repo policy.",
|
|
67
|
+
),
|
|
68
|
+
ActionMetadata(
|
|
69
|
+
name="release-prep",
|
|
70
|
+
safety_class=SafetyClass.LOCAL_ONLY,
|
|
71
|
+
mutation_scope="version-and-release-metadata-files",
|
|
72
|
+
dry_run_supported=False,
|
|
73
|
+
outcome_contract=("PASS", "FAIL"),
|
|
74
|
+
summary="Prepare local release metadata before a release PR.",
|
|
75
|
+
),
|
|
76
|
+
ActionMetadata(
|
|
77
|
+
name="release-gate",
|
|
78
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
79
|
+
mutation_scope="none",
|
|
80
|
+
dry_run_supported=True,
|
|
81
|
+
outcome_contract=("PASS", "FAIL"),
|
|
82
|
+
summary="Verify release readiness without tagging or publishing.",
|
|
83
|
+
),
|
|
84
|
+
ActionMetadata(
|
|
85
|
+
name="finalize-guard",
|
|
86
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
87
|
+
mutation_scope="none",
|
|
88
|
+
dry_run_supported=True,
|
|
89
|
+
outcome_contract=("PASS_ALREADY_ON_MAIN", "PASS_NOOP_BRANCH", "PASS_SUPERSEDED", "PASS_NEEDS_PR", "FAIL_CONFLICT_RELEVANT", "FAIL_NEEDS_HUMAN_REVIEW"),
|
|
90
|
+
summary="Classify branch finalization state without merging or deleting.",
|
|
91
|
+
),
|
|
92
|
+
ActionMetadata(
|
|
93
|
+
name="doctor",
|
|
94
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
95
|
+
mutation_scope="none",
|
|
96
|
+
dry_run_supported=True,
|
|
97
|
+
outcome_contract=("PASS", "FAIL"),
|
|
98
|
+
summary="Run compact project health checks without mutating repository state.",
|
|
99
|
+
),
|
|
100
|
+
|
|
101
|
+
ActionMetadata(
|
|
102
|
+
name="check-docs",
|
|
103
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
104
|
+
mutation_scope="none",
|
|
105
|
+
dry_run_supported=True,
|
|
106
|
+
outcome_contract=("PASS", "FAIL"),
|
|
107
|
+
summary="Run documentation coverage and lifecycle gates without mutating repository state.",
|
|
108
|
+
),
|
|
109
|
+
|
|
110
|
+
ActionMetadata(
|
|
111
|
+
name="cockpit-readiness",
|
|
112
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
113
|
+
mutation_scope="none",
|
|
114
|
+
dry_run_supported=True,
|
|
115
|
+
outcome_contract=("PASS", "FAIL"),
|
|
116
|
+
summary="Render static cockpit readiness metadata without executing actions.",
|
|
117
|
+
),
|
|
118
|
+
|
|
119
|
+
ActionMetadata(
|
|
120
|
+
name="agent-next",
|
|
121
|
+
safety_class=SafetyClass.REMOTE_MUTATION,
|
|
122
|
+
mutation_scope="docs/reports/command_runs and docs/reports/terminal",
|
|
123
|
+
dry_run_supported=False,
|
|
124
|
+
outcome_contract=(
|
|
125
|
+
"PASS_EXECUTED",
|
|
126
|
+
"FAIL_NO_COMMAND",
|
|
127
|
+
"FAIL_AMBIGUOUS_COMMANDS",
|
|
128
|
+
"FAIL_PULL",
|
|
129
|
+
"FAIL_ALREADY_EXECUTED",
|
|
130
|
+
"FAIL_INVALID_COMMAND",
|
|
131
|
+
"FAIL_SHELL_SYNTAX",
|
|
132
|
+
"FAIL_COMMAND",
|
|
133
|
+
"FAIL_UPLOAD",
|
|
134
|
+
"FAIL_POSTCONDITION",
|
|
135
|
+
),
|
|
136
|
+
summary="Pull and execute exactly one pending repo-backed agent command.",
|
|
137
|
+
),
|
|
138
|
+
|
|
139
|
+
ActionMetadata(
|
|
140
|
+
name="agent-run",
|
|
141
|
+
safety_class=SafetyClass.REMOTE_MUTATION,
|
|
142
|
+
mutation_scope="docs/reports/command_runs and docs/reports/terminal",
|
|
143
|
+
dry_run_supported=False,
|
|
144
|
+
outcome_contract=("PASS_EXECUTED", "FAIL_NO_COMMAND", "FAIL_ALREADY_EXECUTED", "FAIL_INVALID_COMMAND", "FAIL_SHELL_SYNTAX", "FAIL_COMMAND", "FAIL_UPLOAD"),
|
|
145
|
+
summary="Pull-safe repo command runner for agent handoff without copy-and-paste terminal blocks.",
|
|
146
|
+
),
|
|
147
|
+
ActionMetadata(
|
|
148
|
+
name="run-logged",
|
|
149
|
+
safety_class=SafetyClass.LOCAL_ONLY,
|
|
150
|
+
mutation_scope="docs/reports/terminal",
|
|
151
|
+
dry_run_supported=False,
|
|
152
|
+
outcome_contract=("PASS", "FAIL", "FAIL_NO_COMMAND", "FAIL_MISSING_SEPARATOR"),
|
|
153
|
+
summary="Run a local command while teeing output to a terminal log.",
|
|
154
|
+
),
|
|
155
|
+
ActionMetadata(
|
|
156
|
+
name="terminal-status",
|
|
157
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
158
|
+
mutation_scope="none",
|
|
159
|
+
dry_run_supported=True,
|
|
160
|
+
outcome_contract=("PASS_LOG_READY", "PASS_NO_LOG", "FAIL_INVALID_POINTER"),
|
|
161
|
+
summary="Inspect the latest terminal log pointer without mutating state.",
|
|
162
|
+
),
|
|
163
|
+
ActionMetadata(
|
|
164
|
+
name="terminal-clean-check",
|
|
165
|
+
safety_class=SafetyClass.READ_ONLY,
|
|
166
|
+
mutation_scope="none",
|
|
167
|
+
dry_run_supported=True,
|
|
168
|
+
outcome_contract=("PASS_CLEAN", "PASS_ONLY_TERMINAL_LOG_DIRTY", "FAIL_DIRTY_NON_LOG_FILES"),
|
|
169
|
+
summary="Check whether only terminal-log artifacts are dirty during logged runs.",
|
|
170
|
+
),
|
|
171
|
+
ActionMetadata(
|
|
172
|
+
name="terminal-upload",
|
|
173
|
+
safety_class=SafetyClass.REMOTE_MUTATION,
|
|
174
|
+
mutation_scope="docs/reports/terminal only",
|
|
175
|
+
dry_run_supported=False,
|
|
176
|
+
outcome_contract=("PASS_UPLOADED", "PASS_ALREADY_UPLOADED", "FAIL_NO_LOG", "FAIL_DIRTY_NON_LOG_FILES", "FAIL_PUSH_FAILED"),
|
|
177
|
+
summary="Commit and push only terminal-log artifacts for failure handoff.",
|
|
178
|
+
),
|
|
179
|
+
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def list_actions() -> tuple[ActionMetadata, ...]:
|
|
184
|
+
"""Return all known action metadata entries."""
|
|
185
|
+
|
|
186
|
+
return ACTIONS
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def get_action(name: str) -> ActionMetadata | None:
|
|
190
|
+
"""Return metadata for one action name, if known."""
|
|
191
|
+
|
|
192
|
+
for action in ACTIONS:
|
|
193
|
+
if action.name == name:
|
|
194
|
+
return action
|
|
195
|
+
return None
|