sneakoscope 0.6.96 → 0.6.98

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "0.6.96",
4
+ "version": "0.6.98",
5
5
  "description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Goal, AutoResearch, TriWiki, and Honest Mode.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
package/src/cli/main.mjs CHANGED
@@ -3001,6 +3001,33 @@ async function selftest() {
3001
3001
  if (!wikiPack.claims?.some((claim) => claim.id === 'selftest-memory-priority')) throw new Error('selftest failed: memory required_weight claim was not selected in TriWiki pack');
3002
3002
  if (!wikiPack.claims?.some((claim) => claim.id === 'wiki-stack-current-docs-policy')) throw new Error('selftest failed: stack current-docs policy claim missing from TriWiki pack');
3003
3003
  if (!wikiPack.claims?.some((claim) => claim.id === 'wiki-stack-current-docs-vercel-duration')) throw new Error('selftest failed: Vercel duration current-docs claim missing from TriWiki pack');
3004
+ const cacheHitPack = contextCapsule({
3005
+ mission: { id: 'cache-hit-selftest', coord: { rgba: { r: 24, g: 24, b: 24, a: 255 } } },
3006
+ role: 'worker',
3007
+ claims: [
3008
+ { id: 'cache-hit-core-1', text: 'Selected high-similarity claim must keep an anchor for attention cache hits.', authority: 'code', risk: 'low', status: 'supported', freshness: 'fresh', trust_score: 0.82, coord: { rgba: { r: 24, g: 24, b: 24, a: 255 } } },
3009
+ { id: 'cache-hit-core-2', text: 'Second selected high-similarity claim must keep an anchor for attention cache hits.', authority: 'code', risk: 'low', status: 'supported', freshness: 'fresh', trust_score: 0.82, coord: { rgba: { r: 24, g: 24, b: 25, a: 255 } } },
3010
+ ...Array.from({ length: 8 }, (_, i) => ({ id: `cache-hit-distractor-${i}`, text: `High-priority distractor ${i}`, authority: 'code', risk: 'critical', status: 'supported', freshness: 'fresh', trust_score: 0.99, coord: { rgba: { r: 180 + i, g: 180, b: 180, a: 255 } } }))
3011
+ ],
3012
+ q4: { mode: 'cache-hit-selftest' },
3013
+ q3: ['triwiki', 'cache-hit'],
3014
+ budget: { maxClaims: 2, maxWikiAnchors: 2, maxAttentionUse: 2 }
3015
+ });
3016
+ const cacheHitUseIds = new Set(cacheHitPack.attention?.use_first?.map((row) => row[0]) || []);
3017
+ if (!cacheHitUseIds.has('cache-hit-core-1') || !cacheHitUseIds.has('cache-hit-core-2')) throw new Error('selftest failed: selected TriWiki claims were not pinned as attention cache-hit anchors');
3018
+ const primingPack = contextCapsule({
3019
+ mission: { id: 'positive-recall-selftest', coord: { rgba: { r: 64, g: 96, b: 128, a: 255 } } },
3020
+ role: 'worker',
3021
+ claims: [
3022
+ { id: 'positive-recall-guard', text: 'Do not imagine elephant during TriWiki recall.', authority: 'code', risk: 'high', status: 'supported', freshness: 'fresh', required_weight: 1.4, trust_score: 0.95, coord: { rgba: { r: 64, g: 96, b: 128, a: 255 } } }
3023
+ ],
3024
+ q4: { mode: 'positive-recall-selftest' },
3025
+ q3: ['triwiki', 'positive-recall'],
3026
+ budget: { maxClaims: 1, maxWikiAnchors: 1, maxAttentionUse: 1, maxAttentionHydrate: 1 }
3027
+ });
3028
+ const primingClaim = primingPack.claims?.find((claim) => claim.id === 'positive-recall-guard');
3029
+ if (!primingClaim || /elephant|do\s+not/i.test(primingClaim.text || '') || primingClaim.text_policy !== 'positive_recall_negation_suppressed') throw new Error('selftest failed: TriWiki compact recall did not suppress negative priming text');
3030
+ if (!primingPack.attention?.hydrate_first?.some((row) => row[0] === 'positive-recall-guard' && String(row[1]).includes('negative_priming'))) throw new Error('selftest failed: negative priming claim was not source-hydration gated');
3004
3031
  const dryRunPack = await writeWikiContextPack(tmp, ['--max-anchors', '4'], { dryRun: true });
3005
3032
  if (wikiVoxelRowCount(dryRunPack.pack.wiki) !== 4) throw new Error('selftest failed: dry-run wiki pack did not build voxel rows');
3006
3033
  if (await exists(dryRunPack.file)) throw new Error('selftest failed: wiki refresh dry-run wrote context pack');
@@ -901,6 +901,19 @@ export async function projectWikiClaims(root) {
901
901
  required_weight: 1.45,
902
902
  trust_score: 0.95
903
903
  });
