fix: per-entity Step 0.55, LAW 7 sub-run quiet, default 2, canonical SKILL.md (#311)

Four fixes based on 2026-04-22 test-window feedback on v3.0.11 --competitors:

- Each competitor sub-run now runs Step 0.55 (X handle / subreddits /
  GitHub) via resolve.auto_resolve inside the fanout closure. Deep-copied
  config per entity prevents _auto_resolve_context leak across sub-runs.
  Resolved data stored on report.artifacts["resolved"] for the renderer.
- New internal_subrun keyword on planner.plan_query and pipeline.run
  suppresses the LAW 7 "No --plan passed" stderr for engine-internal
  fan-out only. Default path unchanged.
- Default --competitors count is now 2 (3-way total). --competitors=N
  still customizes; range 1..6.
- SKILL.md STEP 0 canonical-path self-check forces readers who loaded
  from marketplaces/ (auto-restored to origin/main, stale) to re-read
  from plugins/cache/last30days-skill/last30days/{VERSION}/SKILL.md.
  Two of three 2026-04-22 test windows hit this stale-path trap.
- New ## Resolved Entities block in render_comparison_multi shows
  per-entity handles/subs/github for debug visibility.

Bumps plugin.json to 3.0.12. 12 new tests; 1,175 total passing.

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matt Van Horn
2026-04-22 21:30:08 -07:00
committed by GitHub
parent 5f054380c5
commit 00d01933e0
13 changed files with 1019 additions and 23 deletions
+55
View File
@@ -445,6 +445,11 @@ def render_comparison_multi(
)
lines.append("")
resolved_block = _render_resolved_entities_block(entity_reports)
if resolved_block:
lines.extend(resolved_block)
lines.append("")
fun_params = _FUN_LEVELS.get(fun_level, _FUN_LEVELS["medium"])
for label, report in entity_reports:
lines.extend(_render_entity_evidence_block(
@@ -475,6 +480,52 @@ def render_comparison_multi(
return "\n".join(lines).strip() + "\n"
def _render_resolved_entities_block(
entity_reports: list[tuple[str, schema.Report]],
) -> list[str]:
"""Emit a visible per-entity Step 0.55 resolution summary.
Reads `resolved` dicts from each Report's artifacts. Returns an empty
list when no entity has a resolved payload (mock mode, no web backend,
or artifacts not populated). Missing per-entity fields render as `-`.
Context strings truncate at 120 chars.
"""
any_resolved = any(
isinstance(report.artifacts.get("resolved"), dict)
for _label, report in entity_reports
)
if not any_resolved:
return []
out: list[str] = ["## Resolved Entities", ""]
for label, report in entity_reports:
resolved = report.artifacts.get("resolved") or {}
x_handle = resolved.get("x_handle") or ""
subs = resolved.get("subreddits") or []
gh_user = resolved.get("github_user") or ""
gh_repos = resolved.get("github_repos") or []
context = resolved.get("context") or ""
x_display = f"@{x_handle}" if x_handle else "-"
subs_display = (
", ".join(f"r/{s}" for s in subs[:5]) + (
f" (+{len(subs) - 5})" if len(subs) > 5 else ""
)
) if subs else "-"
gh_display = f"@{gh_user}" if gh_user else "-"
if gh_repos:
gh_display += f" ({', '.join(gh_repos[:3])}" + (
f" +{len(gh_repos) - 3}" if len(gh_repos) > 3 else ""
) + ")"
context_display = _truncate(context, 120) if context else "-"
out.append(
f"- **{label}**: X {x_display} | Subs {subs_display} | "
f"GitHub {gh_display} | Context: {context_display}"
)
return out
def _render_entity_evidence_block(
*,
label: str,
@@ -536,6 +587,10 @@ def render_comparison_multi_context(
_AI_SAFETY_NOTE,
"",
]
resolved_block = _render_resolved_entities_block(entity_reports)
if resolved_block:
lines.extend(resolved_block)
lines.append("")
for label, report in entity_reports:
lines.append(f"## {label}")
lines.append(f"Intent: {report.query_plan.intent}")