Files
gstack/scripts/qid-marker.ts
T
Garry Tanandcapy-ai[bot] 68b1d056a4 Fix five small browse and question-hook bugs (#4192)
* Keep the scroll selector when --wait is absent

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Skip a PATH browse that links to another program such as xdg-open

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Give each project its own browse slug on installs without ~/.claude

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep a question marker when its signal hint is malformed

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Read the lowercased question id in the never-ask preference hook

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep a marker's tail in the one-way door check

Review-Finding: p1/targeted#1 reader=targeted
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Keep a marker's tail apart from the next word in the one-way door check

Review-Finding: p2/outside-voice#1 reader=outside-voice
Review-Finding: p2/adversarial-native#1 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Say where old domain skills live and narrow the marker note in the changelog

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Say how the browse daemon picks a project's domain skill file

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
2026-11-09 06:38:42 +00:00

32 lines
1.1 KiB
TypeScript

/**
* The <gstack-qid:...> marker a skill puts in an asked question (#3442).
*
* `<gstack-qid:{id}>` names the question; an unregistered id may add a
* signal hint, `<gstack-qid:{id};signal={signal_key}>`, naming the
* SIGNAL_MAP key its answer speaks to. Ids and keys are read lowercase.
* A malformed hint (an underscore, a space, an empty or unknown key name)
* is dropped on its own; the id still names the question. Whether a hint
* is a real SIGNAL_MAP key is checked where the row is logged
* (bin/gstack-question-log), not here.
*/
export const QID_MARKER_RE = /<gstack-qid:([a-z0-9-]{1,64})(?:;([^<>\n]{0,128}))?>/i;
const SIGNAL_HINT_RE = /^signal=([a-z0-9-]{1,64})$/i;
export interface QidMarker {
id: string;
signal_key?: string;
stripped: string;
}
export function parseQidMarker(text: string): QidMarker | undefined {
const m = QID_MARKER_RE.exec(text);
if (!m) return undefined;
const hint = m[2] === undefined ? undefined : SIGNAL_HINT_RE.exec(m[2])?.[1];
return {
id: m[1]!.toLowerCase(),
...(hint ? { signal_key: hint.toLowerCase() } : {}),
stripped: text.replace(QID_MARKER_RE, '').trim(),
};
}