forge-orkes 0.80.1 → 0.80.2

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.
@@ -588,12 +588,21 @@ function extractDetectionBlock(guideContent) {
588
588
  * with the exact guide pointer. There are NO per-version code branches: a new
589
589
  * guide that ships with a conformant Detection block is auto-covered.
590
590
  *
591
- * Range: installed < v <= source. `installedVersion` is the project's
591
+ * Range: installed <= v <= source. `installedVersion` is the project's
592
592
  * settings.json forge.version captured BEFORE the version stamp; `source` is
593
593
  * pkgVersion (this package's package.json) — never the template settings.json
594
594
  * literal, which is a placeholder the installer stamps at write time. Non-
595
595
  * interactive: the bin only warns and points at the guide; it never applies.
596
596
  *
597
+ * Lower bound is INCLUSIVE (issue #43): the version stamp always advances
598
+ * unconditionally, even when a MIGRATE hit was surfaced but declined that
599
+ * run — so an exclusive `installed < v` permanently hides a same-numbered
600
+ * guide the moment its own version gets stamped without being applied. This
601
+ * is safe to widen because the guide's own `## Detection` block is the real
602
+ * gate (repo-state-based: tracked file, size, absence of the post-migration
603
+ * artifact) — the version range only decides which guides are worth asking;
604
+ * a genuinely-already-applied guide's Detection block reports a no-op.
605
+ *
597
606
  * Returns the applying guides as [{version, guide, reason}] — the human warning
598
607
  * and the --json `migrations` key render the same findings.
599
608
  */
@@ -606,7 +615,7 @@ function runPostUpgradeMigrationChecks(installedVersion) {
606
615
  installedVersion && installedVersion !== 'unknown' ? installedVersion : '0.0.0';
607
616
  const source = pkgVersion;
608
617
 
609
- // Select in-range guides: installed < v <= source. Parse {v} from the filename.
618
+ // Select in-range guides: installed <= v <= source. Parse {v} from the filename.
610
619
  let guides;
611
620
  try {
612
621
  guides = fs
@@ -618,7 +627,7 @@ function runPostUpgradeMigrationChecks(installedVersion) {
618
627
  .filter(Boolean)
619
628
  .filter(
620
629
  (g) =>
621
- compareVersions(installed, g.version) < 0 &&
630
+ compareVersions(installed, g.version) <= 0 &&
622
631
  compareVersions(g.version, source) <= 0
623
632
  )
624
633
  .sort((a, b) => compareVersions(a.version, b.version));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-orkes",
3
- "version": "0.80.1",
3
+ "version": "0.80.2",
4
4
  "description": "Set up the Forge meta-prompting framework for Claude Code in your project",
5
5
  "bin": {
6
6
  "create-forge": "./bin/create-forge.js"
@@ -135,7 +135,12 @@ function extract_id(line, w, arr, n, tok, digits, suffix) {
135
135
  # normalization. Labelled ids (M-EVT01, m-SEQPRIM01) must NOT be digit-
136
136
  # stripped — that would collapse distinct labelled ids onto the same
137
137
  # numeric suffix (m-EVT01 and m-SEQPRIM01 would both become m-01) — so
138
- # their alphanumeric suffix is preserved verbatim (lowercased) instead.
138
+ # their alphanumeric suffix is preserved VERBATIM, case included (issue
139
+ # #44): only the "m-" prefix is normalized, exactly like the numeric path
140
+ # never invents a digit convention of its own. Forge doesn't own the
141
+ # label's spelling — a project's own casing convention (e.g. m-EVT01, all
142
+ # caps) must survive the shard, or citations elsewhere in the repo stop
143
+ # matching the shard filename.
139
144
  if (tok !~ /^[Mm]-?[A-Za-z0-9]+$/) return ""
140
145
  suffix = tok
141
146
  sub(/^[Mm]-?/, "", suffix)
@@ -145,7 +150,7 @@ function extract_id(line, w, arr, n, tok, digits, suffix) {
145
150
  gsub(/[^0-9]/, "", digits)
146
151
  return "m-" digits
147
152
  }
148
- return "m-" tolower(suffix)
153
+ return "m-" suffix
149
154
  }
150
155
 
151
156
  function add_id(id) {
@@ -159,11 +159,14 @@ src_after="$(cat "$SOURCE" | wc -c)"
159
159
  [ -n "$src_after" ] && pass "source context.md still readable after migration" || fail "source context.md unreadable after migration"
160
160
  grep -q "### M7 — Widget Registry" "$SOURCE" && pass "source context.md left untouched" || fail "source context.md was modified"
161
161
 
162
- # --- labelled milestone ids (issue #42) -------------------------------------
162
+ # --- labelled milestone ids (issue #42, case preservation issue #44) --------
163
163
  # Non-numeric ids (M-EVT01, m-SEQPRIM01) must shard into distinct files —
164
164
  # digit-stripping them onto a shared "m-01" was the exact silent-collision
165
165
  # bug reported upstream. Purely-numeric ids must keep their existing
166
- # normalization (m-53 stays m-53, unaffected by the labelled-id path).
166
+ # normalization (m-53 stays m-53, unaffected by the labelled-id path). The
167
+ # label's own casing must survive verbatim (issue #44) — only the "m-"
168
+ # prefix is normalized — since a project's own convention (e.g. an
169
+ # all-caps label) is what the rest of its repo actually cites.
167
170
 
168
171
  LBLROOT="$(mktemp -d)"
169
172
  trap 'rm -rf "$ROOT" "$LBLROOT"' EXIT INT TERM
@@ -203,15 +206,22 @@ LBLOUT="$("$MIGRATE" --source "$LBLSRC" --dest "$LBLDEST" 2>&1)"
203
206
  LBLRC=$?
204
207
  [ "$LBLRC" -eq 0 ] && pass "labelled-id migration exits 0" || fail "labelled-id migration exits 0 (exit $LBLRC)"
205
208
 
206
- check_file "$LBLDEST/context/m-evt01.md" "context/m-evt01.md created (labelled id, lowercased)"
207
- check_file "$LBLDEST/context/m-seqprim01.md" "context/m-seqprim01.md created (distinct from m-evt01, not digit-collapsed)"
209
+ check_file "$LBLDEST/context/m-EVT01.md" "context/m-EVT01.md created (labelled id, prefix normalized)"
210
+ check_file "$LBLDEST/context/m-SEQPRIM01.md" "context/m-SEQPRIM01.md created (distinct from m-EVT01, not digit-collapsed)"
208
211
  check_file "$LBLDEST/context/m-53.md" "context/m-53.md still created (numeric id unaffected by labelled-id path)"
209
212
 
213
+ # check_file alone can't prove case survived — macOS's default case-insensitive
214
+ # FS makes m-evt01.md and m-EVT01.md the same lookup. `ls` returns the actual
215
+ # stored name; grep -x is case-sensitive regardless of the FS.
216
+ lbl_listing="$(ls "$LBLDEST/context" 2>/dev/null)"
217
+ echo "$lbl_listing" | grep -qx "m-EVT01.md" && pass "m-EVT01.md label case preserved verbatim on disk (issue #44)" || fail "label case NOT preserved — directory listing: $lbl_listing"
218
+ echo "$lbl_listing" | grep -qx "m-SEQPRIM01.md" && pass "m-SEQPRIM01.md label case preserved verbatim on disk (issue #44)" || fail "label case NOT preserved — directory listing: $lbl_listing"
219
+
210
220
  lbl_count="$(ls "$LBLDEST"/context/*.md 2>/dev/null | wc -l | tr -d ' ')"
211
221
  [ "$lbl_count" -eq 3 ] && pass "labelled + numeric ids produce 3 distinct files, none collapsed" || fail "labelled-id run produced $lbl_count file(s), want 3"
212
222
 
213
- evt="$(cat "$LBLDEST/context/m-evt01.md" 2>/dev/null)"
214
- check_has "m-evt01.md carries its own Deferred entry (labelled-prefix match)" "$evt" "a follow-up scoped to the labelled id"
223
+ evt="$(cat "$LBLDEST/context/m-EVT01.md" 2>/dev/null)"
224
+ check_has "m-EVT01.md carries its own Deferred entry (labelled-prefix match)" "$evt" "a follow-up scoped to the labelled id"
215
225
 
216
226
  # --- unresolvable id scheme guard (issue #42) --------------------------------
217
227
  # A context.md whose Locked Decisions headings don't match m-<number> or a
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "forge": {
3
- "version": "0.80.1",
3
+ "version": "0.80.2",
4
4
  "default_tier": "standard",
5
5
  "beads_integration": false,
6
6
  "context_gates": {