@indigoai-us/hq-cli 5.324.0 → 5.325.0
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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.325.0] — 2026-10-02
|
|
6
|
+
- Match Bash pathname expansion in native derive-trigger-facts when a glob has missing suffixes, a trailing slash, or symlink path components.
|
|
7
|
+
|
|
5
8
|
## [5.324.0] — 2026-10-02
|
|
6
9
|
- Keep the bundled shell runner out of native fast-route startup and defer timeout-guard flag snapshot imports until a timeout would block.
|
|
7
10
|
- Reuse the parsed fast-route entry when dispatching the selected command.
|
|
@@ -62,22 +62,50 @@ function globSegmentMatches(pattern, value) {
|
|
|
62
62
|
return false;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
function filesystemPath(candidate, cwd) {
|
|
66
|
+
const value = candidate || ".";
|
|
67
|
+
return path.isAbsolute(value) ? value : `${cwd}${path.sep}${value}`;
|
|
68
|
+
}
|
|
69
|
+
function isDirectoryPath(candidate, cwd) {
|
|
70
|
+
try {
|
|
71
|
+
return fs.statSync(filesystemPath(candidate, cwd)).isDirectory();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function pathEntryExists(candidate, cwd) {
|
|
78
|
+
try {
|
|
79
|
+
fs.lstatSync(filesystemPath(candidate, cwd));
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
65
86
|
function expandBashGlob(token, cwd) {
|
|
66
87
|
if (!hasGlobPattern(token))
|
|
67
88
|
return [token];
|
|
68
89
|
const absolute = token.startsWith(path.sep);
|
|
90
|
+
const trailingSlash = token.endsWith(path.sep);
|
|
69
91
|
const parts = token.split(path.sep).filter((part, index) => !(absolute && index === 0));
|
|
92
|
+
if (trailingSlash)
|
|
93
|
+
parts.pop();
|
|
70
94
|
let candidates = [absolute ? path.sep : ""];
|
|
71
95
|
let matchedPattern = false;
|
|
72
|
-
for (const part of parts) {
|
|
96
|
+
for (const [index, part] of parts.entries()) {
|
|
73
97
|
if (!hasGlobPattern(part)) {
|
|
74
98
|
candidates = candidates.map((parent) => !parent ? part : parent === path.sep ? `${path.sep}${part}` : `${parent}${path.sep}${part}`);
|
|
99
|
+
if (matchedPattern) {
|
|
100
|
+
const needsDirectory = index < parts.length - 1 || trailingSlash;
|
|
101
|
+
candidates = candidates.filter((candidate) => needsDirectory ? isDirectoryPath(candidate, cwd) : pathEntryExists(candidate, cwd));
|
|
102
|
+
}
|
|
75
103
|
continue;
|
|
76
104
|
}
|
|
77
105
|
matchedPattern = true;
|
|
78
106
|
const expanded = [];
|
|
79
107
|
for (const parent of candidates) {
|
|
80
|
-
const directory =
|
|
108
|
+
const directory = filesystemPath(parent || ".", cwd);
|
|
81
109
|
let names;
|
|
82
110
|
try {
|
|
83
111
|
names = fs.readdirSync(directory).sort();
|
|
@@ -97,7 +125,13 @@ function expandBashGlob(token, cwd) {
|
|
|
97
125
|
return [token];
|
|
98
126
|
candidates = expanded;
|
|
99
127
|
}
|
|
100
|
-
|
|
128
|
+
if (trailingSlash) {
|
|
129
|
+
candidates = candidates
|
|
130
|
+
.filter((candidate) => isDirectoryPath(candidate, cwd))
|
|
131
|
+
.map((candidate) => candidate.endsWith(path.sep) ? candidate : `${candidate}${path.sep}`)
|
|
132
|
+
.sort();
|
|
133
|
+
}
|
|
134
|
+
return matchedPattern && candidates.length > 0 ? candidates : [token];
|
|
101
135
|
}
|
|
102
136
|
function bashUnquotedWords(facts, cwd) {
|
|
103
137
|
return facts.join(" ").split(/[\t\n ]+/).filter(Boolean).flatMap((word) => expandBashGlob(word, cwd));
|