@sleepy_panda_srl/portulan 0.1.2 → 0.1.3

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.
@@ -70,6 +70,19 @@ export const MUST_CARRY = ["README.md", "SECURITY.md", ".portulan/products/portu
70
70
  // The record layer. These files preserve sentences that are no longer true, on purpose.
71
71
  export const RECORD_PREFIXES = [
72
72
  "CHANGELOG.md",
73
+ // **A release record is record-layer by nature**, and it was classified here deliberately rather
74
+ // than left to whether a pattern happens to match one. `evals/releases/<version>.md` is generated
75
+ // per release and preserves that release's conditions forever — so the moment `0.1.4` exists,
76
+ // `0.1.3`'s register is a document stating, correctly and permanently, facts about a version that
77
+ // is no longer current. That is precisely what this exclusion is for. Its own drift is held by the
78
+ // `release-eval` recipe, which byte-compares each register against the capture it was rendered
79
+ // from — so for `<version>.json` and `<version>.md` this moves coverage to the rail that can
80
+ // actually read them rather than removing it. **`evals/releases/README.md` is the exception and is
81
+ // named rather than glossed:** `release-eval` reads only the two version-keyed files, so that
82
+ // README now sits under an excluded prefix with nothing covering it. Harmless today — it states no
83
+ // current version — and it is exactly this module's own third named residual, a live claim under an
84
+ // excluded prefix, so it is recorded here instead of being discovered by the next reader.
85
+ "evals/releases/",
73
86
  "docs/plan.md",
74
87
  "docs/milestones/",
75
88
  ".portulan/handoffs/",
@@ -26,15 +26,15 @@
26
26
 
27
27
  ```json
28
28
  {
29
- "portulan": { "gates": "1.0" },
29
+ "portulan": { "spec": "2.2" },
30
30
 
31
31
  "why": "{Why this team gates what it gates — the sentence a new agent reads first. Name the blast radius you are protecting, not the tools you are restricting.}",
32
32
 
33
33
  "floor": {
34
34
  "branch": "{default branch}",
35
- "require_pull_request": true,
36
- "block_force_push": true,
37
- "checks": []
35
+ "checks": [],
36
+ "reviews": 0,
37
+ "resolve_conversations": true
38
38
  },
39
39
 
40
40
  "rules": [
@@ -45,11 +45,17 @@
45
45
  "reason": "{Why, and what to do instead. Prohibited means no yes makes this acceptable — if a human could approve it, it is Gated, not Prohibited.}"
46
46
  },
47
47
  {
48
- "id": "{rule-id}",
48
+ "id": "force-push-without-a-lease",
49
49
  "tier": "gated",
50
- "action": { "shell": "{command prefix}" },
50
+ "action": { "shell": "git push --force" },
51
51
  "reason": "{Why a human must approve each time. Prefer the undoability test: what does it cost if this was wrong and nobody noticed for a week?}"
52
52
  },
53
+ {
54
+ "id": "delete-a-ref",
55
+ "tier": "gated",
56
+ "action": { "shell": "git push --delete" },
57
+ "reason": "{Why a deletion waits for a person. These two ids and actions are filled in already — they are the two destructive ref spellings the floor backend can express, and a `floor` block with no rule reaching it refuses to compile.}"
58
+ },
53
59
  {
54
60
  "id": "{rule-id}",
55
61
  "tier": "propose",
@@ -60,6 +66,16 @@
60
66
  }
61
67
  ```
62
68
 
69
+ > **`floor` is exactly four keys, and they are the four `compile` reads** — `branch`, `checks`,
70
+ > `reviews`, `resolve_conversations`. It is not a free-form block: `reviews` is a non-negative integer
71
+ > and `resolve_conversations` a boolean, both required, because a floor that omitted them would export
72
+ > one weaker than the one already in force. _(Until 2026-08-22 this skeleton emitted
73
+ > `require_pull_request` and `block_force_push` instead — two keys no version of the compiler has ever
74
+ > read — beside a `portulan.gates` version key it does not read either. A scaffold the next documented
75
+ > step refuses is the defect this template's own closing paragraph warns about, one layer up;
76
+ > [#329](https://github.com/sleepy-panda-srl/portulan/issues/329) reported it, and `new`'s test now
77
+ > scaffolds this file and compiles it rather than only checking that it was written.)_
78
+ >
63
79
  > **`checks: []` is deliberate and you should probably leave it that way at first.** A floor requiring a
64
80
  > status check that no workflow job reports is a red nobody caused — a fresh repository reports no checks,
65
81
  > and a real one reports something else, so any name guessed here fails on the first run. Add the check
@@ -72,5 +88,8 @@
72
88
  > print every rule against both rather than reasoning about it — the refusals are printed, never silent.
73
89
  >
74
90
  > **Start with the rules that destroy rather than create.** A ref deletion and a force-push are the two
75
- > the floor backend can express, they are the two whose damage is hardest to undo, and they are a policy's
76
- > honest first pair.
91
+ > **destructive ref spellings** the floor backend can express — it also emits `pull_request` and
92
+ > `required_status_checks` for a `propose` rule once `floor.checks` is non-empty, which is the paragraph
93
+ > above — and they are the two whose damage is hardest to undo, so they are a policy's
94
+ > honest first pair — so the skeleton above ships them filled in rather than as placeholders, which is
95
+ > also what keeps the `floor` block reachable. Their `reason` is still yours to write.