Skip to content

Commit 22e00ce

Browse files
rules(license): cap licence findings at :review strategy (neurophone#99 closeout) (#415)
## Summary - **Policy header** in `lib/rules/cicd_rules.ex` License Validation section: quotes the verbatim owner directive 2026-06-02 + 5-way classification. - **Cap helpers**: `license_finding_strategy/0` (always `:review`), `license_finding_severity_cap/1` (always `:warn`), `license_related_finding?/1` (matches the same regex as the gitbot-fleet dispatcher gate), `owner_license_classification/0` (canonical 5-way map). - **Scorecard ingestor** SC-010 `License` → `auto_fixable: false` with remediation text spelling out the 5-way classification. ## Why Owner directive 2026-06-02 forbids automated licence/SPDX edits. Triggered by [neurophone#99](hyperpolymath/neurophone#99) — an auto-generated PR by the Claude bot reverting PMPL-1.0-or-later → MPL-2.0 across ~140 files, closed by the owner. The fix gates the dispatcher; this PR ensures hypatia (the rule source) never emits an auto-execute licence finding in the first place. Five-way classification (verbatim): > "mpl-2.0 is for my sole repos, all rights reserved is for 007, agpl-3.0-or-later is for those shared with my son, and leave other people's forked stuff alone … only palimpsest license for obvious reasons should be talking about palipsest and palimpsest plasma, and consent-aware-http, but in that case prospectively" ## Test plan - [ ] `Hypatia.Rules.CicdRules.license_finding_strategy() == :review` - [ ] `Hypatia.Rules.CicdRules.license_finding_severity_cap(:critical) == :warn` - [ ] `Hypatia.Rules.CicdRules.license_related_finding?("LicenseCompliance") == true` - [ ] `Hypatia.Rules.CicdRules.license_related_finding?("MissingSPDX") == true` - [ ] `Hypatia.ScorecardIngestor` SC-010 `auto_fixable` is `false`. - [ ] mix test passes. Related: hyperpolymath/gitbot-fleet chore/halt-license-auto-prs, hyperpolymath/standards docs/license-no-auto-policy. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1ec812c commit 22e00ce

2 files changed

Lines changed: 102 additions & 2 deletions

File tree

lib/rules/cicd_rules.ex

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,40 @@ defmodule Hypatia.Rules.CicdRules do
13061306
# ---------------------------------------------------------------------------
13071307
# License Validation
13081308
# ---------------------------------------------------------------------------
1309+
#
1310+
# POLICY — Manual Only (owner directive 2026-06-02; triggered by neurophone#99)
1311+
# ----------------------------------------------------------------------------
1312+
# Findings emitted by this section are **report-only / review-strategy**.
1313+
# They MUST NEVER reach `:auto_execute` confidence, regardless of how
1314+
# cleanly the SPDX validator fires. Licence / SPDX remediation is
1315+
# manual, per-file, owner-only. Every prior LLM-driven sweep has
1316+
# scrambled headers, mis-licensed third-party code, or reverted owner
1317+
# decisions (see neurophone#99 closed 2026-06-02).
1318+
#
1319+
# Five-way classification (verbatim owner directive 2026-06-02):
1320+
# "mpl-2.0 is for my sole repos, all rights reserved is for 007,
1321+
# agpl-3.0-or-later is for those shared with my son, and leave other
1322+
# people's forked stuff alone … only palimpsest license for obvious
1323+
# reasons should be talking about palipsest and palimpsest plasma,
1324+
# and consent-aware-http, but in that case prospectively"
1325+
#
1326+
# 1. Sole owner repos (default) → MPL-2.0
1327+
# 2. The 007 repo → All Rights Reserved (out-of-scope)
1328+
# 3. Shared with son → AGPL-3.0-or-later (idaptik, paint-type, …)
1329+
# 4. Third-party / forks → leave alone, flag-only
1330+
# 5. Palimpsest carve-out → PMPL-1.0-or-later for EXACTLY
1331+
# palimpsest-license, palimpsest-plasma,
1332+
# and consent-aware-http (prospective)
1333+
#
1334+
# Canonical memory files:
1335+
# ~/.claude/projects/.../feedback_estate_license_policy_umbrella.md
1336+
# ~/.claude/projects/.../feedback_no_automated_licence_edits.md
1337+
#
1338+
# Downstream consumers (recipe-generator, dispatch-runner) MUST treat
1339+
# any licence-category finding as `auto_fixable: false` / strategy
1340+
# `:review`. The `license_finding_severity_cap/1` and
1341+
# `license_finding_strategy/0` functions below encode that cap.
1342+
# ----------------------------------------------------------------------------
13091343

13101344
@required_spdx "MPL-2.0"
13111345
# `MPL-2.0` is intentionally absent here — it's the required identifier
@@ -1367,6 +1401,63 @@ defmodule Hypatia.Rules.CicdRules do
13671401

13681402
def license_exception_paths_for(_), do: []
13691403

1404+
# ---------------------------------------------------------------------------
1405+
# License-finding strategy cap (owner directive 2026-06-02)
1406+
# ---------------------------------------------------------------------------
1407+
#
1408+
# License/SPDX findings MUST NEVER drive auto-execute fixes. These helpers
1409+
# are the canonical cap consulted by downstream pipelines (recipe-generator,
1410+
# dispatch-runner). Do not bypass.
1411+
1412+
@doc """
1413+
Strategy for any licence-related finding. Always `:review` (never
1414+
`:auto_execute`). Owner must approve and apply licence edits manually.
1415+
"""
1416+
def license_finding_strategy, do: :review
1417+
1418+
@doc """
1419+
Maximum severity any licence-related finding may carry. Capped at `:warn`
1420+
so the dispatcher never escalates to auto-execute confidence.
1421+
"""
1422+
def license_finding_severity_cap(_severity), do: :warn
1423+
1424+
@doc """
1425+
Returns true if a finding category / recipe / pattern id is licence-related
1426+
and therefore subject to the auto-fix refusal gate. Mirrors the regex used
1427+
in `gitbot-fleet/scripts/dispatch-runner.sh`.
1428+
"""
1429+
def license_related_finding?(category_or_recipe) when is_binary(category_or_recipe) do
1430+
lower = String.downcase(category_or_recipe)
1431+
1432+
String.contains?(lower, "license") or
1433+
String.contains?(lower, "spdx") or
1434+
String.contains?(lower, "pmpl") or
1435+
String.contains?(lower, "mpl-2") or
1436+
String.contains?(lower, "agpl") or
1437+
String.contains?(lower, "palimpsest")
1438+
end
1439+
1440+
def license_related_finding?(_), do: false
1441+
1442+
@doc """
1443+
Five-way licence classification per owner directive 2026-06-02. Returned
1444+
as a map for downstream tooling that needs to render policy in error
1445+
messages or PR descriptions.
1446+
"""
1447+
def owner_license_classification do
1448+
%{
1449+
sole_owner_repos: "MPL-2.0",
1450+
"007": "All Rights Reserved",
1451+
shared_with_son: "AGPL-3.0-or-later",
1452+
third_party_forks: :leave_alone,
1453+
palimpsest_carve_out: %{
1454+
license: "PMPL-1.0-or-later",
1455+
repos: ["palimpsest-license", "palimpsest-plasma", "consent-aware-http"],
1456+
note: "consent-aware-http is prospective only — do NOT retroactively flip"
1457+
}
1458+
}
1459+
end
1460+
13701461
@doc """
13711462
Validate a license SPDX identifier, optionally scoped to a repo name.
13721463
AGPL-3.0-or-later is permitted for repos in @agpl_exception_repos.

lib/scorecard_ingestor.ex

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,19 @@ defmodule Hypatia.ScorecardIngestor do
101101
remediation: "Integrate with OSS-Fuzz or add language-specific fuzzing."
102102
},
103103
"License" => %{
104-
id: "SC-010", pa_rule: "SC010", risk: :low, auto_fixable: true,
104+
# `auto_fixable: false` per owner directive 2026-06-02 (triggered by
105+
# neurophone#99). Licence/SPDX edits are manual, per-file, owner-only.
106+
# See `feedback_no_automated_licence_edits.md` and
107+
# `feedback_estate_license_policy_umbrella.md`. SPDX choice is owner-
108+
# specific (5-way classification) and cannot be auto-derived.
109+
id: "SC-010", pa_rule: "SC010", risk: :low, auto_fixable: false,
105110
category: "LicenseCompliance",
106111
description: "No license file found",
107-
remediation: "Add LICENSE file with SPDX identifier to repository root."
112+
remediation:
113+
"Owner must manually add LICENSE file. SPDX choice depends on owner classification " <>
114+
"(sole repo → MPL-2.0; 007 → ARR; son-shared → AGPL-3.0-or-later; " <>
115+
"fork → leave alone; palimpsest carve-out → PMPL-1.0-or-later). " <>
116+
"Do NOT auto-generate."
108117
},
109118
"Maintained" => %{
110119
id: "SC-011", pa_rule: "SC011", risk: :high, auto_fixable: false,

0 commit comments

Comments
 (0)