@mengyuly/dsh-ponytail 0.3.3 → 0.3.4
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 +13 -0
- package/README.md +20 -17
- package/README_EN.md +311 -0
- package/cordis.patch.yml +1 -1
- package/lib/index.js +7 -7
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,19 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## [0.3.4] - 2026-10-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- English README and bilingual navigation (PR #1), included in the npm package.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- Mode/default status notices now use non-waking injection instead of steering
|
|
17
|
+
an idle agent into an extra model turn (issue #2). Mode changes apply
|
|
18
|
+
immediately; notices reach the model on its next real step. Explicit
|
|
19
|
+
review/audit/debt/gain/help invocations still request an ordinary turn.
|
|
20
|
+
|
|
8
21
|
## [0.3.3] - 2026-09-09
|
|
9
22
|
|
|
10
23
|
### Changed
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# dsh-ponytail
|
|
2
2
|
|
|
3
|
+
[English](README_EN.md) | 简体中文
|
|
4
|
+
|
|
3
5
|

|
|
4
6
|

|
|
5
7
|
[](https://www.npmjs.com/package/@mengyuly/dsh-ponytail)
|
|
@@ -13,15 +15,15 @@
|
|
|
13
15
|
|
|
14
16
|
- **最新版(latest)**:
|
|
15
17
|
`https://github.com/MengYuil/dsh-ponytail/releases/latest/download/mengyuly-dsh-ponytail.tgz`
|
|
16
|
-
- **固定版本 v0.3.
|
|
17
|
-
`https://github.com/MengYuil/dsh-ponytail/releases/download/v0.3.
|
|
18
|
+
- **固定版本 v0.3.4**(按 Tag 不可变):
|
|
19
|
+
`https://github.com/MengYuil/dsh-ponytail/releases/download/v0.3.4/mengyuly-dsh-ponytail.tgz`
|
|
18
20
|
|
|
19
21
|
说明:
|
|
20
22
|
|
|
21
23
|
- **latest**:适合快速安装体验,会随最新 Release 更新;固定资产名
|
|
22
24
|
`mengyuly-dsh-ponytail.tgz` 在每个 Release 中保持不变,因此该 URL
|
|
23
25
|
不会因版本号变化而失效,**不适合作为不可变依赖**。
|
|
24
|
-
- **固定版本**:适合可复现安装,URL 中固定 Tag(如 `v0.3.
|
|
26
|
+
- **固定版本**:适合可复现安装,URL 中固定 Tag(如 `v0.3.4`),按 Tag
|
|
25
27
|
不可变;资产名同样为 `mengyuly-dsh-ponytail.tgz`。
|
|
26
28
|
- npm 安装仍走 npm Registry 或 `dsh plugin` 命令。
|
|
27
29
|
- 固定资产名由 `scripts/release-assets.mjs` 生成并验证(`node scripts/release-assets.mjs`,仅仓库维护者)。
|
|
@@ -54,25 +56,26 @@ dsh plugin --profile web add @mengyuly/dsh-ponytail
|
|
|
54
56
|
## 功能
|
|
55
57
|
|
|
56
58
|
- **核心模式** `/ponytail` — 每轮注入结构化的懒惰开发者规则集,**三个档位是真实不同的 Prompt 片段**(不只是换一行):
|
|
57
|
-
- **Common(所有非 off 档共享)**:先把请求转成可观察的完成条件;沿真实调用流取证,但决策阶梯是快速反射、不是研究项目;按“检查 → 修改 → 最窄有效验证 → 检查最终 diff”闭环执行;非平凡逻辑只留一个最小可执行检查,不额外搭测试框架或 fixtures;只汇报已验证结果。
|
|
59
|
+
- **Common(所有非 off 档共享)**:先把请求转成可观察的完成条件;沿真实调用流取证,但决策阶梯是快速反射、不是研究项目;按“检查 → 修改 → 最窄有效验证 → 检查最终 diff”闭环执行;非平凡逻辑只留一个最小可执行检查,不额外搭测试框架或 fixtures;只汇报已验证结果。
|
|
58
60
|
- **Safety(任何档位都不可删)**:输入校验、防数据丢失的错误处理、安全措施、无障碍、明确验收项、先理解问题、「最小 diff ≠ 正确修复」。
|
|
59
|
-
- **`lite`**:直接执行、减少仪式;完整交付明确要求;可以一句话指出更简方案,但**不挑战明确需求**。
|
|
61
|
+
- **`lite`**:直接执行、减少仪式;完整交付明确要求;可以一句话指出更简方案,但**不挑战明确需求**。
|
|
60
62
|
- **`full`(默认)**:完整七级阶梯(YAGNI → 复用 → 标准库 → 原生 → 已装依赖 → 一行 → 最小实现),默认选最短正确实现,修根因而非症状。
|
|
61
|
-
- **`ultra`**:新增代码前先要证据,优先删除或复用;主动质疑投机性功能/缓存/抽象/配置/新依赖;复杂需求先给最小正确版并说明扩大条件;**不是无脑拒绝**。
|
|
63
|
+
- **`ultra`**:新增代码前先要证据,优先删除或复用;主动质疑投机性功能/缓存/抽象/配置/新依赖;复杂需求先给最小正确版并说明扩大条件;**不是无脑拒绝**。
|
|
62
64
|
- `off`:完全不注入。
|
|
63
65
|
- 档位**会话级**(会话 A 不影响会话 B,会话结束自动释放)。
|
|
64
66
|
- 裸 `/ponytail`:已启用时只报告;`off` 时恢复到有效默认档(默认也是 `off` 则回 `full`)。
|
|
65
|
-
- `/ponytail status`:只查询、永不修改,并显示当前模式来自会话覆盖还是配置默认值。
|
|
66
|
-
- `/ponytail reset`:清除当前会话覆盖,重新跟随有效配置默认值。
|
|
67
|
+
- `/ponytail status`:只查询、永不修改,并显示当前模式来自会话覆盖还是配置默认值。
|
|
68
|
+
- `/ponytail reset`:清除当前会话覆盖,重新跟随有效配置默认值。
|
|
67
69
|
- `/ponytail lite|full|ultra|off`:显式切换。
|
|
68
70
|
- `/ponytail default <mode>`:持久化默认值到**用户级配置文件**(env/Profile 仍优先,命令分别提示 saved 与 effective)。
|
|
71
|
+
- 状态操作立即生效,但不唤醒空闲 Agent;模型通知在下一次真实请求时接收,避免切档位额外触发模型调用。
|
|
69
72
|
- **一次性技能**(用哪个载哪个,不进常驻 prompt):
|
|
70
|
-
- `/ponytail-review` — 针对最近改动找过度工程;每条包含位置、替代方案和实际调用证据,不猜测精确收益。
|
|
71
|
-
- `/ponytail-audit` — 全仓库过度工程审计;区分可安全删除与需要先验证的候选,最多返回 10 条高价值发现。
|
|
73
|
+
- `/ponytail-review` — 针对最近改动找过度工程;每条包含位置、替代方案和实际调用证据,不猜测精确收益。
|
|
74
|
+
- `/ponytail-audit` — 全仓库过度工程审计;区分可安全删除与需要先验证的候选,最多返回 10 条高价值发现。
|
|
72
75
|
- `/ponytail-debt` — 收割所有 `ponytail:` 注释成债务账本。
|
|
73
76
|
- `/ponytail-gain` — 上游 Benchmark 参考计分板(代码减少;Token/成本/延迟效果取决于模型与任务,**非本适配版保证**)。
|
|
74
77
|
- `/ponytail-help` — 参考卡。
|
|
75
|
-
- **停用**:说 `stop ponytail`、`normal mode`、`停止 ponytail`、`关闭 ponytail`、`普通模式` 或 `正常模式`(兼容中英文句末标点);随时 `/ponytail` 恢复。
|
|
78
|
+
- **停用**:说 `stop ponytail`、`normal mode`、`停止 ponytail`、`关闭 ponytail`、`普通模式` 或 `正常模式`(兼容中英文句末标点);随时 `/ponytail` 恢复。
|
|
76
79
|
- **默认值优先级**(代码/测试/文档一致):
|
|
77
80
|
```
|
|
78
81
|
会话 override > PONYTAIL_DEFAULT_MODE > Profile config.defaultMode > 用户 config.json > full
|
|
@@ -104,9 +107,9 @@ prompt 与推理开销变得更贵。
|
|
|
104
107
|
|
|
105
108
|
| 档位 | 字符数 | UTF-8 字节 | 说明 |
|
|
106
109
|
|------|--------|-----------|------|
|
|
107
|
-
| lite | 1915 | 1917 | 实测生成 |
|
|
108
|
-
| full | 3022 | 3038 | 实测生成 |
|
|
109
|
-
| ultra | 2797 | 2813 | 实测生成 |
|
|
110
|
+
| lite | 1915 | 1917 | 实测生成 |
|
|
111
|
+
| full | 3022 | 3038 | 实测生成 |
|
|
112
|
+
| ultra | 2797 | 2813 | 实测生成 |
|
|
110
113
|
| off | 0 | 0 | 不注入 |
|
|
111
114
|
|
|
112
115
|
这些是 **Prompt 体积测量,不是账单金额,也不是对所有模型成立的节省
|
|
@@ -162,8 +165,8 @@ Smoke Benchmark 只提供方向性证据(见 `docs/dsh-smoke-summary.md`)。
|
|
|
162
165
|
node scripts/verify-dist.mjs # 静态一致性:src/d.ts 导出一致、关键签名、运行时导出、provenance
|
|
163
166
|
node scripts/verify-pack.mjs # tarball 边界(含无 scripts/ 暴露回归检查)、版本、安装后 smoke
|
|
164
167
|
node scripts/test-consumer.mjs # NodeNext + skipLibCheck:false 声明消费测试(对打包产物)
|
|
165
|
-
node scripts/test-regressions.mjs # 验证工具自身的回归测试
|
|
166
|
-
node scripts/test-core.mjs # 核心 Prompt 字节、安全边界、模式与 Skill 表面
|
|
168
|
+
node scripts/test-regressions.mjs # 验证工具自身的回归测试
|
|
169
|
+
node scripts/test-core.mjs # 核心 Prompt 字节、安全边界、模式与 Skill 表面
|
|
167
170
|
node scripts/measure-prompt.mjs # 各模式 Prompt 段体积(依赖未发布的 src/)
|
|
168
171
|
node scripts/check-release-links.mjs # README/CHANGELOG/docs 无版本化 latest 资产链接
|
|
169
172
|
node scripts/check-release-consistency.mjs --version <v> # 四方发布一致性(git tag/npm/GitHub/provenance)
|
|
@@ -180,4 +183,4 @@ Smoke Benchmark 只提供方向性证据(见 `docs/dsh-smoke-summary.md`)。
|
|
|
180
183
|
|
|
181
184
|
## 许可
|
|
182
185
|
|
|
183
|
-
MIT,© 2026 DietrichGebert(上游)+ MengYuil(移植)。详见 [LICENSE](LICENSE)。
|
|
186
|
+
MIT,© 2026 DietrichGebert(上游)+ MengYuil(移植)。详见 [LICENSE](LICENSE)。
|
package/README_EN.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# dsh-ponytail
|
|
2
|
+
|
|
3
|
+
English | [简体中文](README.md)
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
[](https://www.npmjs.com/package/@mengyuly/dsh-ponytail)
|
|
8
|
+
[](https://www.dsh.so/artifact/dsh-ponytail-4/)
|
|
9
|
+
|
|
10
|
+
Adapts the minimal-coding principles and skills of
|
|
11
|
+
[DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail) to
|
|
12
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): a YAGNI
|
|
13
|
+
decision ladder, session-level Lite / Full / Ultra / Off modes, and a set of
|
|
14
|
+
skills for code slimming, review, auditing, and technical-debt tracking.
|
|
15
|
+
|
|
16
|
+
This project aligns with the upstream core ideas and main workflows, but DSH's
|
|
17
|
+
model loop, prompt assembly, skill mechanism, and tool calls differ. **The
|
|
18
|
+
upstream benchmark is a reference only and does not imply that this port has
|
|
19
|
+
the same token, cost, or latency gains** (see “Efficiency (conditional gains,
|
|
20
|
+
not guarantees)”).
|
|
21
|
+
|
|
22
|
+
## Download from GitHub Releases
|
|
23
|
+
|
|
24
|
+
- **Latest release**:
|
|
25
|
+
`https://github.com/MengYuil/dsh-ponytail/releases/latest/download/mengyuly-dsh-ponytail.tgz`
|
|
26
|
+
- **Pinned version v0.3.4** (immutable per tag):
|
|
27
|
+
`https://github.com/MengYuil/dsh-ponytail/releases/download/v0.3.4/mengyuly-dsh-ponytail.tgz`
|
|
28
|
+
|
|
29
|
+
Notes:
|
|
30
|
+
|
|
31
|
+
- **latest**: good for a quick install; it tracks the newest release. The fixed
|
|
32
|
+
asset name `mengyuly-dsh-ponytail.tgz` stays the same in every release, so
|
|
33
|
+
the URL never breaks on a version bump — which also means it is **not
|
|
34
|
+
suitable as an immutable dependency**.
|
|
35
|
+
- **Pinned version**: good for reproducible installs; the URL pins a tag
|
|
36
|
+
(e.g. `v0.3.4`) that is immutable per tag; the asset name is likewise
|
|
37
|
+
`mengyuly-dsh-ponytail.tgz`.
|
|
38
|
+
- npm installs still go through the npm Registry or the `dsh plugin` command.
|
|
39
|
+
- The fixed asset name is produced and verified by
|
|
40
|
+
`scripts/release-assets.mjs` (`node scripts/release-assets.mjs`, maintainers
|
|
41
|
+
only).
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
Install into a profile (replace `web` with `tui` or a custom name):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Option 1: local link (current dsh cores >= 0.1.x)
|
|
49
|
+
dsh plugin --profile web add link:$(pwd)
|
|
50
|
+
|
|
51
|
+
# Option 2: install straight from GitHub
|
|
52
|
+
dsh plugin --profile web add github:MengYuil/dsh-ponytail
|
|
53
|
+
|
|
54
|
+
# Option 3: Release tarball (download the tgz first — the latest fixed asset
|
|
55
|
+
# name never changes)
|
|
56
|
+
# https://github.com/MengYuil/dsh-ponytail/releases/latest/download/mengyuly-dsh-ponytail.tgz
|
|
57
|
+
dsh plugin --profile web add file:./mengyuly-dsh-ponytail.tgz
|
|
58
|
+
|
|
59
|
+
# Option 4: npm
|
|
60
|
+
dsh plugin --profile web add @mengyuly/dsh-ponytail
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Restart the profile after installing (`dsh web` / `dsh tui`) for it to take
|
|
64
|
+
effect. Once loaded, the session skill catalog shows 6 `ponytail*` skills; send
|
|
65
|
+
`/ponytail-help` to verify immediately.
|
|
66
|
+
|
|
67
|
+
> `lib/index.js` is a self-contained bundle (`dsh-llm` / `dsh-skill` are
|
|
68
|
+
> already inlined — npm has no compatible versions) with two published
|
|
69
|
+
> runtime peers: `@deepseek-ai/cordis` (4.0.1) and
|
|
70
|
+
> `@deepseek-ai/schemastery` (3.18.x). `schemastery` is deliberately kept
|
|
71
|
+
> external rather than inlined: its schema DSL compiles `callback` strings
|
|
72
|
+
> with `new Function`, so keeping it out means **the shipped artifact contains
|
|
73
|
+
> no dynamic code execution** (CI has a dedicated check). None of the three
|
|
74
|
+
> install paths — GitHub, tgz, npm — needs a dsh source tree.
|
|
75
|
+
|
|
76
|
+
> Note: `src/` is the source, `lib/` is the prebuilt artifact (loadable
|
|
77
|
+
> out of the box, no build step). The authoritative source lives in the
|
|
78
|
+
> deepseek-harness monorepo at `packages/community/ponytail`; after changing
|
|
79
|
+
> source, rebuild and sync the full `lib/` with
|
|
80
|
+
> `DSH_CHECKOUT=/path/to/deepseek-harness node scripts/sync-dist.mjs`
|
|
81
|
+
> (see “Release maintenance” below).
|
|
82
|
+
|
|
83
|
+
## Features
|
|
84
|
+
|
|
85
|
+
- **Core mode** `/ponytail` — injects a structured lazy-developer ruleset
|
|
86
|
+
every turn; **the three levels are genuinely different prompt fragments**
|
|
87
|
+
(not just a swapped line):
|
|
88
|
+
- **Common (shared by every non-off level)**: turn the request into an
|
|
89
|
+
observable completion condition first; gather evidence along the real call
|
|
90
|
+
flow, but the decision ladder is a quick reflex, not a research project;
|
|
91
|
+
follow the “inspect → change → narrowest effective verification → inspect
|
|
92
|
+
the final diff” loop; non-trivial logic keeps exactly one minimal runnable
|
|
93
|
+
check, without standing up a test framework or fixtures; report only
|
|
94
|
+
verified results.
|
|
95
|
+
- **Safety (never removable in any level)**: input validation, error
|
|
96
|
+
handling that prevents data loss, security measures, accessibility,
|
|
97
|
+
explicit acceptance criteria, understanding the problem first, and
|
|
98
|
+
“minimal diff ≠ correct fix”.
|
|
99
|
+
- **`lite`**: execute directly, less ceremony; still complete explicit
|
|
100
|
+
deliverables; you may point out a simpler approach in one sentence, but
|
|
101
|
+
**do not challenge explicit requirements**.
|
|
102
|
+
- **`full`** (default): the full seven-rung ladder (YAGNI → reuse → stdlib
|
|
103
|
+
→ native → installed dependencies → one line → minimal implementation);
|
|
104
|
+
pick the shortest correct implementation by default; fix root causes, not
|
|
105
|
+
symptoms.
|
|
106
|
+
- **`ultra`**: demand evidence before adding code; prefer deleting or
|
|
107
|
+
reusing; proactively question speculative features/caching/abstraction/
|
|
108
|
+
configuration/new dependencies; for complex requests deliver the minimal
|
|
109
|
+
correct version first and state the conditions for expanding — **not a
|
|
110
|
+
blanket refusal**.
|
|
111
|
+
- `off`: no injection at all.
|
|
112
|
+
- Levels are **session-scoped** (session A does not affect session B;
|
|
113
|
+
released automatically when the session ends).
|
|
114
|
+
- Bare `/ponytail`: when enabled it only reports; when `off` it restores the
|
|
115
|
+
effective default level (falling back to `full` if that default is also
|
|
116
|
+
`off`).
|
|
117
|
+
- `/ponytail status`: query only, never modifies, and shows whether the
|
|
118
|
+
current mode comes from a session override or the configured default.
|
|
119
|
+
- `/ponytail reset`: clears the current session override and follows the
|
|
120
|
+
effective configured default again.
|
|
121
|
+
- `/ponytail lite|full|ultra|off`: explicit switch.
|
|
122
|
+
- `/ponytail default <mode>`: persists the default to the **user-level
|
|
123
|
+
config file** (env/profile still take priority; the command reports both
|
|
124
|
+
`saved` and `effective`).
|
|
125
|
+
- Status changes take effect immediately without waking an idle agent.
|
|
126
|
+
Notices reach the model on its next real step, avoiding an extra model
|
|
127
|
+
turn just to switch levels.
|
|
128
|
+
- **One-shot skills** (load on demand, never part of the standing prompt):
|
|
129
|
+
- `/ponytail-review` — find over-engineering in recent changes; every
|
|
130
|
+
finding includes location, replacement, and actual call evidence; no
|
|
131
|
+
guessed savings numbers.
|
|
132
|
+
- `/ponytail-audit` — whole-repo over-engineering audit; distinguishes
|
|
133
|
+
safe-to-delete from verify-first candidates; at most 10 high-value
|
|
134
|
+
findings.
|
|
135
|
+
- `/ponytail-debt` — harvests all `ponytail:` comments into a debt ledger.
|
|
136
|
+
- `/ponytail-gain` — upstream benchmark reference scoreboard (less code;
|
|
137
|
+
token/cost/latency effects depend on model and task, **not guaranteed by
|
|
138
|
+
this port**).
|
|
139
|
+
- `/ponytail-help` — reference card.
|
|
140
|
+
- **Deactivation**: say `stop ponytail`, `normal mode`, `停止 ponytail`,
|
|
141
|
+
`关闭 ponytail`, `普通模式`, or `正常模式` (trailing Chinese/English
|
|
142
|
+
punctuation tolerated); `/ponytail` re-enables at any time.
|
|
143
|
+
- **Default priority** (consistent across code/tests/docs):
|
|
144
|
+
```
|
|
145
|
+
session override > PONYTAIL_DEFAULT_MODE > Profile config.defaultMode > user config.json > full
|
|
146
|
+
```
|
|
147
|
+
- **Profile-level config** (official Cordis plugin config API; each profile
|
|
148
|
+
can differ):
|
|
149
|
+
```yaml
|
|
150
|
+
# add config to the ponytail row in ~/.dsh/profiles/tui/cordis.patch.yml
|
|
151
|
+
- insert:
|
|
152
|
+
- id: ponytail
|
|
153
|
+
name: '@mengyuly/dsh-ponytail'
|
|
154
|
+
config:
|
|
155
|
+
defaultMode: lite
|
|
156
|
+
```
|
|
157
|
+
Example: `web → full`, `tui → lite`, `automation → off`. Profile config is
|
|
158
|
+
read when the plugin initializes (Cordis has no public config-change
|
|
159
|
+
event), so **restart that profile after changing it**; an invalid value
|
|
160
|
+
warns once and falls back without breaking startup. The user `config.json`
|
|
161
|
+
stays hot-reloaded.
|
|
162
|
+
- **User config.json** (`~/.config/ponytail/config.json`, Windows
|
|
163
|
+
`%APPDATA%\ponytail\config.json`): `{"defaultMode": "lite"}`,
|
|
164
|
+
hot-reloaded (~1s polling); invalid content keeps the last valid value.
|
|
165
|
+
- **Subagents (honest boundaries)**: DSH's built-in `subagent` tool is an
|
|
166
|
+
**isolated fork**, but the global system-prompt section participates in each
|
|
167
|
+
subagent's own assembly by default; this is not parent-prompt or session
|
|
168
|
+
state inheritance. `PONYTAIL_SUBAGENT_MATCHER` (a regex matched against the
|
|
169
|
+
subagent's `agentPreset`) only filters which subagents can enter this prompt
|
|
170
|
+
pipeline — it is not an inheritance switch; without a preset nothing is
|
|
171
|
+
excluded by the matcher. DSH currently has no public parent→child prompt
|
|
172
|
+
inheritance API, so **no parent-child prompt inheritance is claimed** (a
|
|
173
|
+
read-only mode-snapshot propagation may follow once an official API
|
|
174
|
+
exists). An invalid regex warns once and fails open.
|
|
175
|
+
- **Config errors**: invalid JSON / invalid `defaultMode` / read failures /
|
|
176
|
+
invalid regex warn exactly once (no log spam); a missing config file is
|
|
177
|
+
normal and never warns.
|
|
178
|
+
|
|
179
|
+
## Efficiency (conditional gains, not guarantees)
|
|
180
|
+
|
|
181
|
+
Ponytail adds a small fixed ruleset to every model request. Its benefit is
|
|
182
|
+
**conditional**: when the agent tends to over-engineer, the reduced code,
|
|
183
|
+
tool calls, and rework may offset or exceed that overhead; when the task is
|
|
184
|
+
already simple, the gain may be near zero — or the extra input overhead may
|
|
185
|
+
lose outright. It is not a “save tokens switch” and does not guarantee savings
|
|
186
|
+
across models — some reasoning models may get more expensive due to prompt
|
|
187
|
+
and reasoning overhead.
|
|
188
|
+
|
|
189
|
+
Measured prompt-section sizes for this DSH port (`node
|
|
190
|
+
scripts/measure-prompt.mjs`, generated from the real
|
|
191
|
+
`getPonytailInstructions()`):
|
|
192
|
+
|
|
193
|
+
| Level | Characters | UTF-8 bytes | Notes |
|
|
194
|
+
|------|--------|-----------|------|
|
|
195
|
+
| lite | 1915 | 1917 | measured output |
|
|
196
|
+
| full | 3022 | 3038 | measured output |
|
|
197
|
+
| ultra | 2797 | 2813 | measured output |
|
|
198
|
+
| off | 0 | 0 | not injected |
|
|
199
|
+
|
|
200
|
+
These are **prompt-size measurements, not billing amounts, and not a savings
|
|
201
|
+
ratio that holds for every model** (there is no universal tokenizer;
|
|
202
|
+
`estimated_tokens` in `measure:prompt` output is null; characters/4 is only a
|
|
203
|
+
rough estimate). Same-mode output is byte-stable, so KV-cache prefixes hit.
|
|
204
|
+
|
|
205
|
+
**Upstream numbers are not a guarantee for this DSH port**: the upstream
|
|
206
|
+
Ponytail single-shot results (code −80–94%, cost −42–75%, latency 3.1–5.8×)
|
|
207
|
+
and agentic results (LOC −54% etc.) are references only; this DSH port has
|
|
208
|
+
**not** established stable token/cost/latency savings rates. The DSH smoke
|
|
209
|
+
benchmark provides directional evidence only (see
|
|
210
|
+
`docs/dsh-smoke-summary.md`).
|
|
211
|
+
|
|
212
|
+
## Known limitations
|
|
213
|
+
|
|
214
|
+
- The levels differ in **rule semantics** (see above); the three prompt
|
|
215
|
+
sizes are similar (measured in the table above).
|
|
216
|
+
- The upstream Claude-only statusline badge has no DSH counterpart; the MCP
|
|
217
|
+
server was dropped because DSH has a first-class system-prompt injection
|
|
218
|
+
point.
|
|
219
|
+
- User `config.json` hot-reloads; `PONYTAIL_DEFAULT_MODE` and profile config
|
|
220
|
+
need a restart.
|
|
221
|
+
- The shipped `lib/` is a prebuilt artifact; to change behavior, rebuild in
|
|
222
|
+
the main repo and re-sync.
|
|
223
|
+
|
|
224
|
+
## Compatibility matrix (measured, not fabricated)
|
|
225
|
+
|
|
226
|
+
| Component | Verified environment | Notes |
|
|
227
|
+
|---|---|---|
|
|
228
|
+
| Node.js | 22.x / 24.x | CI matrix, 4 combinations green |
|
|
229
|
+
| OS | ubuntu-latest / windows-latest | CI matrix |
|
|
230
|
+
| DSH | commit `b150a551` (build checkout) | exact mapping to an official release **TBD** |
|
|
231
|
+
| Cordis | 4.0.1 (build vendor) | same |
|
|
232
|
+
| web profile | verified | long-running on a real local profile + three isolated install-path tests (npm / GitHub / tgz) |
|
|
233
|
+
| tui profile | not verified | not started inside a tui profile |
|
|
234
|
+
| headless profile | not verified | not fully started; plugin unit tests run in a UI-less environment |
|
|
235
|
+
| npm tarball | verified | contents/version/post-install smoke/NodeNext consumer |
|
|
236
|
+
|
|
237
|
+
- `dist-provenance.json` records the actual build sources (checkout commit +
|
|
238
|
+
node/typescript/tsdown/cordis versions).
|
|
239
|
+
- Do not hide failures with `continue-on-error` — the matrix is green only if
|
|
240
|
+
every cell is green.
|
|
241
|
+
|
|
242
|
+
## Test environments and source of truth
|
|
243
|
+
|
|
244
|
+
- Verified locally (Linux, Node.js **v24.16.0**, deepseek-harness checkout
|
|
245
|
+
build) and in the CI matrix (**ubuntu-latest + windows-latest × Node
|
|
246
|
+
22/24**). The exact published DSH/Cordis release they correspond to is
|
|
247
|
+
**TBD** — the checkout is a prerelease working tree, not a release tag.
|
|
248
|
+
- The authoritative source is `packages/community/ponytail`
|
|
249
|
+
(`@deepseek-ai/dsh-ponytail`) in the deepseek-harness monorepo; this
|
|
250
|
+
repository (`@mengyuly/dsh-ponytail`) is a **distribution mirror**: it
|
|
251
|
+
ships build artifacts with the package and is not an independent source of
|
|
252
|
+
truth.
|
|
253
|
+
|
|
254
|
+
## Release maintenance
|
|
255
|
+
|
|
256
|
+
> **The commands below are for source-repository maintainers only.** The
|
|
257
|
+
> `scripts/` directory is deliberately **excluded from the npm tarball**, so
|
|
258
|
+
> these commands are unavailable after installing the published package — npm
|
|
259
|
+
> users never need to run maintenance checks; they exist for maintainers and
|
|
260
|
+
> CI before a release. The published `package.json` exposes no `scripts/`
|
|
261
|
+
> commands (no maintenance entry points, no install lifecycle hooks),
|
|
262
|
+
> enforced by a regression check in `node scripts/verify-pack.mjs`.
|
|
263
|
+
|
|
264
|
+
- **Authoritative source**: `packages/community/ponytail` in the
|
|
265
|
+
deepseek-harness monorepo (this repository is a distribution mirror that
|
|
266
|
+
publishes build artifacts only).
|
|
267
|
+
- **Maintainer commands** (run `node scripts/<script>.mjs` inside the source
|
|
268
|
+
repository; see `package.dev.json` for the shortcut list):
|
|
269
|
+
```bash
|
|
270
|
+
node scripts/check-bundle.mjs # bundle external-dependency allowlist + no new Function/eval
|
|
271
|
+
node scripts/verify-dist.mjs # static consistency: src/d.ts export parity, key signatures, runtime exports, provenance
|
|
272
|
+
node scripts/verify-pack.mjs # tarball boundary (incl. no scripts/ exposure regression), versions, post-install smoke
|
|
273
|
+
node scripts/test-consumer.mjs # NodeNext + skipLibCheck:false declaration consumer test (against the packed artifact)
|
|
274
|
+
node scripts/test-regressions.mjs # regression tests for the verification tooling itself
|
|
275
|
+
node scripts/test-core.mjs # core prompt bytes, safety boundaries, modes and skill surface
|
|
276
|
+
node scripts/measure-prompt.mjs # prompt-section size per mode (depends on the unpublished src/)
|
|
277
|
+
node scripts/check-release-links.mjs # README/CHANGELOG/docs contain no versioned latest asset links
|
|
278
|
+
node scripts/check-release-consistency.mjs --version <v> # four-way release consistency (git tag/npm/GitHub/provenance)
|
|
279
|
+
```
|
|
280
|
+
- **Fully regenerate and sync `lib/`** (JS and declarations must be synced as
|
|
281
|
+
one artifact; copying a single JS file is forbidden):
|
|
282
|
+
```bash
|
|
283
|
+
DSH_CHECKOUT=/path/to/deepseek-harness node scripts/sync-dist.mjs
|
|
284
|
+
```
|
|
285
|
+
This rebuilds inside the authoritative checkout (`tsc` for declarations +
|
|
286
|
+
`tsdown` for the runtime bundle), syncs `lib/index.js`, `lib/invariant.js`,
|
|
287
|
+
`lib/types/*.d.ts`, generates `dist-provenance.json` (recording the
|
|
288
|
+
authoritative checkout's real commit SHA and toolchain versions), and runs
|
|
289
|
+
the consistency checks automatically; it prompts you to commit when
|
|
290
|
+
artifacts changed. **Full build consistency is produced by this command in
|
|
291
|
+
the release process — the mirror repository's CI never rebuilds the
|
|
292
|
+
authoritative monorepo.**
|
|
293
|
+
- **CI capability boundary (honest)**: CI (ubuntu + windows matrix) runs the
|
|
294
|
+
static verification and pack/consumer tests above, but **does not rebuild
|
|
295
|
+
the authoritative monorepo**; `verify:dist` is an export-surface/signature/
|
|
296
|
+
runtime-export consistency check, **not** a byte-level equivalence proof
|
|
297
|
+
against the authoritative build — that is guaranteed by `sync:dist` in the
|
|
298
|
+
release process.
|
|
299
|
+
- `dist-provenance.json` ships with the npm package for build-source audits.
|
|
300
|
+
- When verifying locally, if `npm_execpath` points at another package manager
|
|
301
|
+
(e.g. a pnpm/yarn shim), the scripts fall back to `npm` on PATH; set
|
|
302
|
+
`PONYTAIL_VERIFY_KEEP_TEMP=1` to keep temp directories on failure.
|
|
303
|
+
- **Security**: `scripts/**` exists only for development/build/release
|
|
304
|
+
verification — **not in the npm tarball**, no install lifecycle hooks, not
|
|
305
|
+
referenced by the runtime entry point, and not exposed in the published
|
|
306
|
+
`package.json`; `child_process` warnings there are accepted development-tool
|
|
307
|
+
risk. See [SECURITY.md](SECURITY.md).
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT, © 2026 DietrichGebert (upstream) + MengYuil (port). See [LICENSE](LICENSE).
|
package/cordis.patch.yml
CHANGED
package/lib/index.js
CHANGED
|
@@ -1696,7 +1696,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1696
1696
|
deps.setDefault(effective);
|
|
1697
1697
|
const reason = defaultOverrideReason(process.env, deps.profileMode);
|
|
1698
1698
|
if (reason !== null) {
|
|
1699
|
-
agent.
|
|
1699
|
+
agent.inject(createUserMessage({
|
|
1700
1700
|
content: [{
|
|
1701
1701
|
type: "text",
|
|
1702
1702
|
text: `PONYTAIL DEFAULT SET — saved ${written}, effective ${effective} (${reason}).`
|
|
@@ -1711,7 +1711,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1711
1711
|
text: `Saved default: ${written}. Effective default: ${effective}, overridden by ${reason}.`
|
|
1712
1712
|
};
|
|
1713
1713
|
}
|
|
1714
|
-
agent.
|
|
1714
|
+
agent.inject(createUserMessage({
|
|
1715
1715
|
content: [{
|
|
1716
1716
|
type: "text",
|
|
1717
1717
|
text: `PONYTAIL DEFAULT SET — new sessions start in ${written}.`
|
|
@@ -1739,7 +1739,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1739
1739
|
const changed = deps.store.has(key);
|
|
1740
1740
|
deps.store.clear(key);
|
|
1741
1741
|
const current = deps.defaultMode();
|
|
1742
|
-
if (changed) agent.
|
|
1742
|
+
if (changed) agent.inject(createUserMessage({
|
|
1743
1743
|
content: [{
|
|
1744
1744
|
type: "text",
|
|
1745
1745
|
text: modeNotice(current)
|
|
@@ -1760,7 +1760,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1760
1760
|
if (current === "off") {
|
|
1761
1761
|
if (effectiveDefault === "off") {
|
|
1762
1762
|
deps.store.set(sessionKey(agent), "full");
|
|
1763
|
-
agent.
|
|
1763
|
+
agent.inject(createUserMessage({
|
|
1764
1764
|
content: [{
|
|
1765
1765
|
type: "text",
|
|
1766
1766
|
text: "PONYTAIL MODE CHANGED — level: full"
|
|
@@ -1776,7 +1776,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1776
1776
|
};
|
|
1777
1777
|
}
|
|
1778
1778
|
deps.store.clear(sessionKey(agent));
|
|
1779
|
-
agent.
|
|
1779
|
+
agent.inject(createUserMessage({
|
|
1780
1780
|
content: [{
|
|
1781
1781
|
type: "text",
|
|
1782
1782
|
text: `PONYTAIL MODE ACTIVE — level: ${effectiveDefault}`
|
|
@@ -1791,7 +1791,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1791
1791
|
text: `Ponytail re-enabled. Effective default: ${effectiveDefault}.`
|
|
1792
1792
|
};
|
|
1793
1793
|
}
|
|
1794
|
-
agent.
|
|
1794
|
+
agent.inject(createUserMessage({
|
|
1795
1795
|
content: [{
|
|
1796
1796
|
type: "text",
|
|
1797
1797
|
text: `PONYTAIL MODE ACTIVE — level: ${current}`
|
|
@@ -1812,7 +1812,7 @@ function registerCommands(deps, commandCtx) {
|
|
|
1812
1812
|
text: "Usage: /ponytail [status|reset|default <mode>|lite|full|ultra|off]"
|
|
1813
1813
|
};
|
|
1814
1814
|
deps.store.set(sessionKey(agent), mode);
|
|
1815
|
-
agent.
|
|
1815
|
+
agent.inject(createUserMessage({
|
|
1816
1816
|
content: [{
|
|
1817
1817
|
type: "text",
|
|
1818
1818
|
text: modeNotice(mode)
|
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.3.
|
|
4
|
+
"version": "0.3.4",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
+
"README_EN.md",
|
|
28
29
|
"dist-provenance.json",
|
|
29
30
|
"CHANGELOG.md",
|
|
30
31
|
"lib/index.js",
|