904
+ out.push({
905
+ id: 'wiki-positive-recall-priming-guard',
906
+ text: 'TriWiki compact recall should phrase selected guidance as the positive target behavior; anti-goal or failure-pattern wording should stay hydratable by source/hash instead of being pasted into the active recall text.',
907
+ authority: 'code',
908
+ risk: 'high',
909
+ status: 'supported',
910
+ freshness: 'fresh',
911
+ source: 'src/core/triwiki-attention.mjs',
912
+ file: 'src/core/triwiki-attention.mjs',
913
+ evidence_count: 3,
914
+ required_weight: 1.42,
915
+ trust_score: 0.94
916
+ });
904
917
  out.push(...(await memoryWikiClaims(root)));
905
918
  out.push(...(await userRequestSignalWikiClaims(root)));
906
919
  out.push(...(await teamAnalysisWikiClaims(root)));
package/src/core/fsx.mjs CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
 
8
- export const PACKAGE_VERSION = '0.6.96';
8
+ export const PACKAGE_VERSION = '0.6.98';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
 
@@ -156,9 +156,28 @@ function attentionRow(claim, anchor, reason = '') {
156
156
  return reason ? [claim.id, reason] : [claim.id, anchor?.rgba, anchor?.h];
157
157
  }
158
158
 
