Skip to content
Merged
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
13 changes: 13 additions & 0 deletions config/portfolio-catalog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,19 @@ repos:
review_cadence: weekly
intended_disposition: maintain
tool_provenance: claude-code
notes: Local checkout for the canonical saagpatel/OrbitMechanics browser-game repo.
saagpatel/OrbitMechanics:
owner: d
purpose: browser orbital-mechanics puzzle game with real Newtonian physics and handcrafted levels
lifecycle_state: active
criticality: medium
review_cadence: weekly
intended_disposition: maintain
category: fun
tool_provenance: claude-code
maturity_program: maintain
target_maturity: operating
notes: Canonical GitHub repo identity; local checkout remains OrbitMechanic.
saagpatel/operant:
owner: d
purpose: operating-agent calibration benchmark for evaluating agent decision quality and orchestration judgment
Expand Down
32 changes: 32 additions & 0 deletions src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,7 @@ def _apply_portfolio_catalog(report: AuditReport, args) -> AuditReport:

def _apply_scorecards(report: AuditReport, args) -> AuditReport:
from src.report_enrichment import build_maturity_gap_summary, build_scorecard_line
from src.portfolio_catalog import build_intent_alignment_summary, evaluate_intent_alignment
from src.scorecards import (
DEFAULT_SCORECARDS_PATH,
evaluate_scorecards_for_report,
Expand All @@ -1926,20 +1927,51 @@ def _apply_scorecards(report: AuditReport, args) -> AuditReport:
scorecards_data = load_scorecards(Path(scorecards_path))
repo_results, summary, programs = evaluate_scorecards_for_report(report, scorecards_data)
by_repo = {result.get("repo", ""): result for result in repo_results}
queue_by_repo = {
str(item.get("repo") or item.get("repo_name") or "").strip(): item
for item in (report.operator_queue or [])
if str(item.get("repo") or item.get("repo_name") or "").strip()
}
for audit in report.audits:
result = by_repo.get(audit.metadata.name, {})
audit.scorecard = dict(result)
if audit.portfolio_catalog:
audit.portfolio_catalog["scorecard"] = dict(result)
operator_focus = audit.portfolio_catalog.get("operator_focus", "")
if not operator_focus:
from src.report_enrichment import build_operator_focus

operator_focus = build_operator_focus(queue_by_repo.get(audit.metadata.name, {}))
intent_alignment, intent_alignment_reason = evaluate_intent_alignment(
audit.portfolio_catalog,
completeness_tier=audit.completeness_tier,
archived=audit.metadata.archived,
operator_focus=operator_focus,
)
audit.portfolio_catalog.update(
{
"intent_alignment": intent_alignment,
"intent_alignment_reason": intent_alignment_reason,
"intent_alignment_line": f"{intent_alignment}: {intent_alignment_reason}",
"operator_focus": operator_focus,
}
)
catalog_by_repo = {audit.metadata.name: audit.portfolio_catalog for audit in report.audits}
for item in report.operator_queue:
repo_name = str(item.get("repo") or item.get("repo_name") or "").strip()
result = by_repo.get(repo_name, {})
catalog_entry = catalog_by_repo.get(repo_name, {})
if catalog_entry:
item["portfolio_catalog"] = dict(catalog_entry)
item["intent_alignment"] = catalog_entry.get("intent_alignment", "")
item["intent_alignment_reason"] = catalog_entry.get("intent_alignment_reason", "")
if result:
item["scorecard"] = dict(result)
item["scorecard_line"] = build_scorecard_line(item)
item["maturity_gap_summary"] = build_maturity_gap_summary(item)
report.scorecards_summary = summary
report.scorecard_programs = programs
report.intent_alignment_summary = build_intent_alignment_summary(report.audits)
return report


Expand Down
8 changes: 8 additions & 0 deletions src/portfolio_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,9 @@ def evaluate_intent_alignment(
disposition = _safe_text(entry.get("intended_disposition")).lower()
tier = _safe_text(completeness_tier).lower()
focus = _safe_text(operator_focus)
raw_scorecard = entry.get("scorecard")
scorecard = raw_scorecard if isinstance(raw_scorecard, dict) else {}
scorecard_status = _safe_text(scorecard.get("status")).lower()

if disposition == "archive" and (archived or tier in {"abandoned", "skeleton"}):
return (
Expand All @@ -511,6 +514,11 @@ def evaluate_intent_alignment(
"aligned",
"The repo is holding a maintain posture without urgent or revalidation pressure.",
)
if disposition == "maintain" and scorecard_status == "on-track":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve urgent focus when trusting scorecards

For a maintain repo with an on-track scorecard but an operator queue state that resolves to Act Now or Revalidate (for example an urgent/blocked lane or revalidation-needed status), this unconditional scorecard fallback rewrites the intent alignment to aligned; _apply_scorecards then copies that status back onto the operator queue. That makes portfolio truth/control-center surfaces report an urgent or revalidation item as aligned, bypassing the existing focus guard just above that keeps maintain repos in review when there is active operator pressure.

Useful? React with 👍 / 👎.

return (
"aligned",
"The repo is meeting its maintain scorecard target.",
)
if disposition == "finish" and tier in {"wip", "functional"} and focus != "Revalidate":
return ("aligned", "The repo still looks finishable rather than fully off-track.")

Expand Down
54 changes: 54 additions & 0 deletions tests/test_cli_hardening.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,60 @@ def test_apply_scorecards_populates_report(monkeypatch, sample_metadata, tmp_pat
assert updated.operator_queue[0]["scorecard_line"].startswith("Scorecard: Maintain")


def test_apply_scorecards_refreshes_maintain_intent_alignment(sample_metadata, tmp_path):
scorecards_path = tmp_path / "scorecards.yaml"
scorecards_path.write_text(
"""
programs:
maintain:
label: Maintain
target_maturity: operating
rules:
- key: testing
label: Testing
check: dimension_at_least
dimension: testing
threshold: 0.80
partial_threshold: 0.60
weight: 1.0
"""
)

audit = RepoAudit(
metadata=sample_metadata,
analyzer_results=[AnalyzerResult("testing", 1.0, 1.0, [], {})],
overall_score=1.0,
completeness_tier="",
flags=[],
lenses={"ship_readiness": {"score": 1.0}},
security_posture={"score": 1.0},
portfolio_catalog={
"has_explicit_entry": True,
"intended_disposition": "maintain",
"maturity_program": "maintain",
"target_maturity": "operating",
"intent_alignment": "needs-review",
"intent_alignment_reason": "Stale pre-scorecard alignment.",
"operator_focus": "Act Now",
},
)
report = AuditReport.from_audits("testuser", [audit], [], 1)
report.operator_queue = [
{
"repo": "test-repo",
"title": "Review test-repo",
"intent_alignment": "needs-review",
}
]

updated = cli._apply_scorecards(report, _make_args(scorecards=scorecards_path))

assert updated.audits[0].scorecard["status"] == "on-track"
assert updated.audits[0].portfolio_catalog["intent_alignment"] == "aligned"
assert "scorecard" in updated.audits[0].portfolio_catalog["intent_alignment_reason"]
assert updated.operator_queue[0]["intent_alignment"] == "aligned"


def test_control_center_snapshot_rehydrates_portfolio_context(
tmp_path,
sample_metadata,
Expand Down
8 changes: 8 additions & 0 deletions tests/test_operator_os_seam_linter.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ def _passing_paths(tmp_path: Path) -> tuple[Path, list[Path]]:
return truth, [registry, report]


def _refresh_truth_for_cli(path: Path) -> None:
payload = json.loads(path.read_text())
payload["generated_at"] = datetime.now(UTC).isoformat()
path.write_text(json.dumps(payload))


def _write_identity_truth(path: Path) -> None:
_write_truth(
path,
Expand Down Expand Up @@ -405,6 +411,7 @@ def test_identity_resolution_since_includes_new_timestamped_rows(tmp_path: Path)

def test_cli_identity_resolution_is_opt_in(tmp_path: Path) -> None:
truth, markdown = _passing_paths(tmp_path)
_refresh_truth_for_cli(truth)
bridge_db = tmp_path / "bridge.db"
_write_bridge_db(bridge_db, session_cost_names=["085"])

Expand Down Expand Up @@ -445,6 +452,7 @@ def test_cli_identity_resolution_is_opt_in(tmp_path: Path) -> None:
def test_cli_identity_since_filters_timestamped_identity_rows(tmp_path: Path) -> None:
truth, markdown = _passing_paths(tmp_path)
_write_identity_truth(truth)
_refresh_truth_for_cli(truth)
bridge_db = tmp_path / "bridge.db"
notification_db = tmp_path / "notification.sqlite3"
notion_snapshot = tmp_path / "notion.json"
Expand Down
22 changes: 22 additions & 0 deletions tests/test_portfolio_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,28 @@ def test_evaluate_intent_alignment_uses_disposition_and_focus():
)


def test_evaluate_intent_alignment_trusts_on_track_maintain_scorecard():
maintain_entry = {
"has_explicit_entry": True,
"intended_disposition": "maintain",
"scorecard": {
"status": "on-track",
"maturity_level": "leading",
"target_maturity": "operating",
},
}

alignment, reason = evaluate_intent_alignment(
maintain_entry,
completeness_tier="",
archived=False,
operator_focus="Act Now",
)

assert alignment == "aligned"
assert "scorecard" in reason


def test_catalog_line_and_summaries_cover_missing_contracts():
audits = [
{
Expand Down