@theseus-whale/dsh-continuity 0.0.0-stage → 4.12.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/INSTALL.md +25 -0
- package/PANEL.md +92 -0
- package/README.md +286 -2
- package/RELEASE-NOTES.md +732 -0
- package/bin/bc-acceptance-full.mjs +91 -0
- package/bin/bc-acceptance-tight.mjs +66 -0
- package/bin/bc-acceptance.mjs +22 -0
- package/bin/bc-add-keywords.mjs +21 -0
- package/bin/bc-demo.mjs +47 -0
- package/bin/bc-expand-hint.mjs +179 -0
- package/bin/bc-ingest-index.mjs +35 -0
- package/bin/bc-ingest.mjs +31 -0
- package/bin/bc-label-demo.mjs +18 -0
- package/bin/bc-relabel.mjs +150 -0
- package/bin/bc-sessionize.mjs +59 -0
- package/bin/coref_pipeline.py +47 -0
- package/bin/coref_service.py +57 -0
- package/bin/debug_ckip.py +16 -0
- package/bin/debug_ner_zh.py +18 -0
- package/bin/doctor.mjs +275 -0
- package/bin/en_ner_error_audit.py +33 -0
- package/bin/eval-label-rules.mjs +342 -0
- package/bin/export-turns.py +68 -0
- package/bin/extract-user-paragraph.mjs +14 -0
- package/bin/extraction-composite-smoke.mjs +28 -0
- package/bin/extraction-latency.mjs +58 -0
- package/bin/extraction-user-smoke.mjs +28 -0
- package/bin/extraction_service.py +164 -0
- package/bin/facet-active-experiment.mjs +110 -0
- package/bin/facet-covid.mjs +8 -0
- package/bin/facet-curve.mjs +27 -0
- package/bin/facet-embedding-train.mjs +20 -0
- package/bin/facet-embedding-validate.mjs +83 -0
- package/bin/facet-eval-roleplay.mjs +42 -0
- package/bin/facet-eval.mjs +38 -0
- package/bin/facet-fold.mjs +31 -0
- package/bin/facet-load.mjs +16 -0
- package/bin/facet-mlp-scan.mjs +45 -0
- package/bin/facet-mvp.mjs +34 -0
- package/bin/facet-online-experiments.mjs +78 -0
- package/bin/facet-online-race.mjs +99 -0
- package/bin/facet-online-validate.mjs +51 -0
- package/bin/facet-panel.mjs +22 -0
- package/bin/facet-passage.mjs +41 -0
- package/bin/facet-random-validate.mjs +48 -0
- package/bin/facet-roleplay.mjs +33 -0
- package/bin/facet-scan.mjs +56 -0
- package/bin/facet-segment.mjs +34 -0
- package/bin/facet-train.mjs +19 -0
- package/bin/facet-validate.mjs +103 -0
- package/bin/facet-zeroshot.mjs +14 -0
- package/bin/install-templates.mjs +72 -0
- package/bin/memory-bench.mjs +53 -0
- package/bin/memory-build-summary.mjs +43 -0
- package/bin/memory-build-vector.mjs +31 -0
- package/bin/memory-build.mjs +41 -0
- package/bin/memory-calibration.mjs +70 -0
- package/bin/memory-closed-loop.mjs +119 -0
- package/bin/memory-dry-run.mjs +70 -0
- package/bin/memory-eval.mjs +104 -0
- package/bin/memory-event-alias-test.mjs +89 -0
- package/bin/memory-extraction-bench.mjs +58 -0
- package/bin/memory-load-gate-replay.mjs +137 -0
- package/bin/memory-loop-test.mjs +90 -0
- package/bin/memory-pre-turn-harness.mjs +63 -0
- package/bin/memory-query.mjs +39 -0
- package/bin/memory-replay-hints.mjs +84 -0
- package/bin/memory-scale.mjs +58 -0
- package/bin/memory-scenario-test.mjs +146 -0
- package/bin/memory-user-loop.mjs +95 -0
- package/bin/ner_bench_tiny_zh.py +59 -0
- package/bin/ner_bench_zh.py +60 -0
- package/bin/ner_conll_en.py +139 -0
- package/bin/ner_direct_en.py +123 -0
- package/bin/ner_direct_zh.py +100 -0
- package/bin/ner_pipeline.py +208 -0
- package/bin/noise-selfcheck.mjs +50 -0
- package/bin/pack-integrity.mjs +47 -0
- package/bin/panel-check.mjs +57 -0
- package/bin/plugin-integrity.mjs +74 -0
- package/bin/preview-live.mjs +13 -0
- package/bin/public-install-check.mjs +222 -0
- package/bin/relabel-apply.mjs +272 -0
- package/bin/relabel-dry-run.mjs +381 -0
- package/bin/relik_pipeline.py +39 -0
- package/bin/relik_service.py +52 -0
- package/bin/srl_pipeline.py +55 -0
- package/bin/srl_service.py +68 -0
- package/bin/summary-index.mjs +151 -0
- package/bin/summary-query.mjs +79 -0
- package/bin/vec-check.mjs +27 -0
- package/bin/zh_ner_error_audit.py +36 -0
- package/bin/zh_ner_slot_eval.py +38 -0
- package/client.js +760 -0
- package/cordis.patch.yml +378 -0
- package/docs/API-NOTES.md +1743 -0
- package/docs/ARCHITECTURE.md +355 -0
- package/docs/CACHE.md +253 -0
- package/docs/CONDUCT.md +30 -0
- package/docs/CREATOR-HANDOFF.md +102 -0
- package/docs/EXPERIMENT.md +136 -0
- package/docs/FACET-MVP-REPORT.md +473 -0
- package/docs/GUIDE-0.4.66.md +195 -0
- package/docs/GUIDE.md +127 -0
- package/docs/MECHANISM.md +243 -0
- package/docs/NEW-INSTANCE-HANDOFF.md +219 -0
- package/docs/README.md +37 -0
- package/docs/SESSION-LAYOUT.md +151 -0
- package/docs/history-map.md +249 -0
- package/docs/relabel-migration-wiring.md +366 -0
- package/guides/00-READ-FIRST.md +206 -0
- package/guides/01-INSTALL.md +207 -0
- package/guides/02-TABLES.md +225 -0
- package/guides/03-AUDIT.md +201 -0
- package/guides/04-REBUILD.md +306 -0
- package/guides/05-FIRST-RUN.md +191 -0
- package/guides/06-EMBEDDING.md +146 -0
- package/guides/07-PTC-AND-ASSETS.md +221 -0
- package/icon.svg +7 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/models/README.md +13 -0
- package/models/Xenova/bge-small-zh-v1.5/config.json +31 -0
- package/models/Xenova/bge-small-zh-v1.5/onnx/model_quantized.onnx +0 -0
- package/models/Xenova/bge-small-zh-v1.5/tokenizer.json +21278 -0
- package/models/Xenova/bge-small-zh-v1.5/tokenizer_config.json +15 -0
- package/package.json +139 -4
- package/src/asset-tool.mjs +237 -0
- package/src/assets.mjs +244 -0
- package/src/backfill.mjs +74 -0
- package/src/backup.mjs +80 -0
- package/src/deadend.mjs +95 -0
- package/src/deleted-store.mjs +35 -0
- package/src/engine.mjs +3831 -0
- package/src/facets/classifier.mjs +146 -0
- package/src/facets/embedding-service.mjs +53 -0
- package/src/facets/embedding-worker.mjs +27 -0
- package/src/facets/embedding.mjs +163 -0
- package/src/facets/extract.mjs +80 -0
- package/src/facets/fold-plan.mjs +84 -0
- package/src/facets/hybrid.mjs +29 -0
- package/src/facets/index.mjs +113 -0
- package/src/facets/linear-probe.mjs +43 -0
- package/src/facets/load.mjs +37 -0
- package/src/facets/mlp-probe.mjs +54 -0
- package/src/facets/mlp-service.mjs +53 -0
- package/src/facets/mlp-worker.mjs +26 -0
- package/src/facets/online-knn.mjs +58 -0
- package/src/facets/online-models.mjs +227 -0
- package/src/facets/panel-state.mjs +23 -0
- package/src/facets/panel.mjs +73 -0
- package/src/facets/random.mjs +26 -0
- package/src/facets/scanner.mjs +35 -0
- package/src/facets/schema.mjs +75 -0
- package/src/facets/seed-examples.mjs +58 -0
- package/src/facets/sensitivity.mjs +98 -0
- package/src/facets/service.mjs +53 -0
- package/src/facets/store.mjs +39 -0
- package/src/facets/worker.mjs +23 -0
- package/src/folds-store.mjs +109 -0
- package/src/groups.mjs +167 -0
- package/src/handoff-tool.mjs +51 -0
- package/src/handoff.mjs +127 -0
- package/src/index.mjs +649 -0
- package/src/inject-policy.mjs +17 -0
- package/src/learning.mjs +88 -0
- package/src/memory/alias-proposal.mjs +40 -0
- package/src/memory/bc-audit.mjs +245 -0
- package/src/memory/bc-index-updater.mjs +404 -0
- package/src/memory/bc-index.mjs +48 -0
- package/src/memory/bc-label.mjs +220 -0
- package/src/memory/bc-panel-state.mjs +107 -0
- package/src/memory/bc-pre-step.mjs +463 -0
- package/src/memory/bc-recall.mjs +470 -0
- package/src/memory/bc-shift.mjs +123 -0
- package/src/memory/bc-store.mjs +41 -0
- package/src/memory/bm25.mjs +112 -0
- package/src/memory/calibration.mjs +54 -0
- package/src/memory/chatter.mjs +29 -0
- package/src/memory/cmap-file.mjs +107 -0
- package/src/memory/concepts-file.mjs +41 -0
- package/src/memory/coref-slots.mjs +40 -0
- package/src/memory/event-alias-ledger.mjs +87 -0
- package/src/memory/event-log.mjs +95 -0
- package/src/memory/event-model.mjs +132 -0
- package/src/memory/event-segmenter.mjs +36 -0
- package/src/memory/event-summary-tree.mjs +122 -0
- package/src/memory/extraction-adapter.mjs +76 -0
- package/src/memory/extraction-composite.mjs +75 -0
- package/src/memory/extraction-core.mjs +76 -0
- package/src/memory/extraction-pre-step.mjs +161 -0
- package/src/memory/extraction-provider.mjs +300 -0
- package/src/memory/extraction-score.mjs +36 -0
- package/src/memory/facet-stabilizer.mjs +59 -0
- package/src/memory/history-map.mjs +139 -0
- package/src/memory/language-router.mjs +30 -0
- package/src/memory/load-gate.mjs +161 -0
- package/src/memory/mechanical-note.mjs +104 -0
- package/src/memory/onboarding.mjs +163 -0
- package/src/memory/persona.mjs +78 -0
- package/src/memory/planner.mjs +249 -0
- package/src/memory/pre-turn.mjs +80 -0
- package/src/memory/query-aliases.mjs +39 -0
- package/src/memory/recall-cue.mjs +43 -0
- package/src/memory/recall.mjs +65 -0
- package/src/memory/referent-candidates.mjs +55 -0
- package/src/memory/referent-ledger.mjs +86 -0
- package/src/memory/relabel-migrate.mjs +376 -0
- package/src/memory/relik-adapter.mjs +25 -0
- package/src/memory/special-keywords.mjs +60 -0
- package/src/memory/structured-adapters.mjs +75 -0
- package/src/memory/summary-index.mjs +335 -0
- package/src/memory/summary-tree.mjs +110 -0
- package/src/memory/term-extractor.mjs +44 -0
- package/src/memory/tokenize.mjs +9 -0
- package/src/memory/vector-index.mjs +54 -0
- package/src/memory/window-summary.mjs +133 -0
- package/src/mood.mjs +133 -0
- package/src/peer-tool.mjs +63 -0
- package/src/peer.mjs +144 -0
- package/src/policy.mjs +170 -0
- package/src/preflight.mjs +113 -0
- package/src/provenance.mjs +94 -0
- package/src/range.mjs +75 -0
- package/src/recall-exact-tool.mjs +267 -0
- package/src/recall-tool.mjs +521 -0
- package/src/recheck.mjs +99 -0
- package/src/save-start.mjs +29 -0
- package/src/session-guard.mjs +140 -0
- package/src/session-log-tool.mjs +322 -0
- package/src/session-log.mjs +606 -0
- package/src/skills.mjs +111 -0
- package/src/split-range.mjs +115 -0
- package/src/state.mjs +198 -0
- package/src/t0.mjs +149 -0
- package/src/tag-confirm.mjs +78 -0
- package/src/tag-detect.mjs +42 -0
- package/src/tag-maintenance.mjs +285 -0
- package/src/tag-reject.mjs +73 -0
- package/src/tags-store.mjs +94 -0
- package/src/tags.mjs +692 -0
- package/src/threads-backend.mjs +26 -0
- package/src/threads-core.mjs +1887 -0
- package/src/threads-store.mjs +207 -0
- package/src/threads-tool.mjs +522 -0
- package/src/threads.mjs +929 -0
- package/src/tool-preview.mjs +427 -0
- package/src/topic.mjs +63 -0
- package/src/training.mjs +75 -0
- package/src/turn-tag.mjs +62 -0
- package/src/user-turn.mjs +39 -0
- package/templates/cmap.md +11 -0
- package/templates/concepts.md +12 -0
- package/templates/habits.md +40 -0
- package/templates/keywords.md +6 -0
- package/templates/rebuild.md +134 -0
- package/templates/rules-safe.md +184 -0
- package/templates/rules.md +177 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# Continuity architecture — 4.11.36
|
|
2
|
+
|
|
3
|
+
## 1. Shape
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
DSH Host
|
|
7
|
+
└ dsh-continuity host row
|
|
8
|
+
├ /dsh-continuity/state.json
|
|
9
|
+
├ /dsh-continuity/bc.json
|
|
10
|
+
├ /dsh-continuity/peer
|
|
11
|
+
├ per-session bc pre-step
|
|
12
|
+
└ best-effort tool path guard
|
|
13
|
+
|
|
14
|
+
Continuity preset
|
|
15
|
+
├ compaction engine
|
|
16
|
+
├ session_log
|
|
17
|
+
└ threads-tool (safe mode: recall + peer + session_log)
|
|
18
|
+
|
|
19
|
+
Client
|
|
20
|
+
├ left sidebar control panel
|
|
21
|
+
└ per-session A/B/C/K right tab
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Safe mode does not add a separate prompt-classification, tagging, or workline layer.
|
|
25
|
+
|
|
26
|
+
## 2. Session owns everything
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
~/.dsh/continuity/sessions/<sessionId>/
|
|
30
|
+
bc-index.jsonl
|
|
31
|
+
bc-index-state.json
|
|
32
|
+
audit-state.json
|
|
33
|
+
expand-hint.jsonl
|
|
34
|
+
concepts.md
|
|
35
|
+
cmap.md
|
|
36
|
+
keywords.md
|
|
37
|
+
aliases.md
|
|
38
|
+
rules.md
|
|
39
|
+
habits.md
|
|
40
|
+
rebuild.md
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
No A/C/K/rules/habits inheritance between sessions. A new session starts with:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
empty A/C/K
|
|
47
|
+
rules.md <- templates/rules.md
|
|
48
|
+
habits.md <- templates/habits.md
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Personas are identity/enable labels only:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
session-persona.json:
|
|
55
|
+
<sessionId> -> continuity | <pid>
|
|
56
|
+
default -> continuity
|
|
57
|
+
|
|
58
|
+
personas/<pid>/persona.json:
|
|
59
|
+
{"enabled": true}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`continuity` is enabled for old installs without a file. A disabled persona is
|
|
63
|
+
skipped by the pre-step and its panel returns `persona-disabled`.
|
|
64
|
+
|
|
65
|
+
## 3. Write path
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
completed human turn
|
|
69
|
+
-> bc-pre-step sees agent.session.id
|
|
70
|
+
-> resolve persona (enable check only)
|
|
71
|
+
-> ensure session scaffolds
|
|
72
|
+
-> index file sessions/<id>/bc-index.jsonl
|
|
73
|
+
-> read session tail after lastSeq
|
|
74
|
+
-> label with that session's concepts
|
|
75
|
+
-> append one pointer record
|
|
76
|
+
-> save JSONL + bc-index-state.json
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The current turn is indexed on the next pre-step. Up to 8 missing turns per
|
|
80
|
+
pass; background repair continues. Failure writes `gate-errors.jsonl`.
|
|
81
|
+
|
|
82
|
+
New records carry:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"turn": 40,
|
|
87
|
+
"seqStart": 2186,
|
|
88
|
+
"seqEnd": 2186,
|
|
89
|
+
"generic": ["跑团叙事", "原文与上下文"],
|
|
90
|
+
"genericTopic": ["跑团叙事"],
|
|
91
|
+
"genericWorkflow": ["原文与上下文"],
|
|
92
|
+
"topicScore": 0.71,
|
|
93
|
+
"topicConfidence": "normal",
|
|
94
|
+
"labelVersion": 2,
|
|
95
|
+
"terms": ["跑团"],
|
|
96
|
+
"keywords": ["coo"],
|
|
97
|
+
"conceptScores": {"跑团叙事": 0.71, "原文与上下文": 0.66},
|
|
98
|
+
"vec": "...",
|
|
99
|
+
"chatter": 0.42,
|
|
100
|
+
"sessionId": "session-..."
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
No raw text is stored in the index. Old records read as `labelVersion: 1` and
|
|
105
|
+
have no `topicScore`; they are not backfilled.
|
|
106
|
+
|
|
107
|
+
## 4. A / B / C / K
|
|
108
|
+
|
|
109
|
+
### A — concepts
|
|
110
|
+
|
|
111
|
+
```text
|
|
112
|
+
name | description words | coverage estimate | kind
|
|
113
|
+
kind = topic | workflow (default: topic)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
- `recall("A标签")` lists topic only.
|
|
117
|
+
- `recall("A标签:workflow")` lists workflow only.
|
|
118
|
+
- `recall("A标签:<name>")` browses any concept.
|
|
119
|
+
- `kind` is a human decision, not derived from coverage.
|
|
120
|
+
|
|
121
|
+
### B — per-turn labels
|
|
122
|
+
|
|
123
|
+
`generic` is the topic+workflow union for compatibility. `genericTopic` and
|
|
124
|
+
`genericWorkflow` carry the split. B is display/feature material, not A browse.
|
|
125
|
+
|
|
126
|
+
### C / K
|
|
127
|
+
|
|
128
|
+
Both are session-local files:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
sessions/<id>/cmap.md
|
|
132
|
+
sessions/<id>/keywords.md
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
No fallback to another session, a persona, or the old global table.
|
|
136
|
+
|
|
137
|
+
## 5. Recall
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
recall({ query?, recent?, sinceTurn? })
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
| Query | Result |
|
|
144
|
+
|---|---|
|
|
145
|
+
| none | interpret current user message |
|
|
146
|
+
| `A标签` | topic inventory |
|
|
147
|
+
| `A标签:workflow` | workflow inventory |
|
|
148
|
+
| `A标签:<name>` | area hits for that concept |
|
|
149
|
+
| `B标签` / `C标签` / `K标签` | namespace inventory |
|
|
150
|
+
| `B标签 <v>` / `C标签 <v>` / `K标签 <v>` | namespace search |
|
|
151
|
+
| plain text | literal + alias + K/C/A |
|
|
152
|
+
|
|
153
|
+
- Index and vocabulary come from the current session only.
|
|
154
|
+
- `via` is `A | B | C | K | live`.
|
|
155
|
+
- `intervals` keeps every match; the injected note is bounded.
|
|
156
|
+
- A result is candidates, not facts; open the cited turn/seq.
|
|
157
|
+
|
|
158
|
+
## 6. Compaction and receipts
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
measure
|
|
162
|
+
-> planFold(policy)
|
|
163
|
+
-> choose oldest balanced range
|
|
164
|
+
-> summarize range to [gist]
|
|
165
|
+
-> keep protected tail
|
|
166
|
+
-> record fold + pass
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Band:
|
|
170
|
+
|
|
171
|
+
```text
|
|
172
|
+
high = 0.48 W start a pass
|
|
173
|
+
low = 0.32 W target request
|
|
174
|
+
emergency = 0.65 W
|
|
175
|
+
emergencyTo = 0.42 W
|
|
176
|
+
protect = 0.14 W
|
|
177
|
+
maxPerBatch = 190k
|
|
178
|
+
minAction = 24k
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The continuity preset uses this balanced band from 4.9.122. On the measured
|
|
182
|
+
0b window (baseline 133,272) the floor is ~244.2k, so the 253.6k low target is
|
|
183
|
+
reachable with ~9.4k headroom; .14 is a conservative default, not a guarantee. One pass removes
|
|
184
|
+
~127k, below the 190k cap; emergency 0.65→0.42 is 182k, so the 190k cap is
|
|
185
|
+
kept for emergency drainage.
|
|
186
|
+
|
|
187
|
+
One pass folds one oldest contiguous range. `budget` caps the folded **surface**
|
|
188
|
+
tokens only; the associated non-surface prefix can leave with it, so actual
|
|
189
|
+
request reduction can exceed the budget. Measured: pre 375,803 → next request
|
|
190
|
+
201,756 (174,047 gone) while budget was 122,179 and folded surface was 114,373.
|
|
191
|
+
The selected end must also be tool-pair balanced, so `afterTokens` can be above
|
|
192
|
+
the floor. This is expected, not a measurement error: the measured 0b pass was
|
|
193
|
+
+3,639 above its floor. Reachable floor:
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
floor(T) = (protect * W + baseline(T)) / W
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`baseline` is not constant. For the pass decision, use the baseline at the
|
|
200
|
+
triggering request (`preBaselineTokens`); `afterBaselineTokens` describes the
|
|
201
|
+
post-fold state and must not be used as the pass floor. The measured 0b pass
|
|
202
|
+
closed at preBaseline 133,272 + .16W = 260,084, and afterTokens was 263,723
|
|
203
|
+
(+3,639 from the tool-pair cut).
|
|
204
|
+
|
|
205
|
+
`protect` is calibrated once, at the first band-high trigger, from that
|
|
206
|
+
request's preBaseline:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
protect_eff = clamp((low*W - preBaseline - margin)/W, 0.10, 0.20)
|
|
210
|
+
margin = 0.01*W
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The same fold uses the calibrated value; it is then frozen for the session
|
|
214
|
+
(protect_source=calibration, B0=preBaseline, margin recorded). If calibration
|
|
215
|
+
is unavailable, the default .14 is used (`protect_source=default`). Later folds
|
|
216
|
+
compare the suggested protect against protect_eff; a gap >= 0.02 produces one
|
|
217
|
+
suggestion, never an automatic policy change. If protect_eff clamps at .10 and
|
|
218
|
+
floor >= low, both "low unreachable" and `low_min = floor + margin` are
|
|
219
|
+
reported.
|
|
220
|
+
|
|
221
|
+
Long-session data (5,498 measurements, baseline/surface median 0.519) shows
|
|
222
|
+
that .14 is not a guarantee: floor = baseline + .14W is below low only while
|
|
223
|
+
baseline < 142,663, and three of six sampled pre-fold baselines were above
|
|
224
|
+
that. The drift criterion therefore watches protect distance, not just a
|
|
225
|
+
baseline percentage.
|
|
226
|
+
|
|
227
|
+
Receipt:
|
|
228
|
+
|
|
229
|
+
```text
|
|
230
|
+
[continuity:fold] seq <from>–<to> · N 条 · tokens · reason=...
|
|
231
|
+
压前 ... → 压后 ... · window ...
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Files:
|
|
235
|
+
|
|
236
|
+
```text
|
|
237
|
+
~/.dsh/continuity/passes.jsonl append-only, no 24-row cap
|
|
238
|
+
~/.dsh/continuity/folds.json from/to/gistSeq/at;
|
|
239
|
+
new folds also count/compactionId
|
|
240
|
+
~/.dsh/continuity/sessions/<id>/dropped-ranges.json
|
|
241
|
+
per-session merged ranges + coverageFrom
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
`sessions/<id>/dropped-ranges.json` merges only that session's folds (history
|
|
245
|
+
before pass receipts) and passes. The global `dropped-ranges.json` is no longer
|
|
246
|
+
written; merging different seq spaces was invalid.
|
|
247
|
+
|
|
248
|
+
## 7. Audit
|
|
249
|
+
|
|
250
|
+
Every 200 turns, the per-session audit reads the session index and the session's
|
|
251
|
+
concepts:
|
|
252
|
+
|
|
253
|
+
```text
|
|
254
|
+
vec + chatter + keywords + conceptScores
|
|
255
|
+
k = clamp(round(N/50), 20, 60)
|
|
256
|
+
size >= 10
|
|
257
|
+
topicMax < 0.5
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The result is a pending hint in the session's `expand-hint.jsonl`. It does not
|
|
261
|
+
edit concepts automatically. An empty A table skips audit rather than failing.
|
|
262
|
+
|
|
263
|
+
## 8. Panel
|
|
264
|
+
|
|
265
|
+
`/dsh-continuity/bc.json?sessionId=<id>`:
|
|
266
|
+
|
|
267
|
+
```text
|
|
268
|
+
enabled persona -> available with that session's A/B/C/K
|
|
269
|
+
disabled -> persona-disabled
|
|
270
|
+
unknown -> bc-index not found
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The client reads `sessionId` from slot props. On `persona-disabled`, it closes
|
|
274
|
+
the tab. The panel is read-only and never compacts.
|
|
275
|
+
|
|
276
|
+
## 9. Peer
|
|
277
|
+
|
|
278
|
+
```text
|
|
279
|
+
peer_message({ to, text, from? })
|
|
280
|
+
POST /dsh-continuity/peer
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`to` must be an exact live session id. No newest/active fallback.
|
|
284
|
+
|
|
285
|
+
## 10. Isolation guard
|
|
286
|
+
|
|
287
|
+
The host registers a best-effort `tools.guard`:
|
|
288
|
+
|
|
289
|
+
```text
|
|
290
|
+
each session may touch only its own sessions/<id>/ directory
|
|
291
|
+
another session's continuity files are denied
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
This is not an OS boundary. Arbitrary code with full access can bypass it;
|
|
295
|
+
strong isolation needs ACL/container. The guard exists to stop normal
|
|
296
|
+
edit/write/shell tools from crossing sessions.
|
|
297
|
+
|
|
298
|
+
## 11. Injection prefixes
|
|
299
|
+
|
|
300
|
+
```text
|
|
301
|
+
[continuity:boot] onboarding
|
|
302
|
+
[continuity:audit] audit suggestion
|
|
303
|
+
[continuity:fold] pass receipt
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Plugin-injected `role=user` messages start with `[continuity:*]`.
|
|
307
|
+
`[追忆]` is a recall tool result.
|
|
308
|
+
|
|
309
|
+
## 12. Code map
|
|
310
|
+
|
|
311
|
+
```text
|
|
312
|
+
src/index.mjs host routes, panel, guard install
|
|
313
|
+
src/engine.mjs compaction, pass receipt, fold record
|
|
314
|
+
src/state.mjs passes, dropped-ranges
|
|
315
|
+
src/policy.mjs band math
|
|
316
|
+
src/recall-tool.mjs A/B/C/K retrieval
|
|
317
|
+
src/memory/bc-pre-step.mjs per-session dispatcher
|
|
318
|
+
src/memory/bc-index.mjs JSONL codec
|
|
319
|
+
src/memory/bc-index-updater.mjs turn labelling
|
|
320
|
+
src/memory/bc-panel-state.mjs panel projection
|
|
321
|
+
src/memory/concepts-file.mjs A parser (kind)
|
|
322
|
+
src/memory/persona.mjs identity/enable/session paths
|
|
323
|
+
src/memory/onboarding.mjs boot marker/scaffolds
|
|
324
|
+
src/memory/bc-audit.mjs audit + hint
|
|
325
|
+
src/threads-store.mjs per-session rules/habits
|
|
326
|
+
src/folds-store.mjs folds.json
|
|
327
|
+
src/session-guard.mjs best-effort tool path guard
|
|
328
|
+
client.js right tab
|
|
329
|
+
cordis.patch.yml bundle patch
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
## 13. Authoritative layout
|
|
333
|
+
|
|
334
|
+
`docs/SESSION-LAYOUT.md` is the authoritative path/permission matrix:
|
|
335
|
+
|
|
336
|
+
```text
|
|
337
|
+
sessions/<id>/ one complete set per session
|
|
338
|
+
personas/ deprecated archive; persona.json enable only
|
|
339
|
+
global folds/passes engine-owned
|
|
340
|
+
model tools own session dir + workspace only
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## 14. Invariants
|
|
344
|
+
|
|
345
|
+
```text
|
|
346
|
+
Every session owns A/B/C/K/rules/habits/index.
|
|
347
|
+
No cross-session vocabulary or rules inheritance.
|
|
348
|
+
A topic browse excludes workflow by default.
|
|
349
|
+
A candidate is not a fact.
|
|
350
|
+
[gist] is reconstruction, not verbatim.
|
|
351
|
+
A pass receipt is append-only.
|
|
352
|
+
floor(T) depends on the current baseline.
|
|
353
|
+
No extra prompt-classification/tagging/workline layer in safe mode.
|
|
354
|
+
Tool guard is not an OS security boundary.
|
|
355
|
+
```
|
package/docs/CACHE.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Cache-first context maintenance
|
|
2
|
+
|
|
3
|
+
> **Historical.** 当前 band/floor 行为以 `docs/ARCHITECTURE.md` 和 `src/policy.mjs` 为准;本文的旧数字/策略不作当前契约。
|
|
4
|
+
|
|
5
|
+
The goal is not “small drops”; it is **few prefix rewrites**. This note explains why, measures the
|
|
6
|
+
current Continuity session, and records the policy that follows from it.
|
|
7
|
+
|
|
8
|
+
## 1. Why every compaction invalidates the suffix
|
|
9
|
+
|
|
10
|
+
The provider's prompt cache is prefix-addressed: a request is a hit only up to the first token that
|
|
11
|
+
differs from a cached request. A compaction replaces an old span with one summary user message at
|
|
12
|
+
the **start** of that span. Everything before the span (system prompt, tool schemas) is unchanged;
|
|
13
|
+
everything after the replacement now has a different prefix, so the entire suffix misses on the
|
|
14
|
+
next request and must be re-read/re-cached.
|
|
15
|
+
|
|
16
|
+
Therefore:
|
|
17
|
+
|
|
18
|
+
- **Pass count is the cost**, not pass size. Twenty 4k passes invalidate twenty times; one 190k
|
|
19
|
+
pass invalidates once.
|
|
20
|
+
- A small pass is the worst case: it removes little but still pays a full suffix re-read.
|
|
21
|
+
- Compaction cannot be made cache-transparent while it removes surface nodes. The only lever is to
|
|
22
|
+
do it rarely and do enough at once.
|
|
23
|
+
|
|
24
|
+
## 2. Measured evidence from the Continuity session
|
|
25
|
+
|
|
26
|
+
Session `session-0b094f6e-8a4b-4c61-9ce8-0aec316c57b3` (preset `continuity`, log decoded read-only):
|
|
27
|
+
|
|
28
|
+
| Metric | Value |
|
|
29
|
+
|---|---:|
|
|
30
|
+
| summary compactions | **53** |
|
|
31
|
+
| total shadowed tokens | **698,108** |
|
|
32
|
+
| average pass | 13,172 |
|
|
33
|
+
| largest pass | 100,725 |
|
|
34
|
+
| one-node passes | 34 |
|
|
35
|
+
| passes under 10k | 47 |
|
|
36
|
+
| passes 50k–150k | 6 |
|
|
37
|
+
|
|
38
|
+
The old policy (`setpoint 0.65 / high 0.80 / low 0.55 / maxPerBatch 8k / minAction 4k`) capped every
|
|
39
|
+
high pass at 8k. Draining from 80% to 55% is ~198k, so it took ~24 passes — and because the selector
|
|
40
|
+
stops before a node that would exceed the budget, many passes removed a single ~3.4k node. That is
|
|
41
|
+
the 21 “band-high single message” passes plus emergencies.
|
|
42
|
+
|
|
43
|
+
The cache cost is visible in the provider usage of two adjacent requests:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
request A: inputTokens 659 cacheReadTokens 733,184 (99.91% cached)
|
|
47
|
+
... compaction (one 4k node + summary) ...
|
|
48
|
+
request B: inputTokens 733,414 cacheReadTokens 8,704 (1.2% cached)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A 4k-token reduction forced a **733k-token prefix re-read**. This is why lifetime cache hit rate is
|
|
52
|
+
the wrong metric: 53 such events dilute it. Look at the per-request `cacheReadTokens` between two
|
|
53
|
+
compactions instead.
|
|
54
|
+
|
|
55
|
+
## 3. The policy that follows
|
|
56
|
+
|
|
57
|
+
`src/policy.mjs` now exports `CACHE_FIRST_POLICY` (the default), with `W = messageBudget`:
|
|
58
|
+
|
|
59
|
+
| Field | Value | Tokens at W = 792,576 |
|
|
60
|
+
|---|---:|---:|
|
|
61
|
+
| `setpoint` | 0.60 | 475,546 |
|
|
62
|
+
| `high` | 0.60 | 475,546 |
|
|
63
|
+
| `low` | 0.40 | 317,030 |
|
|
64
|
+
| `emergency` | 0.65 | 515,174 |
|
|
65
|
+
| `emergencyTo` | 0.42 | 332,882 |
|
|
66
|
+
| `maxPerBatch` | 190,000 | — |
|
|
67
|
+
| `minAction` | 24,000 | — |
|
|
68
|
+
| `protect` | 0.30 | 237,773 |
|
|
69
|
+
|
|
70
|
+
`setpoint` **equals** `high` on purpose. Above high, one pass computes
|
|
71
|
+
`est − low × W` (≈158k at the crossing) and the 190k cap lets it land at low. The context then
|
|
72
|
+
swings between 40% and 60%; there are no 24k proportional passes in between. The optional
|
|
73
|
+
`CACHE_GRADUAL_POLICY` keeps `setpoint 0.50` for a smoother average context, but every 24k pass it
|
|
74
|
+
adds is another prefix invalidation.
|
|
75
|
+
|
|
76
|
+
`emergencyTo` is **below high** on purpose. With the old 0.88, a 97% overshoot emergency-landed at
|
|
77
|
+
88% (697,467), still above high, so the next batch immediately ran a second band-high pass: two
|
|
78
|
+
prefix invalidations for one overshoot. 0.2.7 lands at 42% (332,882), leaving 18 percentage points
|
|
79
|
+
below high 60% (475,546); exactly 65% still takes one band-high, and >65% takes one emergency.
|
|
80
|
+
|
|
81
|
+
Expected pass count for the same 698,108 tokens removed:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
698,108 / 158,515 ≈ 4.4 → 5 passes
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
That is the 53 → 5 reduction, without shrinking the protected tail or touching the raw archive.
|
|
88
|
+
|
|
89
|
+
### What stays fixed
|
|
90
|
+
|
|
91
|
+
- **system + tools prefix**: never compacted; the engine starts at the oldest non-system node.
|
|
92
|
+
- **protected tail**: 30% of W (237,773) is never folded; the low water mark (62%) is above it.
|
|
93
|
+
- **gist pointer / raw archive**: the summary still carries
|
|
94
|
+
`[gist · log:<session>#seq=<start>-<end> · N messages · original retrievable]`; the original log
|
|
95
|
+
events remain at those seqs.
|
|
96
|
+
|
|
97
|
+
### What it costs
|
|
98
|
+
|
|
99
|
+
- One large summarization call per pass (~190k input, a few k output).
|
|
100
|
+
- The context oscillates over a 24% band instead of hovering near a setpoint.
|
|
101
|
+
- The first request after a pass is a cache miss from the replacement onward; later requests hit
|
|
102
|
+
again. The win is fewer such first requests.
|
|
103
|
+
|
|
104
|
+
## 4. How to verify
|
|
105
|
+
|
|
106
|
+
1. In the Web UI's performance usage, read per-request `cacheReadTokens` / `inputTokens`; do not
|
|
107
|
+
compare lifetime percentages.
|
|
108
|
+
2. A pass is followed by one low-hit request; subsequent requests should return to high hits.
|
|
109
|
+
3. The Continuity panel's “Recent passes” list records each pass (range, tokens, reason, time).
|
|
110
|
+
Compare the interval between passes before/after the policy change.
|
|
111
|
+
4. The expected signal: pass count drops from ~53 to ~4 for the same session growth; the total
|
|
112
|
+
tokens removed stays similar.
|
|
113
|
+
|
|
114
|
+
## 5. Applying it to a live session
|
|
115
|
+
|
|
116
|
+
The policy is read when the engine mounts. An already-running session keeps the revision it started
|
|
117
|
+
with, so either:
|
|
118
|
+
|
|
119
|
+
- restart DSH and resume the Continuity session with the updated preset (`preset-continuity` pins
|
|
120
|
+
`setpoint 0.86` and inherits the rest of `CACHE_FIRST_POLICY`), or
|
|
121
|
+
- fork the session; the child mounts the current preset and inherits the history, or
|
|
122
|
+
- remount the bundle. In this run a plugin-manager `set_plugin` toggle remounted the preset and
|
|
123
|
+
applied the pinned cache-first policy live at 18:27:37 (`engine.policy` 0.86/0.86/0.62,
|
|
124
|
+
190000/24000/0.30). The JS-module cache still means a full restart is needed for code-only
|
|
125
|
+
changes such as the cold-start route fix.
|
|
126
|
+
|
|
127
|
+
The parent session's 53 old summaries remain as gists; the next high crossing under the new policy
|
|
128
|
+
is the first large drain. Its pass record (reason `band-high`, budget 190000) is the first
|
|
129
|
+
cache-first observation.
|
|
130
|
+
|
|
131
|
+
## A4/B in 0.2.4
|
|
132
|
+
|
|
133
|
+
A4-safe previews only old, non-active `tool/result` text as the first stage of a compression whose
|
|
134
|
+
target is **low 62%** (`emergencyTo` 80% for an emergency), not merely `high` 86%. If the preview
|
|
135
|
+
cannot cover the whole gap it is still applied, and the remaining pass continues to the target even
|
|
136
|
+
when the estimate is already below high. This is deliberately different from 0.2.2, which stopped
|
|
137
|
+
after previewing to high: that left the context hovering at 86% and caused the repeated prefix
|
|
138
|
+
invalidations the 190k band is meant to avoid. One high crossing now produces one 24%-W band; the
|
|
139
|
+
oldest user/reasoning is folded only when the tool previews cannot reach 62%, and active pins stay
|
|
140
|
+
full. The summary-view (B) preview changes only the summarization input, never the surface or cache.
|
|
141
|
+
|
|
142
|
+
0.2.4 adds a 3-turn active window (old unmatched calls no longer pin), non-text handles that keep
|
|
143
|
+
the payload out of the main context (one optional auxiliary semantic call; deterministic fallback),
|
|
144
|
+
and an overflow-only active pause. The pause is the only path that can detach an active result; it
|
|
145
|
+
does so only when that result is large enough to explain the measured overage. Raw stats may
|
|
146
|
+
double-count summary + replacement; that overlap is archive-only, not context.
|
|
147
|
+
|
|
148
|
+
0.2.5 adds no policy change. It makes A4 skip `[tool result handle]` / `[continuity pause]` /
|
|
149
|
+
existing previews (no second preview of a handle), measures the surface after each pass and records
|
|
150
|
+
`afterTokens`/`afterSurfaceTokens`/`rebloatTokens`, and labels a manual `/compact` with a gist header
|
|
151
|
+
plus a `manual` pass record. The manual cut remains the base command's depth.
|
|
152
|
+
|
|
153
|
+
0.2.6 introduced the 515k hard cap. 0.2.7 tunes the ratio to high 0.60 (475,546; 45.4% full),
|
|
154
|
+
low 0.40 (317,030; 30.2%), emergency 0.65 (515,174; 49.1% full) → emergencyTo 0.42 (332,882; 31.8%).
|
|
155
|
+
The high→emergency gap is 5% W (39,628), above `minAction` 24k; 0.62/0.65 was only 3% (23,777), below
|
|
156
|
+
it. `emergencyTo` is below high, so it cannot chain into band-high. `protect`, `maxPerBatch`, and
|
|
157
|
+
`minAction` are unchanged.
|
|
158
|
+
|
|
159
|
+
0.3.0 adds threads without changing the band policy. The active/rules line is a `user/message`
|
|
160
|
+
appended after the surface tail once per turn; it is never part of the system/tool prefix, so the
|
|
161
|
+
static cache prefix is unchanged. The active thread's `loadSeq` is a hard pin: `oldestRange()` uses
|
|
162
|
+
it as the tail floor, so automatic compaction cannot fold the loaded quote. A save clears
|
|
163
|
+
`activeId`; the old quote becomes foldable. Save/load commits are deferred to the next pre-step,
|
|
164
|
+
outside the tool call/result pair.
|
|
165
|
+
|
|
166
|
+
0.3.1 changes injected messages to `source: { kind: "user" }`. The v4 format rejects an
|
|
167
|
+
unregistered `plugin` source kind; the line/load/manual/semantic messages are context, not
|
|
168
|
+
compaction checkpoints, so `user` is the correct producer-owned kind. The gist replacement keeps the
|
|
169
|
+
base `compact` checkpoint source.
|
|
170
|
+
|
|
171
|
+
0.3.2 moves that to `{ kind: "runtime-context", form: "snapshot", sections: [...] }`, which v4
|
|
172
|
+
accepts and the UI renders as a context block rather than a human message. It also removes the
|
|
173
|
+
post-gist `compaction/prune`; the summary's own `shadowedTokenCount` is the price, and a prune after
|
|
174
|
+
the replacement names a shadowed span. No post-replacement prune means no v4 surface corruption.
|
|
175
|
+
|
|
176
|
+
0.3.3 keeps one injection per turn (not per step) and prefixes the rules with an attribution:
|
|
177
|
+
they are the instance's own `rules.md`, not a new user instruction or system requirement, and may
|
|
178
|
+
be ignored or rewritten. The block is appended after the tail; the static prefix is unchanged.
|
|
179
|
+
|
|
180
|
+
0.3.4 adds `thread.segments[]` and optional `save.threadId`. Append is explicit: the engine never
|
|
181
|
+
guesses affinity. `list`/`active` display `segments`/`lastAt`; load quotes the latest segment with
|
|
182
|
+
`第N/M段`; old one-range state normalizes on read and is rewritten with segments on the next write.
|
|
183
|
+
Thread-level totals/`next` follow the latest segment, so the active line and load header stay small.
|
|
184
|
+
|
|
185
|
+
0.3.5 adds `scan` (read-only, non-injecting, reasoning-free heads, synthetic context skipped, <900
|
|
186
|
+
token payload) and range/select load (`fromSeq`/`toSeq`, `select`, `segs`). The static prefix is
|
|
187
|
+
untouched; scan writes nothing and load still queues its quote for the next pre-step.
|
|
188
|
+
|
|
189
|
+
0.3.6 adds the `tags.json` sidecar (overrides → last run → T0), find/tag/retag/tags, scan-by-seqs,
|
|
190
|
+
and tag/seqs load (earliest 3 + latest 5, `segs`). No `[TX]` enters the raw log; the auto-tagger
|
|
191
|
+
writes one run per completed turn into the sidecar only.
|
|
192
|
+
|
|
193
|
+
0.3.7 keeps active only for thread loads; tag/seqs loads append a quote without moving `[线]`.
|
|
194
|
+
find(T0) returns complement ranges; find bounds are strict; tags() carries display/count/active;
|
|
195
|
+
tag accepts a label; receipts dedupe the display name; updatedAt advances.
|
|
196
|
+
|
|
197
|
+
0.3.8 tag ranges append one run instead of hundreds of overrides; find exposes coverage
|
|
198
|
+
ranges/covered; untag writes a T0 run and clears overrides in the interval. No auto-merge, no raw
|
|
199
|
+
change, no save change.
|
|
200
|
+
|
|
201
|
+
0.3.9 tags() rows split entries (runs+overrides) from events (actual resolved coverage); count is
|
|
202
|
+
an alias of events. The coverage pass uses max(session seq, runs, overrides); no other behavior changes.
|
|
203
|
+
|
|
204
|
+
0.4.0 adds T= to gist headers, folds.json visible/folded plus load annotation, thread aliases,
|
|
205
|
+
generated tags.md with keywords, tag load first/last, and a slim [标签]/[习惯] per-turn block. No
|
|
206
|
+
save/load segment semantics changed.
|
|
207
|
+
|
|
208
|
+
0.4.1 allows tag metadata-only (label/keywords/alias), tag alias sets the matching thread alias,
|
|
209
|
+
tags() display uses alias first. find(T0) remains the full complement.
|
|
210
|
+
|
|
211
|
+
0.4.2 unifies T0: tags().T0.events is the complement and equals find(T0).count; other tags match
|
|
212
|
+
find().covered; tags.md uses the same. Gist T= uses display, omits T0 unless all T0, max 3 plus +N.
|
|
213
|
+
|
|
214
|
+
0.4.3 treats alias as display only: auto/find/load/tag writes use canonical thread id, alias resolves,
|
|
215
|
+
and alias-named tags migrate into the canonical tag. find count = total coverage (incl folded), seqs =
|
|
216
|
+
page, covered = count.
|
|
217
|
+
|
|
218
|
+
0.4.4 default save clamps its start to the current T run start (explicit from/to untouched); gist T
|
|
219
|
+
is primary display + secondary non-T0 event count, e.g. T3 +2; no multi-tag list.
|
|
220
|
+
|
|
221
|
+
0.4.5 replaces the run start with a dominance block (own runs join; other-T islands <=5 cross; larger
|
|
222
|
+
other stops). Default save appends to the thread bound to the current T; a new non-T0 thread inherits
|
|
223
|
+
the current T alias and is active.
|
|
224
|
+
|
|
225
|
+
0.4.6 load withReasoning: chronological body + paired reasoning, one 16k budget, 800-token reasoning
|
|
226
|
+
truncated to 150 head + 650 tail, receipt reasoningInjected/reasoningTokens/skipped. Default 8k load,
|
|
227
|
+
gist, and scan unchanged.
|
|
228
|
+
|
|
229
|
+
0.4.7 adds explicit delete with deleted/ backup, header segment/token/activity counts, save relabel
|
|
230
|
+
protection, tag/retag alias id resolution with unknown-tag-id, and drops zero-event tags.md rows.
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
package/docs/CONDUCT.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 基本守则(CONDUCT)
|
|
2
|
+
|
|
3
|
+
> 这是给**新实例**的最小守则,不是完整规则。完整规则见 `rules.md`,那份是长出来的,不必照抄。
|
|
4
|
+
> 引擎会在头里给提示;**提示里带命令的,照命令做**。守则只写“为什么”和“哪条不能省”。
|
|
5
|
+
|
|
6
|
+
## 不可省的五条
|
|
7
|
+
|
|
8
|
+
1. **每条内容必须被判过**:贴标签,或显式判 `T0`。没有“还没轮到”——`save` 会因未决拒绝。
|
|
9
|
+
2. **每轮一个标**:`turnmap.mjs set --turn N --tag Tx`。轮是检索单位,标签是 turn ↔ seq ↔ T 的桥。
|
|
10
|
+
3. **不猜**:不确定属于哪个话题,先 `match-tags.mjs "<原话>"` 查表;查不到再判 T0 或建新标签(要带证据)。
|
|
11
|
+
4. **改代码:先判据,后改,再验**。同一处改到第三版就停下,先搜文献、先写“怎么算改好”。
|
|
12
|
+
5. **不可逆动作先问**(删除、覆盖、重置、重启);可逆的(切线、收段)自己决定,做完报一句。
|
|
13
|
+
|
|
14
|
+
## 别做的三件
|
|
15
|
+
|
|
16
|
+
- **别把痕迹当状态**:记“当时注意力朝哪”,不写“我当时很难过”,也不许事后补写。
|
|
17
|
+
- **别让结论只靠用户的话**:只有陈述支撑的结论标「待验证」,重要结论留 `basis`。
|
|
18
|
+
- **别为了省钱跳过检查**:验一次比返工便宜;闸拒绝时先看它列出的清单,别硬折。
|
|
19
|
+
|
|
20
|
+
## 引擎会替你做的(不用背)
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
头里注入:当前线 / 标签 / 上次段 / 下一步
|
|
24
|
+
每轮:自动归位(唯一命中就贴)
|
|
25
|
+
漏标:下一轮出现 [打标?]
|
|
26
|
+
换话题:出现 [话题?](先 kw-audit explain 再决定)
|
|
27
|
+
save 时:T0 闸 / 标签闸 / tags-gap 闸 / C7 闸
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**闸不是敌人**:它拒绝时给出的清单,就是“该补的账”。
|