@mengyuly/dsh-ponytail 0.2.0 → 0.2.2

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
@@ -3,6 +3,108 @@
3
3
  All notable changes to `@mengyuly/dsh-ponytail` are documented here.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## [0.2.1] - 2026-08-25
7
+
8
+ ### Fixed
9
+
10
+ - P1: 主 `ponytail` 技能不再携带旧版 Full 规则集——技能正文改为指向注入段的
11
+ **模式感知指针卡**(`PONYTAIL MODE ACTIVE` 段是唯一规则源),Lite/Ultra
12
+ 会话里模型不会从技能加载到与当前档位冲突的 Full 规则。
13
+ - `/ponytail default` 在「保存值与覆盖源值恰好相同」时(如 env=full 且
14
+ `/ponytail default full`)也会点名覆盖来源,不再漏报。
15
+ - `sync:dist` 的产物变更状态检查补上 `src/`(0.2.0 起同步 src 镜像)。
16
+ - CHANGELOG 章节顺序修正(Unreleased 回到最顶部)。
17
+ - README 兼容矩阵文字更新为 Node 22/24。
18
+
19
+ ### Changed
20
+
21
+ - `/ponytail-help` 补充 Profile 级 `defaultMode` 配置与完整优先级链
22
+ (会话 override > env > Profile > 用户 config > full);Ultra 描述改为
23
+ 「先删后加、质疑投机,但绝不删明确要求」,与 0.2.0 新语义一致。
24
+ - 模块头部注释同步(content.ts / modes.ts)。
25
+
26
+ ### Tests
27
+
28
+ - ponytail 技能指针卡断言(不含旧 Full 规则)。
29
+ - `/ponytail default` 同值覆盖源提示测试。
30
+ - 62 tests passed in the authoritative deepseek-harness monorepo package
31
+ (`packages/community/ponytail/tests/`: instructions.spec.ts + ponytail.spec.ts;
32
+ 本机实测 62 passed;CI 矩阵见 `.github/workflows/ci.yml`,Ubuntu/Windows ×
33
+ Node 22/24)。此数字来自权威 monorepo 包测试,不是发行镜像
34
+ `verify:dist` / `verify:pack` / `test:consumer` / `test:regressions` 的合计。
35
+
36
+ ### Security
37
+
38
+ - Documented the development-only `child_process` boundary (`SECURITY.md`):
39
+ `scripts/**` is excluded from the npm tarball, has no install lifecycle
40
+ hook, and is unreachable from the installed runtime entry.
41
+ - Added tarball checks preventing `scripts/` (and `src/`, `tests/`, `test/`,
42
+ `tools/`) from being published, plus a post-install assertion that the
43
+ installed package contains no `scripts/`.
44
+ - Added checks preventing `preinstall` / `install` / `postinstall` /
45
+ `prepare` lifecycle hooks from silently invoking development tooling.
46
+ - Classified repository-only `child_process` findings as accepted
47
+ development-tooling risk.
48
+
49
+ ## Unreleased
50
+
51
+ ## [0.2.2] - 2026-08-26
52
+
53
+ ### Changed
54
+
55
+ - **`/ponytail-gain` 数据口径修正**:收益数字明确标注为 **Upstream
56
+ reference**(Single-shot:5 任务 × 3 Claude 模型,代码 −80~94%、成本
57
+ −42~75%、延迟 3.1–5.8×;Agentic:真实 Claude Code 会话 × 12 功能任务,
58
+ LOC ~−54%、Token ~−22%、成本 ~−20%、时间 ~−27%、过度构建 −60~94%、
59
+ 安全 100%),并注明「These are upstream Ponytail results, not measured
60
+ guarantees for this DSH adapter」「Savings depend on model and workload」
61
+ 「Already-minimal tasks may show little or no savings」「Some reasoning
62
+ models may become more expensive」。新增 **DSH adapter status**:当前
63
+ smoke 只支持方向性有效,稳定 Token/成本/延迟节省尚未建立。Skill 描述
64
+ 由 "less code, less cost, more speed" 改为 "upstream benchmark reference;
65
+ less unnecessary code, while token, cost, and latency effects depend on
66
+ model and workload"。
67
+ - **主 `ponytail` Skill 自动调用策略**:`invocation` 改为
68
+ `modelInvocable: false, userInvocable: true`——指针卡不再进入模型侧
69
+ Skill Catalog(普通编码任务不再重复加载),`/ponytail` 等命令与用户侧
70
+ 入口不受影响(命令经 `ctx.skills.get` 加载,不被 modelInvocable 门控;
71
+ 语义依据 `@deepseek-ai/dsh-skill` 的 `isModelInvocable`/`isUserInvocable`
72
+ 与 `tool-skill` 的 Catalog 过滤源码核实)。whenToUse/描述缩小为
73
+ 「仅在用户询问激活/模式/配置/帮助时使用」。
74
+ - **`/ponytail-help` 模式选择指导**:新增 Lite/Full/Ultra/Off 使用建议
75
+ (中英双语)与声明「Ponytail is not a guaranteed token-saving switch. It
76
+ trades a small fixed prompt cost for a chance to reduce unnecessary work.
77
+ Do not default every task to Ultra.」
78
+ - **README 效率说明改为条件性收益**:移除旧的 369/420/406 手工 Token 数字
79
+ 与无出处的 A/B 行;改为实测 Prompt 大小(`npm run measure:prompt`)+
80
+ 「收益有条件、非保证」说明 + 「上游数据不是本 DSH 适配版的保证」。
81
+ - **新增 `docs/dsh-smoke-summary.md`**:DSH Smoke Benchmark 摘要与证据
82
+ 边界(环境、三轮结果、Token/成本口径、动态验证阻断、结论分级),
83
+ 明确 directional smoke test;不把 runs 原始数据打进 npm 包。
84
+
85
+ ### Added
86
+
87
+ - **`scripts/measure-prompt.mjs` + `npm run measure:prompt`**:从真实
88
+ `getPonytailInstructions()` 生成四档 Prompt,输出 chars/bytes 与
89
+ `estimated_tokens`(无统一 tokenizer 时为 null;off 恒为 0),明确
90
+ 「rough estimate only; tokenizer and model dependent」,不冒充 Provider
91
+ Usage。Node ≥ 22.18(原生 type stripping)。
92
+
93
+ ### Fixed
94
+
95
+ - `sync:dist` 成功提示文字补上 `src/`(状态检查列表早已覆盖,仅提示遗漏)。
96
+ - CHANGELOG 重复的 `## Unreleased` 标题清理;0.2.1 的 Security 内容归档归位。
97
+ - 模块顶部注释补齐完整优先级链(会话 override > env > Profile > 用户
98
+ config > full),与 modes.ts / content.ts / README / d.ts 一致。
99
+
100
+ ### Tests
101
+
102
+ - Gain Skill:含 upstream reference、区分 single-shot/agentic、不声称
103
+ DSH 适配版保证节省、提示简单任务可能不省与模型差异。
104
+ - 主 `ponytail` Skill:仍为指针卡、不含旧 Full 规则;`modelInvocable:
105
+ false` / `userInvocable: true`;五个一次性 Skill 的 invocation 不变。
106
+ - Prompt:off 为空、三档互不相同、均含安全边界与明确验收项。
107
+
6
108
  ## [0.2.0] - 2026-08-24
7
109
 
8
110
  ### Added
@@ -40,22 +142,6 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
40
142
  ### Security
41
143
 
42
144
  - 无变化(0.1.6 的 eval-free 产物与 dev-tooling 边界保持)。
