@windyroad/architect 1.1.2-preview.1389 → 1.1.2-preview.1391

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/architect",
3
- "version": "1.1.2-preview.1389",
3
+ "version": "1.1.2-preview.1391",
4
4
  "description": "Architecture decision enforcement for AI coding agents",
5
5
  "bin": {
6
6
  "windyroad-architect": "./bin/install.mjs"
@@ -27,8 +27,8 @@ set -uo pipefail
27
27
  # Without this, BSD awk on macOS (default byte-counting for length/substr) and
28
28
  # GNU awk on Linux (default character-counting under any UTF-8 locale) produce
29
29
  # divergent output when ADR bodies contain multi-byte chars (em-dashes, smart
30
- # quotes, etc.). LC_ALL=C makes both treat input as raw bytes — the truncated
31
- # slice may cut mid-UTF-8 on long lines, but the output is byte-identical
30
+ # quotes, etc.). LC_ALL=C makes both treat input as raw bytes. Truncation
31
+ # backs up to a complete UTF-8 character so the output is byte-identical
32
32
  # across platforms (which is what the CI drift gate at test 2145 enforces).
33
33
  # Companion to the ASCII `...` change in compact_join_bullets/chosen
34
34
  # truncation — both halves are needed to close P334.
@@ -214,13 +214,16 @@ compact_join_bullets() {
214
214
  gsub(/`/, "")
215
215
  # Drop nested-bullet continuation lines that survived earlier filters.
216
216
  if (length($0) == 0) next
217
- if (length($0) > n) line = substr($0, 1, n) "..."
218
- else line = $0
217
+ if (length($0) > n) {
218
+ cut = n
219
+ while (substr($0, cut + 1, 1) ~ /[\200-\277]/) cut--
220
+ line = substr($0, 1, cut) "..."
221
+ } else line = $0
219
222
  if (out == "") out = line
220
223
  else out = out "; " line
221
224
  }
222
225
  END { print out }
223
- ' | iconv -f UTF-8 -t UTF-8 -c); then
226
+ '); then
224
227
  echo "generate-decisions-compendium: failed to truncate confirmation text safely" >&2
225
228
  return 1
226
229
  fi
@@ -259,7 +262,7 @@ oneline() {
259
262
  tr '\n\r' ' ' | tr -s ' ' | sed 's/^ *//; s/ *$//'
260
263
  }
261
264
 
262
- # Truncate a string to N chars + ellipsis if longer. Avoids slicing a `**`
265
+ # Truncate to at most N UTF-8 bytes before adding an ellipsis. Avoids slicing a `**`
263
266
  # marker in half and closes emphasis when truncation lands inside it.
264
267
  truncate_with_ellipsis() {
265
268
  local s="$1" n="$2" truncated remainder pairs=0
@@ -267,6 +270,10 @@ truncate_with_ellipsis() {
267
270
  printf '%s' "$s"
268
271
  return
269
272
  fi
273
+ # A continuation byte immediately after the cut means the cut splits a character.
274
+ while [[ "${s:n:1}" == [$'\200'-$'\277'] ]]; do
275
+ n=$((n - 1))
276
+ done
270
277
  truncated="${s:0:n}"
271
278
  if [[ "$truncated" == *\* && "${s:n:1}" == "*" ]]; then
272
279
  truncated="${truncated%?}"
@@ -308,11 +315,7 @@ emit_entry() {
308
315
 
309
316
  # Chosen-option line — truncate to a comfortable summary length.
310
317
  chosen=$(get_chosen "$file" | strip_links | oneline)
311
- if ! chosen=$(truncate_with_ellipsis "$chosen" 240 \
312
- | iconv -f UTF-8 -t UTF-8 -c); then
313
- echo "generate-decisions-compendium: failed to truncate chosen text safely for $file" >&2
314
- return 1
315
- fi
318
+ chosen=$(truncate_with_ellipsis "$chosen" 240)
316
319
 
317
320
  # Confirmation: preserve every top-level item, ≤ 110 chars each, joined
318
321
  # with "; " on one line for the routine-compliance scannable view.