@danmoisan/drm-copilot-mcp 1.1.14 → 1.1.15

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.
Files changed (19) hide show
  1. package/package.json +1 -1
  2. package/resources/claude-customizations/.claude/lib/ci-gate/Invoke-CiGateParser.ps1 +330 -0
  3. package/resources/claude-customizations/.claude/rules/shell.md +8 -7
  4. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/SKILL.md +8 -8
  5. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup-worktrees.sh +234 -0
  6. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_actions_lib.sh +451 -0
  7. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_detached_lib.sh +301 -0
  8. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_dirt_lib.sh +495 -0
  9. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_enumerate_lib.sh +252 -0
  10. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_lib.sh +496 -0
  11. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_eol_lib.sh +212 -0
  12. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_preserve_lib.sh +492 -0
  13. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_report_records_lib.sh +476 -0
  14. package/resources/claude-customizations/.claude/skills/cleanup-merged-worktrees/scripts/cleanup_worktrees_scan_helper.sh +182 -0
  15. package/resources/claude-customizations/.claude/skills/epic-orchestrate/SKILL.md +1 -1
  16. package/resources/claude-customizations/.claude/skills/orchestrate/SKILL.md +1 -1
  17. package/resources/claude-customizations/pack-manifests/core.json +11 -0
  18. package/resources/codex-and-agents-customizations/.codex/config.toml +1 -1
  19. package/resources/powershell/PoshQC/settings/pester.runsettings.psd1 +5 -0
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env bash
2
+ # cleanup_worktrees_preserve_eol_lib.sh: the line-ending and MEMORY.md index group of the
3
+ # preserve-file consolidation function set, split out of
4
+ # cleanup_worktrees_preserve_lib.sh to keep every file within the 500-line cap. The split
5
+ # is pre-authorized by the specification's placement decision, which names exactly this
6
+ # group: preserve_derive_line_ending, preserve_render_index_append, and
7
+ # preserve_index_has_entry, together with the per-record index decision that consumes
8
+ # them.
9
+ #
10
+ # Sourcing contract: this library defines functions only; it never runs work at source
11
+ # time, so the wrapper and the bats suites can source it without side effects. It MUST be
12
+ # sourced immediately BEFORE cleanup_worktrees_preserve_lib.sh, whose read-only planning
13
+ # phase calls the functions defined here.
14
+ #
15
+ # The convention used to write an index append is derived from the target file's current
16
+ # bytes at run time. The manifest's line_ending field is never read as an input to that
17
+ # decision; it is read for exactly one purpose, comparison, so that a stale advisory value
18
+ # produces a reported mismatch rather than a wrong write.
19
+
20
+ preserve_index_has_entry() {
21
+ # Report whether the destination index already carries an entry for the given file.
22
+ #
23
+ # A duplicate exists when some line of the index holds a markdown link whose target -
24
+ # the text between `](` and `)` - equals the basename of target_path. Index links in
25
+ # this repository are bare filenames with no directory component, so the basename is
26
+ # the whole comparison. Matching on the link target rather than on the whole line makes
27
+ # the check independent of the description text, which the operator may have reworded.
28
+ #
29
+ # Args: $1 = index path, $2 = the basename to look for. Returns 0 on a duplicate.
30
+ local index=${1-} base=${2-}
31
+ [[ -f $index ]] || return 1
32
+ local line target
33
+ while IFS= read -r line || [[ -n $line ]]; do
34
+ [[ $line == *"]("* ]] || continue
35
+ target=${line#*](}
36
+ target=${target%%)*}
37
+ if [[ $target == "$base" ]]; then
38
+ return 0
39
+ fi
40
+ done <"$index"
41
+ return 1
42
+ }
43
+
44
+ preserve_line_terminator() {
45
+ # Echo the raw bytes of the line terminator the given token selects.
46
+ #
47
+ # The selection lives in one place so that the writer and the tests read the same
48
+ # answer. A token this function does not recognise falls to a line feed, which is the
49
+ # only convention a newly tracked file in this repository can hold.
50
+ #
51
+ # Args: $1 = the token returned by preserve_derive_line_ending.
52
+ case ${1:-lf} in
53
+ crlf) printf '\r\n' ;;
54
+ *) printf '\n' ;;
55
+ esac
56
+ }
57
+
58
+ preserve_render_index_append() {
59
+ # Append one index line to the destination index.
60
+ #
61
+ # The line's own bytes are written verbatim: no separator normalization is performed,
62
+ # because the field is defined as the index line from the source worktree and
63
+ # re-rendering the separator would drift from both conventions in use in this
64
+ # repository. Only the line terminator is supplied here.
65
+ #
66
+ # Args: $1 = index path, $2 = the index line, $3 = the terminator token as returned by
67
+ # preserve_derive_line_ending, $4 = `yes` when the target's final byte is not a line
68
+ # feed and a leading terminator has to be written first.
69
+ #
70
+ # The terminator is selected from the token and from nothing else. An `absent` target
71
+ # is created with a line feed, because .gitattributes guarantees a line feed for every
72
+ # tracked path in this repository and a newly tracked file can hold no other
73
+ # convention. A `mixed` target never reaches this function: it is refused in the
74
+ # read-only phase.
75
+ local index=${1-} line=${2-} token=${3:-lf} pre=${4:-no}
76
+ local term
77
+ term=$(
78
+ preserve_line_terminator "$token"
79
+ printf x
80
+ )
81
+ term=${term%x}
82
+ {
83
+ if [[ $pre == "yes" ]]; then
84
+ printf '%s' "$term"
85
+ fi
86
+ printf '%s%s' "$line" "$term"
87
+ } >>"$index"
88
+ }
89
+
90
+ preserve_derive_line_ending() {
91
+ # Echo exactly one token describing the named file's line-ending convention:
92
+ # `absent`, `lf`, `crlf`, or `mixed`.
93
+ #
94
+ # The convention is derived from the file's current bytes at run time. The manifest's
95
+ # advisory line_ending field is never an input to this decision; it is compared against
96
+ # the answer and never substituted for it.
97
+ #
98
+ # Only TERMINATED lines are counted. `read` returns non-zero on a final line that
99
+ # carries no terminator, so the loop below does not count it, which is the correct
100
+ # reading of the contract: an unterminated final line has no terminator to classify.
101
+ # The separate question of whether one has to be written before an append is answered
102
+ # by preserve_index_needs_terminator.
103
+ #
104
+ # A non-empty file holding no terminated line at all falls to `lf`. That case is
105
+ # outside the specification's table, and `lf` is the safe answer because the
106
+ # repository's .gitattributes guarantees a line feed for every tracked path, so a newly
107
+ # terminated file can hold no other convention.
108
+ local path=${1-}
109
+ if [[ ! -f $path || ! -s $path ]]; then
110
+ printf 'absent\n'
111
+ return 0
112
+ fi
113
+ local line total=0 crlf=0
114
+ while IFS= read -r line; do
115
+ total=$((total + 1))
116
+ if [[ $line == *$'\r' ]]; then
117
+ crlf=$((crlf + 1))
118
+ fi
119
+ done <"$path"
120
+ if ((total == 0 || crlf == 0)); then
121
+ printf 'lf\n'
122
+ elif ((crlf == total)); then
123
+ printf 'crlf\n'
124
+ else
125
+ printf 'mixed\n'
126
+ fi
127
+ }
128
+
129
+ preserve_index_needs_terminator() {
130
+ # Report whether a terminator has to be written before the append, which is the case
131
+ # when the file exists, is not empty, and its final byte is not a line feed.
132
+ #
133
+ # `wc -l` counts newline characters, so a file whose last line carries no terminator
134
+ # would otherwise have the new index line concatenated onto its existing last entry.
135
+ # The trailing `printf x` is required: command substitution strips trailing newlines,
136
+ # so without a sentinel the line-feed case and the no-final-byte case would be
137
+ # indistinguishable.
138
+ #
139
+ # Args: $1 = path. Returns 0 when a leading terminator is needed.
140
+ local path=${1-} last
141
+ [[ -f $path && -s $path ]] || return 1
142
+ last=$(
143
+ tail -c 1 -- "$path" 2>/dev/null
144
+ printf x
145
+ )
146
+ last=${last%x}
147
+ [[ $last != $'\n' ]]
148
+ }
149
+
150
+ # SC2034 is disabled for this function only. The four PRESERVE_INDEX_* variables and
151
+ # PRESERVE_EXIT are written here and read by preserve_plan_one and preserve_commit_plan in
152
+ # the sibling cleanup_worktrees_preserve_lib.sh, which shellcheck analyses as a separate
153
+ # file and therefore cannot see. They are deliberately globals rather than return values
154
+ # because a shell function returns one integer and this decision carries four fields.
155
+ # shellcheck disable=SC2034
156
+ preserve_plan_index() {
157
+ # Decide what happens to one record's destination index. Performs no write.
158
+ #
159
+ # The destination index is the MEMORY.md sibling of target_path, derived from
160
+ # target_path's own directory and never from the source's, because the index line
161
+ # belongs to the destination namespace and re-namespacing during consolidation is
162
+ # permitted.
163
+ #
164
+ # Args: $1 = target_path, $2 = the index line, $3 = the advisory line_ending value,
165
+ # $4 = the consolidation worktree path.
166
+ #
167
+ # Sets PRESERVE_INDEX_ACTION (`none`, `append`, or `create`), PRESERVE_INDEX_PATH,
168
+ # PRESERVE_INDEX_TERM, and PRESERVE_INDEX_PRE for the writing phase to consume.
169
+ # Returns 0 to proceed with the record and 1 to refuse it outright.
170
+ local tgt=${1-} advisory=${3-} cwt=${4-}
171
+ local tdir=""
172
+ [[ $tgt != */* ]] || tdir="${tgt%/*}/"
173
+ PRESERVE_INDEX_ACTION="none"
174
+ PRESERVE_INDEX_PATH="$cwt/${tdir}MEMORY.md"
175
+ PRESERVE_INDEX_TERM="lf"
176
+ PRESERVE_INDEX_PRE="no"
177
+ local derived
178
+ derived=$(preserve_derive_line_ending "$PRESERVE_INDEX_PATH")
179
+ if [[ $derived != "$advisory" ]]; then
180
+ # The advisory value disagreed with the target's own bytes. Report it and proceed
181
+ # with the re-derived value; the advisory value never changes what is written.
182
+ printf 'ACTION|preserve-eol|%s|ADVISORY-MISMATCH\n' "$PRESERVE_INDEX_PATH"
183
+ printf 'cleanup-worktrees: advisory line_ending %s disagrees with the derived %s: %s\n' \
184
+ "$advisory" "$derived" "$PRESERVE_INDEX_PATH" >&2
185
+ fi
186
+ if [[ $derived == "mixed" ]]; then
187
+ # Refuse rather than normalize. There is no convention to normalize to, and a
188
+ # majority rule would silently rewrite the operator's file.
189
+ printf 'ACTION|preserve-index|%s|EOL-MIXED\n' "$PRESERVE_INDEX_PATH"
190
+ printf 'cleanup-worktrees: refusing an index with mixed line endings: %s\n' \
191
+ "$PRESERVE_INDEX_PATH" >&2
192
+ PRESERVE_EXIT=1
193
+ return 1
194
+ fi
195
+ if [[ $derived == "absent" ]]; then
196
+ PRESERVE_INDEX_ACTION="create"
197
+ printf 'ACTION|preserve-index|%s|CREATED\n' "$PRESERVE_INDEX_PATH"
198
+ PRESERVE_EXIT=1
199
+ return 0
200
+ fi
201
+ if preserve_index_has_entry "$PRESERVE_INDEX_PATH" "${tgt##*/}"; then
202
+ printf 'ACTION|preserve-index|%s|SKIPPED-DUPLICATE\n' "$PRESERVE_INDEX_PATH"
203
+ return 0
204
+ fi
205
+ PRESERVE_INDEX_ACTION="append"
206
+ PRESERVE_INDEX_TERM="$derived"
207
+ if preserve_index_needs_terminator "$PRESERVE_INDEX_PATH"; then
208
+ PRESERVE_INDEX_PRE="yes"
209
+ fi
210
+ printf 'ACTION|preserve-index|%s|OK\n' "$PRESERVE_INDEX_PATH"
211
+ return 0
212
+ }