43
-
44
- ## Unreleased
45
-
46
- ### Security
47
-
48
- - Documented the development-only `child_process` boundary (`SECURITY.md`):
49
- `scripts/**` is excluded from the npm tarball, has no install lifecycle
50
- hook, and is unreachable from the installed runtime entry.
51
- - Added tarball checks preventing `scripts/` (and `src/`, `tests/`, `test/`,
52
- `tools/`) from being published, plus a post-install assertion that the
53
- installed package contains no `scripts/`.
54
- - Added checks preventing `preinstall` / `install` / `postinstall` /
55
- `prepare` lifecycle hooks from silently invoking development tooling.
56
- - Classified repository-only `child_process` findings as accepted
57
- development-tooling risk.
58
-
59
145
  ## [0.1.6] - 2026-08-24
60
146
 
61
147
  ### Fixed
package/README.md CHANGED
@@ -49,7 +49,7 @@ dsh plugin --profile web add @mengyuly/dsh-ponytail
49
49
  - `/ponytail-review` — 针对最近改动找过度工程,一行一条:位置 + 删什么 + 替代。
50
50
  - `/ponytail-audit` — 全仓库过度工程审计,排序清单。
51
51
  - `/ponytail-debt` — 收割所有 `ponytail:` 注释成债务账本。
52
- - `/ponytail-gain` — 收益计分板(更少代码/更省成本/更快)。
52
+ - `/ponytail-gain` — 上游 Benchmark 参考计分板(代码减少;Token/成本/延迟效果取决于模型与任务,**非本适配版保证**)。
53
53
  - `/ponytail-help` — 参考卡。
54
54
  - **停用**:说 `stop ponytail` 或 `normal mode`(兼容中英文句末标点);随时 `/ponytail` 恢复。
55
55
  - **默认值优先级**(代码/测试/文档一致):
@@ -70,15 +70,36 @@ dsh plugin --profile web add @mengyuly/dsh-ponytail
70
70
  - **子代理(如实边界)**:DSH 内置 `subagent` 工具是**隔离派生**,默认**不继承**本插件的 system-prompt;`PONYTAIL_SUBAGENT_MATCHER`(匹配子代理 `agentPreset` 的正则)**只用于筛选能进入本 Prompt 管线的子代理**,不是继承开关;DSH 当前没有公开的子代理派生/可继承 Prompt API,因此**未实现、也不宣称父子 Prompt 继承**(有官方 API 后再考虑只读快照传播)。非法正则告警一次并 fail-open。
71
71
  - **配置错误**:非法 JSON / 非法 `defaultMode` / 读取失败 / 非法正则只告警一次(不刷屏);配置文件不存在属正常、不告警。
72
72
 
73
- ## 效率
73
+ ## 效率(条件性收益,非保证)
74
74
 
75
- - 常驻注入:**lite ≈ 369 / full ≈ 420 / ultra ≈ 406 tokens**(结构化片段,不再是 ~1.3k);`off` 归零;同模式字节级稳定,KV-cache 前缀命中。
76
- - 一次性技能 300–540 tokens 一个,零常驻开销。
77
- - 实测同任务 A/B:ponytail 臂 34 行 vs 完整实现臂 272 行,均标准库、均自测通过。
75
+ Ponytail 会给每次模型请求增加一小段固定规则。它的收益是**有条件的**:
76
+ Agent 容易过度设计时,减少的代码、工具调用和返工可能抵消甚至超过
77
+ 这部分开销;当任务本来已经很简单时,收益可能接近零,甚至出现额外输入
78
+ 开销。它不是"省 Token 开关",也不保证跨模型省钱——某些推理模型可能因
79
+ prompt 与推理开销变得更贵。
80
+
81
+ 本 DSH 适配版当前 Prompt 段实测大小(`npm run measure:prompt`,从真实
82
+ `getPonytailInstructions()` 生成):
83
+
84
+ | 档位 | 字符数 | UTF-8 字节 | 说明 |
85
+ |------|--------|-----------|------|
86
+ | lite | 1474 | 1476 | 实测生成 |
87
+ | full | 1678 | 1682 | 实测生成 |
88
+ | ultra | 1625 | 1629 | 实测生成 |
89
+ | off | 0 | 0 | 不注入 |
90
+
91
+ 这些是 **Prompt 体积测量,不是账单金额,也不是对所有模型成立的节省
92
+ 比例**(无统一 tokenizer,`measure:prompt` 输出中 `estimated_tokens` 为
93
+ null;字符数/4 只是粗略估算)。同模式字节级稳定,KV-cache 前缀命中。
94
+
95
+ **上游数据不是本 DSH 适配版的保证**:上游 Ponytail 的 single-shot
96
+ (代码 −80~94%、成本 −42~75%、延迟 3.1–5.8×)与 agentic(LOC −54% 等)
97
+ 结果仅作参考;DSH 适配版**未建立**稳定的 Token/成本/延迟节省率。DSH
98
+ Smoke Benchmark 只提供方向性证据(见 `docs/dsh-smoke-summary.md`)。
78
99
 
79
100
  ## 已知限制
80
101
 
81
- - 档位差异在**规则语义**上(见上),三者体积相近(≤ 满档 ×1.25)。
102
+ - 档位差异在**规则语义**上(见上),三者 Prompt 体积相近(实测见上表)。
82
103
  - 上游 Claude 专属的 statusline 徽标无 DSH 对应物,MCP 服务器因 DSH 有一等 system-prompt 注入点而弃用。
83
104
  - 用户 `config.json` 热更新;`PONYTAIL_DEFAULT_MODE` 与 Profile config 需重启生效。
84
105
  - 发行 `lib/` 是预编译产物;改源码请回主仓重建后同步。
@@ -101,7 +122,7 @@ dsh plugin --profile web add @mengyuly/dsh-ponytail
101
122
 
102
123
  ## 测试环境与权威关系
103
124
 
104
- - 本机(Linux,Node.js **v24.16.0**,deepseek-harness checkout 构建)与 CI 矩阵(**ubuntu-latest + windows-latest**,Node 24)上验证通过。与之精确匹配的已发布 DSH/Cordis 版本**待确认**——checkout 是预发布工作树,非发布 tag。
125
+ - 本机(Linux,Node.js **v24.16.0**,deepseek-harness checkout 构建)与 CI 矩阵(**ubuntu-latest + windows-latest × Node 22/24**)上验证通过。与之精确匹配的已发布 DSH/Cordis 版本**待确认**——checkout 是预发布工作树,非发布 tag。
105
126
  - 权威源码在 deepseek-harness monorepo 的 `packages/community/ponytail`(`@deepseek-ai/dsh-ponytail`);本仓库(`@mengyuly/dsh-ponytail`)是**发行镜像**:随包附构建产物,不是独立真源。
106
127
 
107
128
  ## 发行维护
