Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions loopx/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
validate_goal_id_path_segment,
)
from .control_plane.goals.active_state_metadata import markdown_blockquote, markdown_frontmatter_string
from .control_plane.goals.architecture_invariants import (
compute_file_sha256,
discover_top_level_specs,
render_architecture_invariants_markdown,
)
from .registry_writability import probe_registry_write_path


Expand Down Expand Up @@ -90,9 +95,16 @@ def resolve_project_path(project: Path, path: Path | None) -> Path | None:


def render_authority_sources(project: Path, goal_doc: Path | None) -> str:
if not goal_doc:
entries: list[str] = []
if goal_doc:
entries.append(f"- Primary goal document: `{rel_or_abs(goal_doc, project)}`")
for spec in discover_top_level_specs(project):
entries.append(
f"- Top-level specification (`{spec['kind']}`): `{spec['path']}` (sha256=`{spec['sha256'][:12]}`)"
)
if not entries:
return "- No explicit goal document was provided during bootstrap."
return f"- Primary goal document: `{rel_or_abs(goal_doc, project)}`"
return "\n".join(entries)


def repair_missing_todo_source_sections(state_text: str) -> tuple[str, list[str]]:
Expand Down Expand Up @@ -172,7 +184,7 @@ def render_state_markdown(
- Do not perform irreversible production operations without explicit approval.
- Do not publish private project evidence.
- Do not optimize for activity if no useful artifact or decision can be produced.

{render_architecture_invariants_markdown(project)}
## User Todo / Owner Review Reading Queue

## Agent Todo
Expand Down Expand Up @@ -222,8 +234,10 @@ def build_goal_entry(
"kind": "goal_doc",
"path": rel_or_abs(goal_doc, project),
"role": "primary_goal_document",
**({"sha256": compute_file_sha256(goal_doc)} if goal_doc.is_file() else {}),
}
)
authority_sources.extend(discover_top_level_specs(project))
adapter = {
"kind": adapter_kind,
"status": adapter_status,
Expand Down
42 changes: 42 additions & 0 deletions loopx/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
contract_error_views,
project_contract_health_for_goal,
)
from .control_plane.goals.architecture_invariants import (
verify_authority_source_digests,
verify_executable_architecture_invariants,
)
from .control_plane.goals.activation import (
GoalActivationState,
goal_activation_state,
Expand Down Expand Up @@ -850,6 +854,35 @@ def _active_state_projection_gap_warnings(
return warnings


def _authority_and_invariant_diagnostics(
registry: dict[str, Any],
*,
include_architecture_invariants: bool,
goal_id_filter: str | None = None,
activation_state_filter: GoalActivationState | str | None = None,
) -> tuple[list[dict[str, Any]], list[str]]:
diagnostics: list[dict[str, Any]] = []
checks: list[str] = []
for goal in registry_goals(registry):
goal_id = str(goal.get("id") or "")
if goal_id_filter and goal_id != goal_id_filter:
continue
if (
activation_state_filter is not None
and goal_activation_state(goal)
is not normalize_goal_activation_state(activation_state_filter)
):
continue
goal_diags, goal_checks = verify_authority_source_digests(goal)
if include_architecture_invariants:
executable_diags, executable_checks = verify_executable_architecture_invariants(goal)
goal_diags.extend(executable_diags)
goal_checks.extend(executable_checks)
diagnostics.extend(goal_diags)
checks.extend(goal_checks)
return diagnostics, checks


def _tracked_scan_files(scan_root: Path) -> list[Path]:
scan_root = scan_root.resolve()
repo_root = _git_worktree_root(scan_root)
Expand Down Expand Up @@ -1204,6 +1237,7 @@ def check_contract(
goal_id_filter: str | None = None,
activation_state_filter: GoalActivationState | str | None = None,
include_public_boundary_scan: bool = True,
include_architecture_invariants: bool = True,
history_audit: RunHistoryAudit | None = None,
registry: dict[str, Any] | None = None,
todo_snapshot: CanonicalTodoSnapshot | None = None,
Expand Down Expand Up @@ -1273,6 +1307,14 @@ def add_global_error(code: str, message: str) -> None:
if checked_user_gates:
checks.append(f"user-gate scopes checked: {checked_user_gates} open multi-agent gates")
error_diagnostics.extend(todo_contract_diagnostics)
invariant_diagnostics, invariant_checks = _authority_and_invariant_diagnostics(
registry,
include_architecture_invariants=include_architecture_invariants,
goal_id_filter=goal_id_filter,
activation_state_filter=activation_state_filter,
)
error_diagnostics.extend(invariant_diagnostics)
checks.extend(invariant_checks)
warnings.extend(
_active_state_projection_gap_warnings(
registry,
Expand Down
Loading
Loading