gsd-core Workstream 命名规范化:CJS 与 SDK 双层的名字校验、路径穿越拦截与活动指针安全
【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载本篇围绕 gsd-core 的一次缺陷修复changesetFixed对应 PR #3269展开工作流workstream名称现在在 CJS 层与 SDK 层使用同一套校验规则仅接受字母数字、连字符、下划线和点号如v1.0并在两层同时拦截..路径穿越序列model_profile: inherit哨兵值不再作为字面模型 ID 泄漏到 session-runnerSDK 的writeActiveWorkstream在写入指针前会先校验目标 workstream 目录存在。读完后你可以掌握 gsd-core 活动工作流指针的完整解析链路、命名策略源码实现以及如何在自己的代码或插件中安全地复用这套校验逻辑。为什么需要统一的工作流命名策略gsd-core 的多工作流workstream体系把每个工作流的计划数据存放在.planning/workstreams/name/目录下并用一个活动工作流指针记录当前会话正在操作的工作流。这意味着workstream 名称会直接参与文件路径拼接——一旦名称中可以混入../、空格或特殊字符轻则指针解析失败重则发生路径穿越path traversal。活动工作流的解析优先级在 active-workstream-store 的模块注释中明确定义为三级CLI 参数--ws最高优先级环境变量GSD_WORKSTREAM已存储的活动工作流指针session 指针或共享标记.planning/active-workstreamresolveActiveWorkstream 按此顺序解析并对最终结果做一次统一校验// src/active-workstream-store.cts if (ws !validateWorkstreamName(ws)) { throw new Error(Invalid workstream name: must be alphanumeric, hyphens, underscores, or dots); }本修复的核心目标就是让任何一条入口CLI、环境变量、存储指针、SDK 写入拿到的名字都必须通过同一套规则校验且 CJS 层与 SDK 层的行为保持字节级一致避免某一层放行、另一层拒绝造成的行为漂移。命名规则正则、路径段检查与错误消息校验逻辑的单一事实源是 workstream-name-policy。核心规则如下// src/workstream-name-policy.cts export const INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE Invalid workstream name: must be alphanumeric, hyphens, underscores, or dots; const ACTIVE_WORKSTREAM_RE /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;规则说明首字符必须为字母或数字[a-zA-Z0-9]不允许以.、-、_开头后续字符允许字母、数字、点.、下划线_、连字符-因此v1.0这类语义化版本名是合法工作流名空值处理normalizeWorkstreamNameInput先trim空串归一化为null返回reason: empty路径段检查hasInvalidPathSegment拒绝任何路径分隔符/、\、裸点.、以及包含..的序列非法值返回{ ok: false, reason: invalid, value }保留原值便于诊断两个检查函数各自承担不同职责hasInvalidPathSegment防御性检查源码注释说明其目标是任何会把名字变成不安全文件系统路径段的形态——路径分隔符、裸点、..序列。validateActiveWorkstreamName先做路径段检查再跑ACTIVE_WORKSTREAM_RE两步都通过才返回ok: true。注意顺序上的细节即便正则本身不允许/和\hasInvalidPathSegment仍然先行判断..等危险序列。这种纵深防御的写法保证了即使未来正则放宽路径穿越检查依然独立生效。面向 SDK 层的调用方模块还导出了两个便捷入口// src/workstream-name-policy.cts /** Alias for isValidActiveWorkstreamName; provided for SDK-layer callers. */ export function validateWorkstreamName(name: string | null | undefined): boolean { return isValidActiveWorkstreamName(name); }以及带异常语义的断言版本供内部热路径使用校验失败抛出可定制的Error成功时返回归一化后的名字export function assertValidActiveWorkstreamName( name: string | null | undefined, errorMessage: string INVALID_ACTIVE_WORKSTREAM_NAME_MESSAGE, ): string { const validation validateActiveWorkstreamName(name); if (!validation.ok) { throw new Error(errorMessage); } return validation.value!; }active-workstream-store 内部也复用同一策略模块validateWorkstreamName在其内部只是isValidActiveWorkstreamName的别名——这正是 changeset 中CJS 与 SDK 层一致校验这一承诺在源码上的落点两层不各写一份正则而是共享同一个策略实现。活动指针写入先验目录再写指针changeset 的第三点修复是SDKwriteActiveWorkstream现在在写入指针前校验目标工作流目录存在。在仓库源码中CJS 侧对应的写入入口是 setActiveWorkstreamfunction setActiveWorkstream(cwd: string, name: string | null | undefined, opts: ActiveWorkstreamOpts {}): void { const adapter pickActiveWorkstreamAdapter(cwd, opts); if (!adapter) return; if (!name) { adapter.clear(); return; } if (!validateWorkstreamName(name)) { throw new Error(Invalid workstream name: must be alphanumeric, hyphens, underscores, or dots); } const wsDir path.join(planningRoot(cwd), workstreams, name); platformEnsureDir(wsDir); adapter.write(name); }可以看到写入链路是三步原子序格式校验——非法名字直接抛错指针文件绝不会被写坏目录就位——确保.planning/workstreams/name存在platformEnsureDir落盘指针——由 WorkstreamPointerAdapter 接口执行write共享标记写入.planning/active-workstreamsession 指针写入系统临时目录下的会话作用域文件。读取侧则要求反向一致一个名字不仅要格式合法其目录还必须真实存在。这一可解析谓词被单独抽出// src/active-workstream-store.cts function resolvesToExistingWorkstream(cwd: string, name: string | null): name is string { if (!name || !validateWorkstreamName(name)) return false; return fs.existsSync(path.join(planningRoot(cwd), workstreams, name)); }它被 resolveFromChain 和诊断函数 diagnoseUnresolvedActiveWorkstream 共同复用保证了写入时检查目录与读取时判定可解析用的是同一份定义。诊断函数还能区分两种都返回null的失败原因名字格式非法invalid_name与名字合法但目录缺失missing_workstream_dir这对排查指针为什么解析不出来非常实用。此外该模块刻意区分了两种读取语义值得集成方注意getActiveWorkstream带自愈self-heal发现 owned 指针失效时会clear()掉过期指针peekActiveWorkstream只读姊妹函数绝不调用clear()——注释指出statusline 这类每次渲染都会调用的只读消费者绝不能因为画个屏幕就改动跨会话的持久状态。model_profile: inherit哨兵泄漏的修复changeset 的第二点修复针对 session-runnermodel_profile: inherit之前会作为字面模型 ID 泄漏出去。inherit在 gsd-core 的模型体系里是一个哨兵值sentinel语义是跟随会话不由本层指定模型而不是任何真实存在的模型名。从 model-resolver 的实现可以印证这一语义边界——解析器在多处显式地把inherit排除在可解析为模型的分支之外// src/model-resolver.cts节选 if (!tier || tier inherit) return null; // ... : (profile inherit ? inherit : /* 解析目录中的真实模型 */); // ... if (tier inherit) return inherit;源码注释对inherit的定位非常明确model-resolvermodel_profile: inherit报告 inherit —— 会话模型不归我们命名并且要求调用方把unknown与inherit都当作无法判定而非足够好。effort 维度同理EFFORT_SET 把inherit作为声明式的跟随选择纳入合法集合但nextEffort(inherit)返回null即解析循环不会越过显式的inherit继续推断。这次修复把上述约束贯彻到了 session-runner当 profile 为inherit时session-runner 不再把字符串inherit当作模型 ID 下发而是按未指定模型处理让宿主会话自身的模型选择生效。对依赖模型目录做路由或展示的功能例如 code-review-depth 之类的深度推断这一修复避免了哨兵值被误当成真实模型去查表、比较或渲染。测试佐证与可验证性命名策略的行为有专门的测试守护。active-workstream-store 单测 中即包含rejects path traversal用例约 L75直接验证带..的名字被拒绝——这正是 changeset 承诺两层同时拦截路径穿越的可执行证据。测试文件整体覆盖了--ws解析、session 与 shared 指针的解析链、以及失效指针的自愈/只读语义。如果你想在本地复核这套行为可以# 查看命名策略源码正则、路径段检查、断言函数 less src/workstream-name-policy.cts # 查看活动指针解析链、写入前目录校验 less src/active-workstream-store.cts # 运行相关单测确认路径穿越被拒绝 node tests/active-workstream-store.unit.test.cjs小结本次修复的四个行为契约契约修复前风险源码落点双层一致的命名校验CJS 与 SDK 各写一套规则行为漂移workstream-name-policy.cts 作为单一事实源active-workstream-store.cts 复用允许点号v1.0风格语义化版本名被误拒正则[a-zA-Z0-9][a-zA-Z0-9._-]*拦截..路径穿越名字可被拼入文件路径造成穿越hasInvalidPathSegment 单测守护写指针前确认目录 inherit不泄漏悬空指针、哨兵值被当模型 IDsetActiveWorkstream、model-resolver.cts 中inherit分支这套机制对扩展开发者的实际意义是无论是通过--ws、GSD_WORKSTREAM还是 SDK 写入指针gsd-core 都保证.planning/workstreams/name路径永远处于项目目录之内且指针要么指向真实存在的目录要么被解析链安全地判为无活动工作流并可经诊断接口定位原因。理解这条链路后你在编写宿主插件或外部集成时只要复用validateWorkstreamName/assertValidActiveWorkstreamName这两个公开入口就能与核心保持完全一致的命名与安全语义。赞分享【免费下载链接】gsd-coreGit. Ship. Done - Core项目地址https://gitcode.com/gh_mirrors/ge/gsd-core点击查看免费下载相关推荐get-shit-done 工作流名称规范化与路径穿越防护CJS/SDK 双层校验一致性加固解析get shit done 工作流名称规范化与路径穿越防护CJS/SDK 双层校验一致性加固解析 本文围绕 get shit doneTÂCHES 出品的轻人工智能AI 应用提示工程开发工具工作流自动化AI Agentget-shit-done SDK 安全加固剖析relPlanningPath 对工作流名的路径穿越校验Issue 3589get shit done SDK 安全加固剖析relPlanningPath 对工作流名的路径穿越校验Issue 3589 本文基于仓库中的变更集文档人工智能AI 应用提示工程开发工具工作流自动化AI Agentget-shit-done 命令契约校验ADR-0002以双层校验与前端字段规范锁定 65 个 gsd 斜杠命令的质量基线get shit done 命令契约校验ADR 0002以双层校验与前端字段规范锁定 65 个 gsd 斜杠命令的质量基线 导读 本篇文章围绕 get s人工智能AI 应用提示工程开发工具工作流自动化AI Agent上一篇Whispering资源限制设置控制CPU与内存使用的系统配置下一篇murex错误处理终极指南告别shell脚本的泄漏故障模式创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考