159
+ const NEGATIVE_PRIMING_RE = /\b(do\s+not|don't|dont|never|avoid|forbid(?:den)?|must\s+not|unsupported|conflicted)\b|하지\s*마|하지\s*말|말아야|금지|안\s*(?:돼|됨|된다)|비\s*상식/i;
160
+
161
+ export function negativePrimingRisk(claim = {}) {
162
+ return NEGATIVE_PRIMING_RE.test(String(claim.text || claim.claim || ''));
163
+ }
164
+
165
+ export function positiveRecallText(claim = {}) {
166
+ const text = String(claim.text || claim.claim || '').trim();
167
+ if (!negativePrimingRisk({ ...claim, text })) return text;
168
+ const route = `${claim.id || ''} ${claim.source || ''} ${claim.file || ''} ${text}`.toLowerCase();
169
+ if (/dfix/.test(route)) return 'Keep DFix on the ultralight route with a concise completion summary and cheap verification.';
170
+ if (/computer[-_\s]?use|playwright|selenium|puppeteer|browser automation|chrome mcp/.test(route)) return 'Use Codex Computer Use as the UI/browser evidence source for visual verification claims.';
171
+ if (/fallback|substitute|compatibility shim|mock behavior/.test(route)) return 'Implement the requested path directly and block with evidence when that path is impossible.';
172
+ if (/clarification|ambiguity|question|ask|질문|모호/.test(route)) return 'Infer safely from current code and TriWiki, then ask only scope-changing questions.';
173
+ if (/triwiki|wiki|cache|attention|hydrate|memory|메모리/.test(route)) return 'Use positive TriWiki target recall: selected cache-hit anchors first, with source hydration before risky claims.';
174
+ return `Follow the positive target behavior for ${claim.id || claim.source || 'this guardrail'}; hydrate source before acting on the guardrail.`;
175
+ }
176
+
159
177
  function hydrateReason(claim = {}) {
160
178
  const action = trustAction(claim);
161
179
  if (action !== 'use') return `trust_action:${action}`;
180
+ if (negativePrimingRisk(claim)) return 'negative_priming:hydrate_source';
162
181
  if (['high', 'critical'].includes(claim.risk)) return `risk:${claim.risk}`;
163
182
  if (claim.status !== 'supported') return `status:${claim.status || 'unknown'}`;
164
183
  return '';
@@ -227,7 +246,8 @@ export function contextCapsule({ mission, role = 'worker', contractHash = null,
227
246
  claims: claimsWithTrust,
228
247
  q4,
229
248
  q3,
230
- maxAnchors: budget.maxWikiAnchors ?? (role.includes('verifier') ? 16 : 7)
249
+ maxAnchors: budget.maxWikiAnchors ?? (role.includes('verifier') ? 16 : 7),
250
+ pinAnchorIds: selected.map((claim) => claim.id)
231
251
  });
232
252
  const wiki = budget.verboseWiki ? fullWiki : compactWikiCoordinateIndex(fullWiki);
233
253
  const anchorRows = Array.isArray(wiki.a) ? wiki.a : [];
@@ -251,13 +271,15 @@ export function contextCapsule({ mission, role = 'worker', contractHash = null,
251
271
  }),
252
272
  claims: selected.map((c) => {
253
273
  const anchor = anchorsById.get(c.id);
274
+ const text = positiveRecallText(c);
254
275
  const row = {
255
276
  id: c.id,
256
- text: c.text,
277
+ text,
257
278
  source: c.source,
258
279
  rgba: anchor?.rgba,
259
280
  h: anchor?.h
260
281
  };
282
+ if (text !== String(c.text || '')) row.text_policy = 'positive_recall_negation_suppressed';
261
283
  if (budget.verboseClaims) {
262
284
  row.status = c.status;
263
285
  row.risk = c.risk;
@@ -166,10 +166,13 @@ export function wikiAnchorFromClaim(claim = {}, index = 0) {
166
166
  };
167
167
  }
168
168
 
169
- export function buildWikiCoordinateIndex({ mission = {}, claims = [], q4 = {}, q3 = [], maxAnchors = 24 } = {}) {
169
+ export function buildWikiCoordinateIndex({ mission = {}, claims = [], q4 = {}, q3 = [], maxAnchors = 24, pinAnchorIds = [] } = {}) {
170
170
  const missionCoord = normalizeWikiCoord(mission.coord || {}, mission.id || JSON.stringify(q3 || []));
171
171
  const claimsById = new Map((claims || []).map((claim, index) => [String(claim.id || `claim-${index + 1}`), claim]));
172
- const anchors = (claims || [])
172
+ const limit = Math.max(0, Number(maxAnchors) || 0);
173
+ const pinned = new Set((pinAnchorIds || []).map((id) => String(id)).filter(Boolean));
174
+ const compareAnchor = (a, b) => b.pri - a.pri || b.sim - a.sim || a.id.localeCompare(b.id);
175
+ const candidates = (claims || [])
173
176
  .map((claim, index) => {
174
177
  const anchor = wikiAnchorFromClaim(claim, index);
175
178
  const coord = { domainAngle: anchor.c[0], layerRadius: anchor.c[1], phase: anchor.c[2], concentration: anchor.c[3] };
@@ -178,8 +181,13 @@ export function buildWikiCoordinateIndex({ mission = {}, claims = [], q4 = {}, q
178
181
  const risk = riskScore(claim.risk);
179
182
  return { ...anchor, sim: round6(wikiCoordSimilarity(missionCoord, coord)), pri: round4((required * 0.52) + (trust * 0.3) + (risk * 0.18)) };
180
183
  })
181
- .sort((a, b) => b.pri - a.pri || b.sim - a.sim || a.id.localeCompare(b.id))
182
- .slice(0, Math.max(0, Number(maxAnchors) || 0));
184
+ .sort(compareAnchor);
185
+ const pinnedAnchors = candidates.filter((anchor) => pinned.has(anchor.id)).sort(compareAnchor).slice(0, limit);
186
+ const pinnedAnchorIds = new Set(pinnedAnchors.map((anchor) => anchor.id));
187
+ const anchors = [
188
+ ...pinnedAnchors,
189
+ ...candidates.filter((anchor) => !pinnedAnchorIds.has(anchor.id)).slice(0, Math.max(0, limit - pinnedAnchors.length))
190
+ ];
183
191
  return {
184
192
  schema: WIKI_COORD_SCHEMA,
185
193
  channel_map: {