vouchington-tooling 0.12.4 → 0.13.1

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/README.md CHANGED
@@ -152,6 +152,10 @@ import {
152
152
  checkHarnessConfig,
153
153
  dumpHarnessPolicy,
154
154
  } from 'vouchington-tooling/agent-harness-config'
155
+ import {
156
+ inspectHarnessEnvironment,
157
+ selectHarnessSession,
158
+ } from 'vouchington-tooling/agent-harness-identity'
155
159
  import {
156
160
  readVitestReportAttempts,
157
161
  writeVitestBlobManifest,
@@ -246,6 +250,10 @@ classifier stays available in plan mode; its defined sandbox profile still requi
246
250
  `unrestricted` disables the sandbox. Repo checks surface user-level trust or mode prerequisites
247
251
  instead of claiming that repo files alone activate them.
248
252
 
253
+ `agent-harness-identity` inspects the four harness environment signals without choosing a winner.
254
+ Callers supply their own precedence to `selectHarnessSession`, keeping product-specific identity
255
+ policy out of this package.
256
+
249
257
  `checkWorkspaceGatesPolicy` rejects tracked test assertions that hard-code the exact version of a
250
258
  dependency declared by a non-fixture package manifest. Assert dependency membership or placement,
251
259
  or derive a configuration or documentation package spec from that manifest instead.
@@ -1,5 +1,7 @@
1
- export declare const HARNESS_IDS: readonly ['claude', 'codex', 'grok', 'cursor'];
2
- export type HarnessId = (typeof HARNESS_IDS)[number];
1
+ import { HARNESS_IDS } from '../agent-harness-identity/index.mts';
2
+ import type { HarnessId } from '../agent-harness-identity/index.mts';
3
+ export { HARNESS_IDS };
4
+ export type { HarnessId };
3
5
  export type ApplyTarget = {
4
6
  readonly kind: 'global';
5
7
  } | {
@@ -1 +1,2 @@
1
- export const HARNESS_IDS = ['claude', 'codex', 'grok', 'cursor'];
1
+ import { HARNESS_IDS } from '../agent-harness-identity/index.mjs';
2
+ export { HARNESS_IDS };
@@ -0,0 +1,26 @@
1
+ export declare const HARNESS_IDS: readonly ['claude', 'codex', 'grok', 'cursor'];
2
+ export type HarnessId = (typeof HARNESS_IDS)[number];
3
+ export interface HarnessEnvironment {
4
+ readonly claude: {
5
+ readonly compatMode: boolean;
6
+ readonly sessionId?: string;
7
+ };
8
+ readonly codex: {
9
+ readonly sessionId?: string;
10
+ };
11
+ readonly cursor: {
12
+ readonly agentMarker: boolean;
13
+ readonly sessionId?: string;
14
+ };
15
+ readonly grok: {
16
+ readonly agentMarker: boolean;
17
+ readonly hookEvent: boolean;
18
+ readonly sessionId?: string;
19
+ };
20
+ }
21
+ export interface HarnessSessionIdentity {
22
+ readonly harness: HarnessId;
23
+ readonly sessionId: string;
24
+ }
25
+ export declare function inspectHarnessEnvironment(env?: NodeJS.ProcessEnv): HarnessEnvironment;
26
+ export declare function selectHarnessSession(environment: HarnessEnvironment, precedence: readonly HarnessId[]): HarnessSessionIdentity | undefined;
@@ -0,0 +1,30 @@
1
+ export const HARNESS_IDS = ['claude', 'codex', 'grok', 'cursor'];
2
+ function session(value) {
3
+ return value ? { sessionId: value } : {};
4
+ }
5
+ export function inspectHarnessEnvironment(env = process.env) {
6
+ return {
7
+ claude: {
8
+ compatMode: env.CLAUDECODE === '1',
9
+ ...session(env.CLAUDE_CODE_SESSION_ID),
10
+ },
11
+ codex: session(env.CODEX_THREAD_ID),
12
+ cursor: {
13
+ agentMarker: Boolean(env.CURSOR_AGENT),
14
+ ...session(env.CURSOR_SESSION_ID),
15
+ },
16
+ grok: {
17
+ agentMarker: Boolean(env.GROK_AGENT),
18
+ hookEvent: Boolean(env.GROK_HOOK_EVENT),
19
+ ...session(env.GROK_SESSION_ID),
20
+ },
21
+ };
22
+ }
23
+ export function selectHarnessSession(environment, precedence) {
24
+ for (const harness of precedence) {
25
+ const sessionId = environment[harness].sessionId;
26
+ if (sessionId)
27
+ return { harness, sessionId };
28
+ }
29
+ return undefined;
30
+ }
package/dist/index.d.mts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { linkSkill, readSkillManifest } from './skill-discovery/index.mts';
2
2
  export type { LinkSkillOptions, LinkSkillResult, SkillManifest, SkillManifestEntry, } from './skill-discovery/index.mts';
3
+ export { HARNESS_IDS, inspectHarnessEnvironment, selectHarnessSession, } from './agent-harness-identity/index.mts';
4
+ export type { HarnessEnvironment, HarnessSessionIdentity } from './agent-harness-identity/index.mts';
3
5
  export { codexChildren, codexIdentity, computeTranscriptFacts, formatTranscriptFacts, formatUnavailable, resolveTranscriptFile, runRetrospectiveTranscript, } from './retrospective-transcript/index.mts';
4
6
  export type { ResolveOptions, TokenTotals, TranscriptFacts, } from './retrospective-transcript/index.mts';
5
7
  export { runRetrospectiveFacts } from './retrospective-facts/index.mts';
@@ -13,7 +15,7 @@ export type { EphemeralListenerOptions, RunnerPortPolicy } from './runner-port-p
13
15
  export { extractAlterTableAddColumnLocations, extractCreateIndexMetadata, extractCreateTableMetadata, extractDefaultFunction, extractDropIndexMetadata, extractFuncCallArgColumnNames, extractMigrationConstraintMetadata, initSqlAst, lineOfUtf8ByteOffset, MissingSqlAstParserError, parseSql, } from './sql-ast/index.mts';
14
16
  export type { ForeignKey, SqlCreateIndexMetadata, SqlCreateTableColumn, SqlCreateTableMetadata, SqlDropIndexMetadata, SqlIndexParam, SqlMigrationConstraintMetadata, } from './sql-ast/index.mts';
15
17
  export { dollarQuoteEnd, lineOf, maskSqlQuotedText, readDollarQuoteDelimiter, readStringLiteral, splitSqlStatements, sqlFragments, stripSqlComments, } from './sql-scanner/index.mts';
16
- export { applyHarnessConfig, checkHarnessConfig, dumpHarnessPolicy, planHarnessConfig, DEFAULT_EXTRA_WRITABLE_ROOTS, HARNESS_IDS, } from './agent-harness-config/index.mts';
18
+ export { applyHarnessConfig, checkHarnessConfig, dumpHarnessPolicy, planHarnessConfig, DEFAULT_EXTRA_WRITABLE_ROOTS, } from './agent-harness-config/index.mts';
17
19
  export type { ApplyTarget, FilePlan, FileResult, HarnessApplyResult, HarnessCheckResult, HarnessConfigOptions, HarnessId, HarnessPlan, HarnessPolicyDump, JsonPatch, KeyDrift, TomlPatch, TomlValue, } from './agent-harness-config/index.mts';
18
20
  export { auditCiJobRuntime, parseWorkflowNameMatch } from './gha-runtime-audit/index.mts';
19
21
  export type { GhApiExecutor, RuntimeAuditOptions, RuntimeAuditResult, RuntimeAuditWorkflowFilter, RuntimeJobResult, RuntimeSample, } from './gha-runtime-audit/index.mts';
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable max-lines -- package entry point enumerates the supported public API. */
2
2
  export { linkSkill, readSkillManifest } from './skill-discovery/index.mjs';
3
+ export { HARNESS_IDS, inspectHarnessEnvironment, selectHarnessSession, } from './agent-harness-identity/index.mjs';
3
4
  export { codexChildren, codexIdentity, computeTranscriptFacts, formatTranscriptFacts, formatUnavailable, resolveTranscriptFile, runRetrospectiveTranscript, } from './retrospective-transcript/index.mjs';
4
5
  export { runRetrospectiveFacts } from './retrospective-facts/index.mjs';
5
6
  export { appendJournal, assertSessionId, cleanupSnapshotPartitions, partitionSnapshot, probeBlackboard, readJournal, resolveBlackboardConnection, } from './agent-blackboard/index.mjs';
@@ -7,7 +8,7 @@ export { buildSessionFrictionReport, classifyFrictionObservation, FRICTION_LOG_M
7
8
  export { EphemeralListenerAttemptsExhaustedError, isRunnerReservedPort, listenOnRunnerUnreservedEphemeralPort, loadRunnerPortPolicy, runnerPortPolicy, validateRunnerPortPolicy, } from './runner-port-policy/index.mjs';
8
9
  export { extractAlterTableAddColumnLocations, extractCreateIndexMetadata, extractCreateTableMetadata, extractDefaultFunction, extractDropIndexMetadata, extractFuncCallArgColumnNames, extractMigrationConstraintMetadata, initSqlAst, lineOfUtf8ByteOffset, MissingSqlAstParserError, parseSql, } from './sql-ast/index.mjs';
9
10
  export { dollarQuoteEnd, lineOf, maskSqlQuotedText, readDollarQuoteDelimiter, readStringLiteral, splitSqlStatements, sqlFragments, stripSqlComments, } from './sql-scanner/index.mjs';
10
- export { applyHarnessConfig, checkHarnessConfig, dumpHarnessPolicy, planHarnessConfig, DEFAULT_EXTRA_WRITABLE_ROOTS, HARNESS_IDS, } from './agent-harness-config/index.mjs';
11
+ export { applyHarnessConfig, checkHarnessConfig, dumpHarnessPolicy, planHarnessConfig, DEFAULT_EXTRA_WRITABLE_ROOTS, } from './agent-harness-config/index.mjs';
11
12
  export { auditCiJobRuntime, parseWorkflowNameMatch } from './gha-runtime-audit/index.mjs';
12
13
  export { checkGhaWorkspacePolicy } from './gha-workspace-policy/index.mjs';
13
14
  export { requireUpToDate } from './require-up-to-date/index.mjs';
@@ -2,6 +2,7 @@ import { existsSync, globSync } from 'node:fs';
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { homedir } from 'node:os';
4
4
  import { basename, dirname, join } from 'node:path';
5
+ import { inspectHarnessEnvironment, selectHarnessSession, } from '../agent-harness-identity/index.mjs';
5
6
  import { codexChildren, codexIdentity, computeCodex } from './codex.mjs';
6
7
  import { segmentCodex } from './codex-segment.mjs';
7
8
  import { computeClaude } from './claude.mjs';
@@ -28,9 +29,8 @@ export function resolveTranscriptFile(options) {
28
29
  }
29
30
  const env = options.env ?? process.env;
30
31
  const sessionId = options.sessionId ??
31
- ['CODEX_THREAD_ID', 'CLAUDE_CODE_SESSION_ID', 'CURSOR_SESSION_ID', 'GROK_SESSION_ID']
32
- .map((key) => env[key])
33
- .find(Boolean);
32
+ selectHarnessSession(inspectHarnessEnvironment(env), ['codex', 'claude', 'cursor', 'grok'])
33
+ ?.sessionId;
34
34
  if (!sessionId)
35
35
  return {
36
36
  error: 'no session id (pass --session-id or set CODEX_THREAD_ID, CLAUDE_CODE_SESSION_ID, CURSOR_SESSION_ID, or GROK_SESSION_ID)',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vouchington-tooling",
3
- "version": "0.12.4",
3
+ "version": "0.13.1",
4
4
  "description": "Vouchington CLI and extractable tooling libraries.",
5
5
  "homepage": "https://github.com/vouchington/vouchington-tooling/tree/main/packages/vouchington-tooling#readme",
6
6
  "bugs": {
@@ -33,6 +33,11 @@
33
33
  "import": "./dist/index.mjs",
34
34
  "default": "./dist/index.mjs"
35
35
  },
36
+ "./agent-harness-identity": {
37
+ "types": "./dist/agent-harness-identity/index.d.mts",
38
+ "import": "./dist/agent-harness-identity/index.mjs",
39
+ "default": "./dist/agent-harness-identity/index.mjs"
40
+ },
36
41
  "./skill-discovery": {
37
42
  "types": "./dist/skill-discovery/index.d.mts",
38
43
  "import": "./dist/skill-discovery/index.mjs",
@@ -25,16 +25,47 @@ browser_revision() {
25
25
  node -e "const fs=require('node:fs'); const file=process.argv[1]; const name=process.argv[2]; const browser=JSON.parse(fs.readFileSync(file,'utf8')).browsers.find(b => b.name === name); if (!browser) { process.stderr.write('unknown browser '+name); process.exit(1) } process.stdout.write(String(browser.revision))" "$browsers_json" "$1"
26
26
  }
27
27
 
28
+ browser_executable() {
29
+ local name="$1" dir="$2" exe
30
+ case "$name" in
31
+ chromium) exe="$dir/chrome-linux-arm64/chrome" ;;
32
+ chromium-headless-shell) exe="$dir/chrome-headless-shell-linux-arm64/chrome-headless-shell" ;;
33
+ *)
34
+ echo "::error::browser_executable: unknown browser name '$name'" >&2
35
+ return 2
36
+ ;;
37
+ esac
38
+ if [ -x "$exe" ]; then
39
+ printf '%s\n' "$exe"
40
+ return
41
+ fi
42
+
43
+ # Playwright releases before 1.63 used these archive layouts.
44
+ case "$name" in
45
+ chromium) exe="$dir/chrome-linux/chrome" ;;
46
+ chromium-headless-shell) exe="$dir/chrome-linux/headless_shell" ;;
47
+ esac
48
+ if [ -x "$exe" ]; then
49
+ printf '%s\n' "$exe"
50
+ return
51
+ fi
52
+ return 1
53
+ }
54
+
28
55
  install_browser() {
29
56
  local name="$1" archive="$2"
30
57
  local rev
31
58
  rev=$(browser_revision "$name")
32
59
  local dir="${browsers_path}/${name//-/_}-${rev}"
33
60
  local marker="${dir}/INSTALLATION_COMPLETE"
61
+ local exe
34
62
 
35
63
  if [ -f "$marker" ]; then
36
- echo "Already installed: ${name}-${rev} (cache hit)"
37
- return
64
+ if exe=$(browser_executable "$name" "$dir"); then
65
+ echo "Already installed: ${name}-${rev} (cache hit)"
66
+ return
67
+ fi
68
+ echo "Reinstalling ${name}-${rev}: cache marker exists but executable is missing"
38
69
  fi
39
70
 
40
71
  echo "Installing ${name} v${rev} via curl + system unzip"
@@ -47,17 +78,8 @@ install_browser() {
47
78
  unzip -q "$tmp" -d "$dir"
48
79
  rm -f "$tmp"
49
80
 
50
- local exe
51
- case "$name" in
52
- chromium) exe="$dir/chrome-linux/chrome" ;;
53
- chromium-headless-shell) exe="$dir/chrome-linux/headless_shell" ;;
54
- *)
55
- echo "::error::install_browser: unknown browser name '$name'"
56
- exit 1
57
- ;;
58
- esac
59
- if [ ! -x "$exe" ]; then
60
- echo "::error::Expected ${name} binary missing or not executable after extract: $exe"
81
+ if ! exe=$(browser_executable "$name" "$dir"); then
82
+ echo "::error::Expected ${name} binary missing or not executable after extract: $dir"
61
83
  exit 1
62
84
  fi
63
85