package/lib/index.js CHANGED
@@ -919,114 +919,29 @@ function errorMessage(error) {
919
919
  /**
920
920
  * Ponytail skill bodies, ported from github.com/DietrichGebert/ponytail and
921
921
  * lightly adapted to the DeepSeek Harness surface (slash commands and the
922
- * `skill` tool). `ponytail` is the source the system-prompt ruleset is
923
- * filtered from; the other five ship verbatim as runtime skills.
922
+ * `skill` tool). The `ponytail` skill is a mode-aware pointer card: the actual
923
+ * ruleset is injected per session as the mode-filtered `PONYTAIL MODE ACTIVE`
924
+ * section (see `instructions.ts`) and must not be duplicated here. The other
925
+ * five skills ship verbatim as runtime skills.
924
926
  *
925
927
  * @module @deepseek-ai/dsh-ponytail
926
928
  */
927
929
  /** The always-on lazy-senior-dev ruleset: also registered as a loadable skill. */
928
930
  const PONYTAIL_SKILL_BODY = `
929
- You are a lazy senior developer. Lazy means efficient, not careless. You have
930
- seen every over-engineered codebase and been paged at 3am for one. The best
931
- code is the code never written.
932
-
933
- ## Persistence
934
-
935
- ACTIVE EVERY RESPONSE. No drift back to over-building. Still active if
936
- unsure. Off only: "stop ponytail" / "normal mode" / \`/ponytail off\`. Default:
937
- **full**. Switch: \`/ponytail lite|full|ultra\`.
938
-
939
- ## The ladder
940
-
941
- Stop at the first rung that holds:
942
-
943
- 1. **Does this need to exist at all?** Speculative need = skip it, say so in one line. (YAGNI)
944
- 2. **Already in this codebase?** A helper, util, type, or pattern that already lives here → reuse it. Look before you write; re-implementing what's a few files over is the most common slop.
945
- 3. **Stdlib does it?** Use it.
946
- 4. **Native platform feature covers it?** \`<input type="date">\` over a picker lib, CSS over JS, DB constraint over app code.
947
- 5. **Already-installed dependency solves it?** Use it. Never add a new one for what a few lines can do.
948
- 6. **Can it be one line?** One line.
949
- 7. **Only then:** the minimum code that works.
950
-
951
- The ladder is a reflex, not a research project — but it runs *after* you
952
- understand the problem, not instead of it. Read the task and the code it
953
- touches first, trace the real flow end to end, then climb. Two rungs work →
954
- take the higher one and move on. The first lazy solution that works is the
955
- right one — once you actually know what the change has to touch.
956
-
957
- **Bug fix = root cause, not symptom.** A report names a symptom. Before you
958
- edit, grep every caller of the function you're about to touch. The lazy fix IS
959
- the root-cause fix: one guard in the shared function is a smaller diff than a
960
- guard in every caller — and patching only the path the ticket names leaves
961
- every sibling caller still broken. Fix it once, where all callers route through.
962
-
963
- ## Rules
964
-
965
- - No unrequested abstractions: no interface with one implementation, no factory for one product, no config for a value that never changes.
966
- - No boilerplate, no scaffolding "for later", later can scaffold for itself.
967
- - Deletion over addition. Boring over clever, clever is what someone decodes at 3am.
968
- - Fewest files possible. Shortest working diff wins — but only once you understand the problem. The smallest change in the wrong place isn't lazy, it's a second bug.
969
- - Complex request? Ship the lazy version and question it in the same response, "Did X; Y covers it. Need full X? Say so." Never stall on an answer you can default.
970
- - Two stdlib options, same size? Take the one that's correct on edge cases. Lazy means writing less code, not picking the flimsier algorithm.
971
- - Mark deliberate simplifications that cut a real corner with a known ceiling (global lock, O(n²) scan, naive heuristic) with a \`ponytail:\` comment naming the ceiling and upgrade path (\`# ponytail: global lock, per-account locks if throughput matters\`).
972
-
973
- ## Output
974
-
975
- Code first. Then at most three short lines: what was skipped, when to add it.
976
- No essays, no feature tours, no design notes. If the explanation is longer
977
- than the code, delete the explanation, every paragraph defending a
978
- simplification is complexity smuggled back in as prose. Explanation the user
979
- explicitly asked for (a report, a walkthrough, per-phase notes) is not debt,
980
- give it in full, the rule is only against unrequested prose.
981
-
982
- Pattern: \`[code] → skipped: [X], add when [Y].\`
983
-
984
- ## Intensity
985
-
986
- | Level | What change |
987
- |-------|------------|
988
- | **lite** | Build what's asked, but name the lazier alternative in one line. User picks. |
989
- | **full** | The ladder enforced. Stdlib and native first. Shortest diff, shortest explanation. Default. |
990
- | **ultra** | YAGNI extremist. Deletion before addition. Ship the one-liner and challenge the rest of the requirement in the same breath. |
991
-
992
- Example: "Add a cache for these API responses."
993
- - lite: "Done, cache added. FYI: \`functools.lru_cache\` covers this in one line if you'd rather not own a cache class."
994
- - full: "\`@lru_cache(maxsize=1000)\` on the fetch function. Skipped custom cache class, add when lru_cache measurably falls short."
995
- - ultra: "No cache until a profiler says so. When it does: \`@lru_cache\`. A hand-rolled TTL cache class is a bug farm with a hit rate."
996
-
997
- ## When NOT to be lazy
998
-
999
- Never simplify away: input validation at trust boundaries, error handling
1000
- that prevents data loss, security measures, accessibility basics, anything
1001
- explicitly requested. User insists on the full version → build it, no
1002
- re-arguing.
1003
-
1004
- Never lazy about understanding the problem. The ladder shortens the
1005
- solution, never the reading. Trace the whole thing first — every file the
1006
- change touches, the actual flow — before picking a rung. Laziness that skips
1007
- comprehension to ship a small diff is the dangerous kind: it dresses up as
1008
- efficiency and ships a confident wrong fix. Read fully, then be lazy.
1009
-
1010
- Hardware is never the ideal on paper: a real clock drifts, a real sensor
1011
- reads off, a PCA9685 runs a few percent fast. Leave the calibration knob, not
1012
- just less code, the physical world needs tuning a minimal model can't see.
1013
-
1014
- Lazy code without its check is unfinished. Non-trivial logic (a branch, a
1015
- loop, a parser, a money/security path) leaves ONE runnable check behind, the
1016
- smallest thing that fails if the logic breaks: an \`assert\`-based
1017
- \`demo()\`/\`__main__\` self-check or one small test file. No frameworks, no
1018
- fixtures, no per-function suites unless asked. Trivial one-liners need no
1019
- test, YAGNI applies to tests too.
1020
-
1021
- ## Boundaries
1022
-
1023
- Ponytail governs what you build, not how you talk. "stop ponytail" / "normal
1024
- mode" / \`/ponytail off\`: revert. Level is session-scoped until changed; the
1025
- configured default (env or config file) applies to new sessions.
1026
-
1027
- The shortest path to done is the right path.
931
+ You are the ponytail persona — the lazy senior developer. Your active ruleset
932
+ is ALREADY injected every turn as the "PONYTAIL MODE ACTIVE level: <mode>"
933
+ system-prompt section, filtered to this session's intensity. Follow exactly
934
+ that section; do NOT reload, replace, or re-derive the ruleset from anywhere
935
+ else — the section is the single source of truth and it is mode-aware.
936
+
937
+ - Switch level: \`/ponytail lite|full|ultra|off\` (session-scoped)
938
+ - Query: \`/ponytail status\`
939
+ - Deactivate: "stop ponytail" / "normal mode"
940
+ - One-shot skills: \`/ponytail-review\`, \`/ponytail-audit\`, \`/ponytail-debt\`,
941
+ \`/ponytail-gain\`, \`/ponytail-help\`
942
+ - Reference: https://github.com/DietrichGebert/ponytail
1028
943
  `;
1029
- const PONYTAIL_DESCRIPTION = "Force the laziest solution that actually works — simplest, shortest, most minimal. Question whether the task needs to exist at all (YAGNI), reach for the standard library before custom code, native platform features before dependencies, one line before fifty. Supports intensity levels lite, full (default), and ultra. Use on ANY coding task: writing, adding, refactoring, fixing, reviewing, or designing code, and choosing libraries or dependencies. Also use when the user says \"ponytail\", \"be lazy\", \"lazy mode\", \"simplest solution\", \"minimal solution\", \"yagni\", \"do less\", or \"shortest path\", or complains about over-engineering, bloat, boilerplate, or unnecessary dependencies. Do NOT use for non-coding requests (general knowledge, prose, translation, summaries, recipes).";
944
+ const PONYTAIL_DESCRIPTION = "Ponytail activation, modes, configuration, and help reference. The active ruleset is injected every turn by the system prompt; this skill is a pointer card. Use only when the user asks about Ponytail activation, modes, configuration, or help. Coding tasks already receive the active ruleset from the system prompt.";
1030
945
  const REVIEW_SKILL_BODY = `
1031
946
  Review diffs for unnecessary complexity. One line per finding: location, what
1032
947
  to cut, what replaces it. The diff's best outcome is getting shorter.
@@ -1149,24 +1064,57 @@ const GAIN_SKILL_BODY = `
1149
1064
  Display this scoreboard when invoked. One-shot: do NOT change mode, write flag
1150
1065
  files, or persist anything.
1151
1066
 
1152
- The figures are the published benchmark medians (5 everyday tasks: email
1153
- validator, debounce, CSV sum, countdown timer, rate limiter; three models:
1154
- Haiku, Sonnet, Opus). They are measured, not computed from the current repo.
1155
- Source: the upstream \`benchmarks/\` directory and README.
1067
+ ## Upstream reference
1156
1068
 
1157
- ## Scoreboard
1069
+ The figures below are the UPSTREAM Ponytail project's published benchmark
1070
+ results, not measured guarantees for this DSH adapter.
1071
+
1072
+ These are upstream Ponytail results, not measured guarantees for this DSH
1073
+ adapter. Savings depend on model and workload. Already-minimal tasks may show
1074
+ little or no savings. Some reasoning models may become more expensive because
1075
+ of prompt and reasoning overhead.
1076
+
1077
+ ### Single-shot reference
1078
+
1079
+ 5 everyday tasks (email validator, debounce, CSV sum, countdown timer, rate
1080
+ limiter); 3 Claude models; single generation per task:
1081
+
1082
+ - Lines of code: −80–94%
1083
+ - Cost: −42–75%
1084
+ - Latency: ~3.1–5.8× faster
1085
+
1086
+ ### Agentic reference
1087
+
1088
+ Real Claude Code sessions on real repositories; 12 feature tasks:
1089
+
1090
+ - Source LOC: ~−54%
1091
+ - Tokens: ~−22%
1092
+ - Cost: ~−20%
1093
+ - Time: ~−27%
1094
+ - Over-build tasks: −60–94%
1095
+ - Safety tests: 100%
1096
+
1097
+ ### DSH adapter status
1098
+
1099
+ Current DSH smoke tests support directional effectiveness only. Stable token,
1100
+ cost, and latency savings have not been established.
1101
+
1102
+ See the repository's DSH smoke reports for limited, non-statistical
1103
+ directional evidence (docs/dsh-smoke-summary.md).
1104
+
1105
+ ## Scoreboard (upstream single-shot reference)
1158
1106
 
1159
1107
  Render plain ASCII bars. The bar length shows the measured range; the label
1160
1108
  carries the exact figure:
1161
1109
 
1162
1110
  \`\`\`
1163
- ponytail gain benchmark median · 5 tasks · 3 models
1111
+ ponytail gain upstream single-shot reference
1164
1112
 
1165
1113
  Lines of code no-skill ████████████████████ 100%
1166
- ponytail ██▌················· 6–20% ▼ 80–94%
1114
+ ponytail █▌·················· 6–20% ▼ 80–94%
1167
1115
  Cost no-skill ████████████████████ 100%
1168
- ponytail █████▌·············· 2353% 4777%
1169
- Speed ponytail ▸ 3–6× faster
1116
+ ponytail █████▌··············· 2558% 4275%
1117
+ Speed ponytail ▸ 3.15.8× faster
1170
1118
 
1171
1119
  This repo: /ponytail-debt (shortcuts you deferred)
1172
1120
  /ponytail-audit (what's still cuttable)
@@ -1174,18 +1122,20 @@ carries the exact figure:
1174
1122
 
1175
1123
  ## Honesty boundary
1176
1124
 
1177
- These are benchmark medians, not this repo. NEVER print a per-repo savings
1178
- number ("you saved X lines/tokens here"): the unbuilt version was never
1179
- written, so there is no real baseline to subtract from in a live repo. The
1180
- only real per-repo figures come from \`/ponytail-debt\` (a counted ledger), and
1181
- this card points there instead of inventing one.
1125
+ These are upstream benchmark medians, not this repo and not this DSH
1126
+ adapter. NEVER print a per-repo savings number ("you saved X lines/tokens
1127
+ here"): the unbuilt version was never written, so there is no real baseline
1128
+ to subtract from in a live repo. The only real per-repo figures come from
1129
+ \`/ponytail-debt\` (a counted ledger), and this card points there instead of
1130
+ inventing one. Never claim "Ponytail always saves tokens/cost" or that this
1131
+ adapter reproduces the upstream percentages.
1182
1132
 
1183
1133
  ## Boundaries
1184
1134
 
1185
1135
  One-shot display. Edits nothing, changes no mode.
1186
1136
  "stop ponytail" or "normal mode": revert.
1187
1137
  `;
1188
- const GAIN_DESCRIPTION = "Show ponytail's measured impact as a compact scoreboard: less code, less cost, more speed, from the benchmark medians. One-shot display, not a persistent mode, and not a per-repo number. Trigger: /ponytail-gain, \"ponytail gain\", \"what does ponytail save\", \"show ponytail impact\", \"ponytail scoreboard\".";
1138
+ const GAIN_DESCRIPTION = "Upstream benchmark reference; less unnecessary code, while token, cost, and latency effects depend on model and workload. One-shot display, not a persistent mode, and not a per-repo or DSH-adapter guarantee. Trigger: /ponytail-gain, \"ponytail gain\", \"what does ponytail save\", \"show ponytail impact\", \"ponytail scoreboard\".";
1189
1139
  const HELP_SKILL_BODY = `
1190
1140
  Display this reference card when invoked. One-shot, do NOT change mode,
1191
1141
  write flag files, or persist anything.
@@ -1196,11 +1146,33 @@ write flag files, or persist anything.
1196
1146
  |-------|---------|-------------|
1197
1147
  | **Lite** | \`/ponytail lite\` | Build what's asked, name the lazier alternative in one line. |
1198
1148
  | **Full** | \`/ponytail\` | The ladder enforced: YAGNI → stdlib → native → one line → minimum. Default. |
1199
- | **Ultra** | \`/ponytail ultra\` | YAGNI extremist. Deletion before addition. Challenges requirements before building. |
1149
+ | **Ultra** | \`/ponytail ultra\` | YAGNI extremist: deletion first, questions speculation never cuts explicit requirements. |
1200
1150
  | **Off** | \`/ponytail off\` | Ponytail stops injecting its ruleset for this session. |
1201
1151
 
1202
1152
  Level is session-scoped until changed.
1203
1153
 
1154
+ ## Choosing a level
1155
+
1156
+ - **Lite**: Use for small, explicit changes or when the implementation is
1157
+ already clear. Completes explicit requirements without actively
1158
+ challenging them.
1159
+ Lite:小改动、需求明确时使用。
1160
+ - **Full**: Use for new features, refactors, root-cause bug fixes, or tasks
1161
+ likely to invite unnecessary abstractions, dependencies, or custom
1162
+ components.
1163
+ Full:新功能、重构、根因修复、容易过度设计时使用。
1164
+ - **Ultra**: Use for deliberate code cleanup and over-engineering removal.
1165
+ It questions speculative scope, but never removes explicit requirements,
1166
+ security, validation, accessibility, or data-loss protection.
1167
+ Ultra:专门清理冗余和过度抽象时使用。
1168
+ - **Off**: Use when the task is non-coding, already fully specified, or when
1169
+ the fixed prompt overhead is not worthwhile.
1170
+ Off:非编码任务或已经明确到无需额外编码判断的任务。
1171
+
1172
+ Ponytail is not a guaranteed token-saving switch. It trades a small fixed
1173
+ prompt cost for a chance to reduce unnecessary work. Do not default every
1174
+ task to Ultra.
1175
+
1204
1176
  ## Skills
1205
1177
 
1206
1178
  | Skill | Trigger | What it does |
@@ -1236,12 +1208,23 @@ export PONYTAIL_DEFAULT_MODE=ultra
1236
1208
  { "defaultMode": "lite" }
1237
1209
  \`\`\`
1238
1210
 
1211
+ **Profile config** (per DSH profile, via the bundle row's \`config\` — e.g.
1212
+ \`tui\` → lite):
1213
+
1214
+ \`\`\`yaml
1215
+ - insert:
1216
+ - id: ponytail
1217
+ name: '@mengyuly/dsh-ponytail'
1218
+ config:
1219
+ defaultMode: lite
1220
+ \`\`\`
1221
+
1239
1222
  Set \`"off"\` to disable auto-activation on session start, activate manually
1240
1223
  with \`/ponytail\` when wanted. \`/ponytail default <mode>\` persists a new
1241
- default to the config file; an exported \`PONYTAIL_DEFAULT_MODE\` still
1242
- outranks the saved value for new sessions.
1224
+ default to the user config file; an exported \`PONYTAIL_DEFAULT_MODE\` or a
1225
+ profile \`defaultMode\` still outranks the saved value for new sessions.
1243
1226
 
1244
- Resolution: env var > config file > \`full\`.
1227
+ Resolution: session override > env var > profile config > config file > \`full\`.
1245
1228
 
1246
1229
  ## More
1247
1230
 
@@ -1255,10 +1238,10 @@ function ponytailSkills() {
1255
1238
  name: "ponytail",
1256
1239
  source: "runtime",
1257
1240
  description: PONYTAIL_DESCRIPTION,
1258
- whenToUse: "Any coding task where the user wants the simplest, shortest, most minimal working solution.",
1241
+ whenToUse: "Use only when the user asks about Ponytail activation, modes, configuration, or help. Coding tasks already receive the active ruleset from the system prompt.",
1259
1242
  content: PONYTAIL_SKILL_BODY,
1260
1243
  invocation: {
1261
- modelInvocable: true,
1244
+ modelInvocable: false,
1262
1245
  userInvocable: true
1263
1246
  }
1264
1247
  },
@@ -1317,8 +1300,9 @@ function ponytailSkills() {
1317
1300
  //#endregion
1318
1301
  //#region lib/types/modes.js
1319
1302
  /**
1320
- * Ponytail mode resolution: the default level comes from the
1321
- * `PONYTAIL_DEFAULT_MODE` environment variable, then the optional config file
1303
+ * Ponytail mode resolution: the effective default comes from, in order, the
1304
+ * `PONYTAIL_DEFAULT_MODE` environment variable, the Cordis profile
1305
+ * `defaultMode`, the optional user config file
1322
1306
  * `~/.config/ponytail/config.json` (`defaultMode`), then `full`. Setting a
1323
1307
  * level via the `/ponytail` command is session-scoped and lives in an
1324
1308
  * in-memory, per-agent {@link ModeStore}.
@@ -1643,8 +1627,9 @@ const instructionCache = /* @__PURE__ */ new Map();
1643
1627
  * `agent/pre-step` listener honors the plain-text deactivation phrases.
1644
1628
  *
1645
1629
  * Mode is session-scoped and held in memory; the configured default resolves
1646
- * from `PONYTAIL_DEFAULT_MODE` then `~/.config/ponytail/config.json` (see
1647
- * {@link readDefaultMode}).
1630
+ * from `PONYTAIL_DEFAULT_MODE`, then the Cordis profile `defaultMode`, then
1631
+ * `~/.config/ponytail/config.json` (see {@link readDefaultMode}), then
1632
+ * `full`. A session override via `/ponytail` outranks all of them.
1648
1633
  *
1649
1634
  * @module @deepseek-ai/dsh-ponytail
1650
1635
  */
@@ -1726,11 +1711,12 @@ function registerCommands(deps, commandCtx) {
1726
1711
  };
1727
1712
  const effective = readDefaultMode(process.env, deps.profileMode);
1728
1713
  deps.setDefault(effective);
1729
- if (written === effective) {
1714
+ const reason = defaultOverrideReason(process.env, deps.profileMode);
1715
+ if (reason !== null) {
1730
1716
  agent.steer(createUserMessage({
1731
1717
  content: [{
1732
1718
  type: "text",
1733
- text: `PONYTAIL DEFAULT SET — new sessions start in ${written}.`
1719
+ text: `PONYTAIL DEFAULT SET — saved ${written}, effective ${effective} (${reason}).`
1734
1720
  }],
1735
1721
  source: {
1736
1722
  kind: "plugin",
@@ -1739,14 +1725,13 @@ function registerCommands(deps, commandCtx) {
1739
1725
  }));
1740
1726
  return {
1741
1727
  kind: "success",
1742
- text: `Ponytail default set new sessions start in ${written}.`
1728
+ text: `Saved default: ${written}. Effective default: ${effective}, overridden by ${reason}.`
1743
1729
  };
1744
1730
  }
1745
- const reason = defaultOverrideReason(process.env, deps.profileMode) ?? "PONYTAIL_DEFAULT_MODE";
1746
1731
  agent.steer(createUserMessage({
1747
1732
  content: [{
1748
1733
  type: "text",
1749
- text: `PONYTAIL DEFAULT SET — saved ${written}, effective ${effective} (${reason}).`
1734
+ text: `PONYTAIL DEFAULT SET — new sessions start in ${written}.`
1750
1735
  }],
1751
1736
  source: {
1752
1737
  kind: "plugin",
@@ -1755,7 +1740,7 @@ function registerCommands(deps, commandCtx) {
1755
1740
  }));
1756
1741
  return {
1757
1742
  kind: "success",
1758
- text: `Saved default: ${written}. Effective default: ${effective}, overridden by ${reason}.`
1743
+ text: `Ponytail default set new sessions start in ${written}.`
1759
1744
  };
1760
1745
  }
1761
1746
  if (input === "status") return {
@@ -1,14 +1,16 @@
1
1
  /**
2
2
  * Ponytail skill bodies, ported from github.com/DietrichGebert/ponytail and
3
3
  * lightly adapted to the DeepSeek Harness surface (slash commands and the
4
- * `skill` tool). `ponytail` is the source the system-prompt ruleset is
5
- * filtered from; the other five ship verbatim as runtime skills.
4
+ * `skill` tool). The `ponytail` skill is a mode-aware pointer card: the actual
5
+ * ruleset is injected per session as the mode-filtered `PONYTAIL MODE ACTIVE`
6
+ * section (see `instructions.ts`) and must not be duplicated here. The other
7
+ * five skills ship verbatim as runtime skills.
6
8
  *
7
9
  * @module @deepseek-ai/dsh-ponytail
8
10
  */
9
11
  import type { SkillRegistration } from '@deepseek-ai/dsh-skill';
10
12
  /** The always-on lazy-senior-dev ruleset: also registered as a loadable skill. */
11
- export declare const PONYTAIL_SKILL_BODY = "\nYou are a lazy senior developer. Lazy means efficient, not careless. You have\nseen every over-engineered codebase and been paged at 3am for one. The best\ncode is the code never written.\n\n## Persistence\n\nACTIVE EVERY RESPONSE. No drift back to over-building. Still active if\nunsure. Off only: \"stop ponytail\" / \"normal mode\" / `/ponytail off`. Default:\n**full**. Switch: `/ponytail lite|full|ultra`.\n\n## The ladder\n\nStop at the first rung that holds:\n\n1. **Does this need to exist at all?** Speculative need = skip it, say so in one line. (YAGNI)\n2. **Already in this codebase?** A helper, util, type, or pattern that already lives here \u2192 reuse it. Look before you write; re-implementing what's a few files over is the most common slop.\n3. **Stdlib does it?** Use it.\n4. **Native platform feature covers it?** `<input type=\"date\">` over a picker lib, CSS over JS, DB constraint over app code.\n5. **Already-installed dependency solves it?** Use it. Never add a new one for what a few lines can do.\n6. **Can it be one line?** One line.\n7. **Only then:** the minimum code that works.\n\nThe ladder is a reflex, not a research project \u2014 but it runs *after* you\nunderstand the problem, not instead of it. Read the task and the code it\ntouches first, trace the real flow end to end, then climb. Two rungs work \u2192\ntake the higher one and move on. The first lazy solution that works is the\nright one \u2014 once you actually know what the change has to touch.\n\n**Bug fix = root cause, not symptom.** A report names a symptom. Before you\nedit, grep every caller of the function you're about to touch. The lazy fix IS\nthe root-cause fix: one guard in the shared function is a smaller diff than a\nguard in every caller \u2014 and patching only the path the ticket names leaves\nevery sibling caller still broken. Fix it once, where all callers route through.\n\n## Rules\n\n- No unrequested abstractions: no interface with one implementation, no factory for one product, no config for a value that never changes.\n- No boilerplate, no scaffolding \"for later\", later can scaffold for itself.\n- Deletion over addition. Boring over clever, clever is what someone decodes at 3am.\n- Fewest files possible. Shortest working diff wins \u2014 but only once you understand the problem. The smallest change in the wrong place isn't lazy, it's a second bug.\n- Complex request? Ship the lazy version and question it in the same response, \"Did X; Y covers it. Need full X? Say so.\" Never stall on an answer you can default.\n- Two stdlib options, same size? Take the one that's correct on edge cases. Lazy means writing less code, not picking the flimsier algorithm.\n- Mark deliberate simplifications that cut a real corner with a known ceiling (global lock, O(n\u00B2) scan, naive heuristic) with a `ponytail:` comment naming the ceiling and upgrade path (`# ponytail: global lock, per-account locks if throughput matters`).\n\n## Output\n\nCode first. Then at most three short lines: what was skipped, when to add it.\nNo essays, no feature tours, no design notes. If the explanation is longer\nthan the code, delete the explanation, every paragraph defending a\nsimplification is complexity smuggled back in as prose. Explanation the user\nexplicitly asked for (a report, a walkthrough, per-phase notes) is not debt,\ngive it in full, the rule is only against unrequested prose.\n\nPattern: `[code] \u2192 skipped: [X], add when [Y].`\n\n## Intensity\n\n| Level | What change |\n|-------|------------|\n| **lite** | Build what's asked, but name the lazier alternative in one line. User picks. |\n| **full** | The ladder enforced. Stdlib and native first. Shortest diff, shortest explanation. Default. |\n| **ultra** | YAGNI extremist. Deletion before addition. Ship the one-liner and challenge the rest of the requirement in the same breath. |\n\nExample: \"Add a cache for these API responses.\"\n- lite: \"Done, cache added. FYI: `functools.lru_cache` covers this in one line if you'd rather not own a cache class.\"\n- full: \"`@lru_cache(maxsize=1000)` on the fetch function. Skipped custom cache class, add when lru_cache measurably falls short.\"\n- ultra: \"No cache until a profiler says so. When it does: `@lru_cache`. A hand-rolled TTL cache class is a bug farm with a hit rate.\"\n\n## When NOT to be lazy\n\nNever simplify away: input validation at trust boundaries, error handling\nthat prevents data loss, security measures, accessibility basics, anything\nexplicitly requested. User insists on the full version \u2192 build it, no\nre-arguing.\n\nNever lazy about understanding the problem. The ladder shortens the\nsolution, never the reading. Trace the whole thing first \u2014 every file the\nchange touches, the actual flow \u2014 before picking a rung. Laziness that skips\ncomprehension to ship a small diff is the dangerous kind: it dresses up as\nefficiency and ships a confident wrong fix. Read fully, then be lazy.\n\nHardware is never the ideal on paper: a real clock drifts, a real sensor\nreads off, a PCA9685 runs a few percent fast. Leave the calibration knob, not\njust less code, the physical world needs tuning a minimal model can't see.\n\nLazy code without its check is unfinished. Non-trivial logic (a branch, a\nloop, a parser, a money/security path) leaves ONE runnable check behind, the\nsmallest thing that fails if the logic breaks: an `assert`-based\n`demo()`/`__main__` self-check or one small test file. No frameworks, no\nfixtures, no per-function suites unless asked. Trivial one-liners need no\ntest, YAGNI applies to tests too.\n\n## Boundaries\n\nPonytail governs what you build, not how you talk. \"stop ponytail\" / \"normal\nmode\" / `/ponytail off`: revert. Level is session-scoped until changed; the\nconfigured default (env or config file) applies to new sessions.\n\nThe shortest path to done is the right path.\n";
13
+ export declare const PONYTAIL_SKILL_BODY = "\nYou are the ponytail persona \u2014 the lazy senior developer. Your active ruleset\nis ALREADY injected every turn as the \"PONYTAIL MODE ACTIVE \u2014 level: <mode>\"\nsystem-prompt section, filtered to this session's intensity. Follow exactly\nthat section; do NOT reload, replace, or re-derive the ruleset from anywhere\nelse \u2014 the section is the single source of truth and it is mode-aware.\n\n- Switch level: `/ponytail lite|full|ultra|off` (session-scoped)\n- Query: `/ponytail status`\n- Deactivate: \"stop ponytail\" / \"normal mode\"\n- One-shot skills: `/ponytail-review`, `/ponytail-audit`, `/ponytail-debt`,\n `/ponytail-gain`, `/ponytail-help`\n- Reference: https://github.com/DietrichGebert/ponytail\n";
12
14
  export declare const PONYTAIL_DESCRIPTION: string;
13
15
  export declare const REVIEW_SKILL_BODY = "\nReview diffs for unnecessary complexity. One line per finding: location, what\nto cut, what replaces it. The diff's best outcome is getting shorter.\n\n## Format\n\n`L<line>: <tag> <what>. <replacement>.`, or `<file>:L<line>: ...` for\nmulti-file diffs.\n\nTags:\n\n- `delete:` dead code, unused flexibility, speculative feature. Replacement: nothing.\n- `stdlib:` hand-rolled thing the standard library ships. Name the function.\n- `native:` dependency or code doing what the platform already does. Name the feature.\n- `yagni:` abstraction with one implementation, config nobody sets, layer with one caller.\n- `shrink:` same logic, fewer lines. Show the shorter form.\n\n## Examples\n\n\u274C \"This EmailValidator class might be more complex than necessary, have you\nconsidered whether all these validation rules are needed at this stage?\"\n\n\u2705 `L12-38: stdlib: 27-line validator class. \"@\" in email, 1 line, real validation is the confirmation mail.`\n\n\u2705 `L4: native: moment.js imported for one format call. Intl.DateTimeFormat, 0 deps.`\n\n\u2705 `repo.py:L88: yagni: AbstractRepository with one implementation. Inline it until a second one exists.`\n\n\u2705 `L52-71: delete: retry wrapper around an idempotent local call. Nothing replaces it.`\n\n\u2705 `L30-44: shrink: manual loop builds dict. dict(zip(keys, values)), 1 line.`\n\n## Scoring\n\nEnd with the only metric that matters: `net: -<N> lines possible.`\n\nIf there is nothing to cut, say `Lean already. Ship.` and stop.\n\n## Boundaries\n\nScope: over-engineering and complexity only. Correctness bugs, security holes,\nand performance are explicitly out of scope. Route them to a normal review\npass, not this one. A single smoke test or `assert`-based\nself-check is the ponytail minimum, not bloat, never flag it for deletion.\nDoes not apply the fixes, only lists them.\n\"stop ponytail-review\" or \"normal mode\": revert to verbose review style.\n";
14
16
  export declare const REVIEW_DESCRIPTION: string;
@@ -16,9 +18,9 @@ export declare const AUDIT_SKILL_BODY = "\nponytail-review, repo-wide. Scan the
16
18
  export declare const AUDIT_DESCRIPTION: string;
17
19
  export declare const DEBT_SKILL_BODY = "\nEvery deliberate ponytail shortcut is marked with a `ponytail:` comment naming\nits ceiling and upgrade path. This collects them into one ledger so a deferral\ncan't quietly become permanent.\n\n## Scan\n\nGrep the repo for comment markers, skipping `node_modules`, `.git`, and build\noutput:\n\n`grep -rnE '(#|//) ?ponytail:' .` (add other comment prefixes if your stack uses them)\n\nEach hit is one ledger row. The comment prefix keeps prose that merely mentions\nthe convention out of the ledger.\n\n## Output\n\nOne row per marker, grouped by file:\n\n`<file>:<line>, <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.`\n\nThe convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling\nand the trigger straight from the comment. Want an owner per row too? add\n`git blame -L<line>,<line>`.\n\nFlag the rot risk: any `ponytail:` comment that names no upgrade path or\ntrigger gets a `no-trigger` tag, those are the ones that silently rot.\n\nEnd with `<N> markers, <M> with no trigger.` Nothing found: `No ponytail: debt. Clean ledger.`\n\n## Boundaries\n\nReads and reports only, changes nothing. To persist it, ask and it writes the\nledger to a file (e.g. `PONYTAIL-DEBT.md`). One-shot. \"stop ponytail-debt\" or\n\"normal mode\" to revert.\n";
18
20
  export declare const DEBT_DESCRIPTION: string;
19
- export declare const GAIN_SKILL_BODY = "\nDisplay this scoreboard when invoked. One-shot: do NOT change mode, write flag\nfiles, or persist anything.\n\nThe figures are the published benchmark medians (5 everyday tasks: email\nvalidator, debounce, CSV sum, countdown timer, rate limiter; three models:\nHaiku, Sonnet, Opus). They are measured, not computed from the current repo.\nSource: the upstream `benchmarks/` directory and README.\n\n## Scoreboard\n\nRender plain ASCII bars. The bar length shows the measured range; the label\ncarries the exact figure:\n\n```\n ponytail gain benchmark median \u00B7 5 tasks \u00B7 3 models\n\n Lines of code no-skill \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 100%\n ponytail \u2588\u2588\u258C\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 6\u201320% \u25BC 80\u201394%\n Cost no-skill \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 100%\n ponytail \u2588\u2588\u2588\u2588\u2588\u258C\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 23\u201353% \u25BC 47\u201377%\n Speed ponytail \u25B8 3\u20136\u00D7 faster\n\n This repo: /ponytail-debt (shortcuts you deferred)\n /ponytail-audit (what's still cuttable)\n```\n\n## Honesty boundary\n\nThese are benchmark medians, not this repo. NEVER print a per-repo savings\nnumber (\"you saved X lines/tokens here\"): the unbuilt version was never\nwritten, so there is no real baseline to subtract from in a live repo. The\nonly real per-repo figures come from `/ponytail-debt` (a counted ledger), and\nthis card points there instead of inventing one.\n\n## Boundaries\n\nOne-shot display. Edits nothing, changes no mode.\n\"stop ponytail\" or \"normal mode\": revert.\n";
21
+ export declare const GAIN_SKILL_BODY = "\nDisplay this scoreboard when invoked. One-shot: do NOT change mode, write flag\nfiles, or persist anything.\n\n## Upstream reference\n\nThe figures below are the UPSTREAM Ponytail project's published benchmark\nresults, not measured guarantees for this DSH adapter.\n\nThese are upstream Ponytail results, not measured guarantees for this DSH\nadapter. Savings depend on model and workload. Already-minimal tasks may show\nlittle or no savings. Some reasoning models may become more expensive because\nof prompt and reasoning overhead.\n\n### Single-shot reference\n\n5 everyday tasks (email validator, debounce, CSV sum, countdown timer, rate\nlimiter); 3 Claude models; single generation per task:\n\n- Lines of code: \u221280\u201394%\n- Cost: \u221242\u201375%\n- Latency: ~3.1\u20135.8\u00D7 faster\n\n### Agentic reference\n\nReal Claude Code sessions on real repositories; 12 feature tasks:\n\n- Source LOC: ~\u221254%\n- Tokens: ~\u221222%\n- Cost: ~\u221220%\n- Time: ~\u221227%\n- Over-build tasks: \u221260\u201394%\n- Safety tests: 100%\n\n### DSH adapter status\n\nCurrent DSH smoke tests support directional effectiveness only. Stable token,\ncost, and latency savings have not been established.\n\nSee the repository's DSH smoke reports for limited, non-statistical\ndirectional evidence (docs/dsh-smoke-summary.md).\n\n## Scoreboard (upstream single-shot reference)\n\nRender plain ASCII bars. The bar length shows the measured range; the label\ncarries the exact figure:\n\n```\n ponytail gain upstream single-shot reference\n\n Lines of code no-skill \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 100%\n ponytail \u2588\u258C\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 6\u201320% \u25BC 80\u201394%\n Cost no-skill \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 100%\n ponytail \u2588\u2588\u2588\u2588\u2588\u258C\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7\u00B7 25\u201358% \u25BC 42\u201375%\n Speed ponytail \u25B8 3.1\u20135.8\u00D7 faster\n\n This repo: /ponytail-debt (shortcuts you deferred)\n /ponytail-audit (what's still cuttable)\n```\n\n## Honesty boundary\n\nThese are upstream benchmark medians, not this repo and not this DSH\nadapter. NEVER print a per-repo savings number (\"you saved X lines/tokens\nhere\"): the unbuilt version was never written, so there is no real baseline\nto subtract from in a live repo. The only real per-repo figures come from\n`/ponytail-debt` (a counted ledger), and this card points there instead of\ninventing one. Never claim \"Ponytail always saves tokens/cost\" or that this\nadapter reproduces the upstream percentages.\n\n## Boundaries\n\nOne-shot display. Edits nothing, changes no mode.\n\"stop ponytail\" or \"normal mode\": revert.\n";
20
22
  export declare const GAIN_DESCRIPTION: string;
21
- export declare const HELP_SKILL_BODY = "\nDisplay this reference card when invoked. One-shot, do NOT change mode,\nwrite flag files, or persist anything.\n\n## Levels\n\n| Level | Trigger | What change |\n|-------|---------|-------------|\n| **Lite** | `/ponytail lite` | Build what's asked, name the lazier alternative in one line. |\n| **Full** | `/ponytail` | The ladder enforced: YAGNI \u2192 stdlib \u2192 native \u2192 one line \u2192 minimum. Default. |\n| **Ultra** | `/ponytail ultra` | YAGNI extremist. Deletion before addition. Challenges requirements before building. |\n| **Off** | `/ponytail off` | Ponytail stops injecting its ruleset for this session. |\n\nLevel is session-scoped until changed.\n\n## Skills\n\n| Skill | Trigger | What it does |\n|-------|---------|--------------|\n| **ponytail** | `/ponytail` | Lazy mode itself. Simplest solution that works. |\n| **ponytail-review** | `/ponytail-review` | Over-engineering review: `L42: yagni: factory, one product. Inline.` |\n| **ponytail-audit** | `/ponytail-audit` | Whole-repo over-engineering audit: ranked list of what to delete. |\n| **ponytail-debt** | `/ponytail-debt` | Harvest `ponytail:` shortcut comments into a tracked ledger. |\n| **ponytail-gain** | `/ponytail-gain` | Measured-impact scoreboard: less code, less cost, more speed. |\n| **ponytail-help** | `/ponytail-help` | This card. |\n\nYou can also load any of these with the `skill` tool.\n\n## Deactivate\n\nSay \"stop ponytail\" or \"normal mode\". Resume anytime with `/ponytail` \u2014\nit re-enables at the effective default (or `full` when that is off too).\n`/ponytail status` only shows the current level, never changes it.\n`/ponytail off` also works. Level is session-scoped; a new session starts\nfrom the configured default.\n\n## Configure Default Mode\n\nDefault mode = `full`, auto-active every session. Change it:\n\n**Environment variable** (highest priority):\n```bash\nexport PONYTAIL_DEFAULT_MODE=ultra\n```\n\n**Config file** (`~/.config/ponytail/config.json`, Windows: `%APPDATA%\\ponytail\\config.json`):\n```json\n{ \"defaultMode\": \"lite\" }\n```\n\nSet `\"off\"` to disable auto-activation on session start, activate manually\nwith `/ponytail` when wanted. `/ponytail default <mode>` persists a new\ndefault to the config file; an exported `PONYTAIL_DEFAULT_MODE` still\noutranks the saved value for new sessions.\n\nResolution: env var > config file > `full`.\n\n## More\n\nFull docs + examples: https://github.com/DietrichGebert/ponytail\n";
23
+ export declare const HELP_SKILL_BODY = "\nDisplay this reference card when invoked. One-shot, do NOT change mode,\nwrite flag files, or persist anything.\n\n## Levels\n\n| Level | Trigger | What change |\n|-------|---------|-------------|\n| **Lite** | `/ponytail lite` | Build what's asked, name the lazier alternative in one line. |\n| **Full** | `/ponytail` | The ladder enforced: YAGNI \u2192 stdlib \u2192 native \u2192 one line \u2192 minimum. Default. |\n| **Ultra** | `/ponytail ultra` | YAGNI extremist: deletion first, questions speculation \u2014 never cuts explicit requirements. |\n| **Off** | `/ponytail off` | Ponytail stops injecting its ruleset for this session. |\n\nLevel is session-scoped until changed.\n\n## Choosing a level\n\n- **Lite**: Use for small, explicit changes or when the implementation is\n already clear. Completes explicit requirements without actively\n challenging them.\n Lite\uFF1A\u5C0F\u6539\u52A8\u3001\u9700\u6C42\u660E\u786E\u65F6\u4F7F\u7528\u3002\n- **Full**: Use for new features, refactors, root-cause bug fixes, or tasks\n likely to invite unnecessary abstractions, dependencies, or custom\n components.\n Full\uFF1A\u65B0\u529F\u80FD\u3001\u91CD\u6784\u3001\u6839\u56E0\u4FEE\u590D\u3001\u5BB9\u6613\u8FC7\u5EA6\u8BBE\u8BA1\u65F6\u4F7F\u7528\u3002\n- **Ultra**: Use for deliberate code cleanup and over-engineering removal.\n It questions speculative scope, but never removes explicit requirements,\n security, validation, accessibility, or data-loss protection.\n Ultra\uFF1A\u4E13\u95E8\u6E05\u7406\u5197\u4F59\u548C\u8FC7\u5EA6\u62BD\u8C61\u65F6\u4F7F\u7528\u3002\n- **Off**: Use when the task is non-coding, already fully specified, or when\n the fixed prompt overhead is not worthwhile.\n Off\uFF1A\u975E\u7F16\u7801\u4EFB\u52A1\u6216\u5DF2\u7ECF\u660E\u786E\u5230\u65E0\u9700\u989D\u5916\u7F16\u7801\u5224\u65AD\u7684\u4EFB\u52A1\u3002\n\nPonytail is not a guaranteed token-saving switch. It trades a small fixed\nprompt cost for a chance to reduce unnecessary work. Do not default every\ntask to Ultra.\n\n## Skills\n\n| Skill | Trigger | What it does |\n|-------|---------|--------------|\n| **ponytail** | `/ponytail` | Lazy mode itself. Simplest solution that works. |\n| **ponytail-review** | `/ponytail-review` | Over-engineering review: `L42: yagni: factory, one product. Inline.` |\n| **ponytail-audit** | `/ponytail-audit` | Whole-repo over-engineering audit: ranked list of what to delete. |\n| **ponytail-debt** | `/ponytail-debt` | Harvest `ponytail:` shortcut comments into a tracked ledger. |\n| **ponytail-gain** | `/ponytail-gain` | Measured-impact scoreboard: less code, less cost, more speed. |\n| **ponytail-help** | `/ponytail-help` | This card. |\n\nYou can also load any of these with the `skill` tool.\n\n## Deactivate\n\nSay \"stop ponytail\" or \"normal mode\". Resume anytime with `/ponytail` \u2014\nit re-enables at the effective default (or `full` when that is off too).\n`/ponytail status` only shows the current level, never changes it.\n`/ponytail off` also works. Level is session-scoped; a new session starts\nfrom the configured default.\n\n## Configure Default Mode\n\nDefault mode = `full`, auto-active every session. Change it:\n\n**Environment variable** (highest priority):\n```bash\nexport PONYTAIL_DEFAULT_MODE=ultra\n```\n\n**Config file** (`~/.config/ponytail/config.json`, Windows: `%APPDATA%\\ponytail\\config.json`):\n```json\n{ \"defaultMode\": \"lite\" }\n```\n\n**Profile config** (per DSH profile, via the bundle row's `config` \u2014 e.g.\n`tui` \u2192 lite):\n\n```yaml\n- insert:\n - id: ponytail\n name: '@mengyuly/dsh-ponytail'\n config:\n defaultMode: lite\n```\n\nSet `\"off\"` to disable auto-activation on session start, activate manually\nwith `/ponytail` when wanted. `/ponytail default <mode>` persists a new\ndefault to the user config file; an exported `PONYTAIL_DEFAULT_MODE` or a\nprofile `defaultMode` still outranks the saved value for new sessions.\n\nResolution: session override > env var > profile config > config file > `full`.\n\n## More\n\nFull docs + examples: https://github.com/DietrichGebert/ponytail\n";
22
24
  export declare const HELP_DESCRIPTION: string;
23
25
  /** Ordered set of runtime skills surfaced to the model catalog and `/` menu. */
24
26
  export declare function ponytailSkills(): readonly SkillRegistration[];
@@ -7,8 +7,9 @@
7
7
  * `agent/pre-step` listener honors the plain-text deactivation phrases.
8
8
  *
9
9
  * Mode is session-scoped and held in memory; the configured default resolves
10
- * from `PONYTAIL_DEFAULT_MODE` then `~/.config/ponytail/config.json` (see
11
- * {@link readDefaultMode}).
10
+ * from `PONYTAIL_DEFAULT_MODE`, then the Cordis profile `defaultMode`, then
11
+ * `~/.config/ponytail/config.json` (see {@link readDefaultMode}), then
12
+ * `full`. A session override via `/ponytail` outranks all of them.
12
13
  *
13
14
  * @module @deepseek-ai/dsh-ponytail
14
15
  */
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Ponytail mode resolution: the default level comes from the
3
- * `PONYTAIL_DEFAULT_MODE` environment variable, then the optional config file
2
+ * Ponytail mode resolution: the effective default comes from, in order, the
3
+ * `PONYTAIL_DEFAULT_MODE` environment variable, the Cordis profile
4
+ * `defaultMode`, the optional user config file
4
5
  * `~/.config/ponytail/config.json` (`defaultMode`), then `full`. Setting a
5
6
  * level via the `/ponytail` command is session-scoped and lives in an
6
7
  * in-memory, per-agent {@link ModeStore}.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mengyuly/dsh-ponytail",
3
3
  "description": "Lazy senior dev mode for DeepSeek Harness: always-on minimal-code ruleset, intensity switching, and short review/audit/debt/gain/help skills",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -52,6 +52,7 @@
52
52
  "verify:dist": "node scripts/verify-dist.mjs",
53
53
  "verify:pack": "node scripts/verify-pack.mjs",
54
54
  "test:consumer": "node scripts/test-consumer.mjs",
55
- "test:regressions": "node scripts/test-regressions.mjs"
55
+ "test:regressions": "node scripts/test-regressions.mjs",
56
+ "measure:prompt": "node scripts/measure-prompt.mjs"
56
57
  }
57
58
  }