Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2a94a67
fix(worker): restore clean container build inputs
HShuM Sep 8, 2026
7e0dd1f
fix(worker): remove orphan worktree entry blocking clean checkout
HShuM Sep 8, 2026
170701d
test(worker): compare container inputs to declared runtime versions
HShuM Sep 8, 2026
65c061c
fix(worker): retain dotenv in the production image
HShuM Sep 8, 2026
beb412c
fix(deps): patch the installed paged-request HTTP client
HShuM Sep 8, 2026
86e3eb1
fix(security): remove token-bearing statistics sync logging
HShuM Sep 8, 2026
779b38f
fix(security): update the guarded SDK download dependency
HShuM Sep 8, 2026
7b7f84f
fix(security): use the patched Anthropic memory client
HShuM Sep 8, 2026
08c70fa
fix(web): finish shared code renderer migration
HShuM Sep 8, 2026
006c168
fix(web): keep copy errors readable in both themes
HShuM Sep 8, 2026
4a3c88a
fix(types): preserve generated API contracts and check the real app
HShuM Sep 8, 2026
bec25ac
fix(ci): retain app evidence after backend codegen typing fails
HShuM Sep 8, 2026
12a206a
fix(types): restore research dashboard type exports
HShuM Sep 8, 2026
e8986d1
fix(pipelines): retain owned records across access checks
HShuM Sep 8, 2026
d5eba8f
test(pipelines): run ownership isolation in CI
HShuM Sep 8, 2026
c0a066c
fix(types): restore Convex SDK contracts and honest app preflight
HShuM Sep 8, 2026
0567d63
fix(types): break circular action result inference with concrete cont…
HShuM Sep 8, 2026
92a3882
fix(types): align backend calls with registered function visibility
HShuM Sep 8, 2026
944bafd
fix(security): authenticate deletion requests and restrict workflow m…
HShuM Sep 8, 2026
db5b87a
fix(privacy): make reviewed deletions transactional and resumable
HShuM Sep 8, 2026
bfafc4f
fix(convex-mcp): honor configured projects and reject unevaluated scores
HShuM Sep 8, 2026
086bbbd
perf(convex-mcp): reuse registration patterns and function extraction
HShuM Sep 8, 2026
e8cf890
fix(telegram): secure webhook admission and restore typed storage
HShuM Sep 9, 2026
787893e
fix(agents): restore delegation registration types
HShuM Sep 9, 2026
ac984af
fix(convex): preserve typed queries while lazy references load
HShuM Sep 9, 2026
3f99082
fix: preserve owned profile and calendar preference returns
HShuM Sep 9, 2026
d8e2363
fix: restore Settings dialog slot and focus behavior
HShuM Sep 9, 2026
b803cb5
fix: keep Settings controls reachable on compact screens
HShuM Sep 9, 2026
b162b56
fix: declare finite batch and pipeline return contracts
HShuM Sep 9, 2026
527db79
fix: keep workflow event data out of executable source
HShuM Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .claude/worktrees/festive-mclaren-0555d3
Submodule festive-mclaren-0555d3 deleted from cab564
5 changes: 4 additions & 1 deletion .gcloudignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ test-agents
tmp-chrome-procs.txt
tmp-playwright-*
.npmrc
# Root .npmrc contains only the public legacy-peer-deps install policy.
!/.npmrc
.env*
!python-mcp-servers/langgraph_agent/.env
packages/mcp-local/.mcpregistry_registry_token
packages/mcp-local/.mcpregistry_github_token
3 changes: 2 additions & 1 deletion .github/workflows/attrition-qa.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ jobs:
- uses: actions/checkout@v6

- name: Crawl all surfaces
env:
BASE: ${{ github.event.inputs.api_url || 'https://scratchnode.live' }}
run: |
BASE="${{ github.event.inputs.api_url || 'https://scratchnode.live' }}"
if [[ "$BASE" == https://vercel.com/* ]]; then
BASE="https://scratchnode.live"
fi
Expand Down
49 changes: 47 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ jobs:
node-version-file: ".nvmrc"

- name: Install dependencies
id: typecheck_dependencies
run: npm install --no-audit --no-fund

- name: Convex bundle analysis (codegen)
Expand All @@ -55,8 +56,24 @@ jobs:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
run: npx convex codegen

- name: App typecheck
run: npx tsc --noEmit --pretty false
- name: Installed Convex generator contracts
if: ${{ !cancelled() && steps.typecheck_dependencies.outcome == 'success' }}
run: npm run test:convex-api-codegen

- name: App typecheck and generated API call contracts
# Codegen also typechecks the legacy backend. Keep that failure, but
# still collect the independent application result after installation.
if: ${{ !cancelled() && steps.typecheck_dependencies.outcome == 'success' }}
run: npm run typecheck:app

- name: Preserve actual application typecheck evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: app-typecheck-evidence
path: .tmp/app-typecheck/
if-no-files-found: warn
retention-days: 14

- name: Convex typecheck
run: npx tsc -p backend/convex --noEmit --pretty false
Expand All @@ -76,6 +93,9 @@ jobs:
- name: Install dependencies
run: npm install --no-audit --no-fund

- name: Workflow event data scenarios
run: node --test scripts/nodebench-packet-contracts.node.mjs

- name: Runtime smoke tests
run: >
npx vitest run
Expand All @@ -91,6 +111,21 @@ jobs:
backend/convex/domains/mcp/mcpSourcingDraft.integration.test.ts
backend/convex/domains/mcp/mcpExecutionTraceEndpoints.integration.test.ts
backend/convex/domains/agents/mcp_tools/models/modelResolver.test.ts
backend/convex/domains/pipelines/pipelineOwnership.auth.test.ts
backend/convex/domains/operations/__tests__/privacyAdmission.auth.test.ts
backend/convex/domains/operations/__tests__/privacyExecution.transactions.test.ts
backend/convex/domains/integrations/__tests__/telegramAdmission.test.ts
backend/convex/domains/agents/__tests__/delegationRegistration.test.ts
apps/web/src/lib/__tests__/convexApiQuery.test.tsx
backend/convex/domains/product/__tests__/preferencesReturnContract.test.ts
apps/web/src/lib/__tests__/preferencesReturnContract.test.tsx
apps/web/src/components/ai-ui/__tests__/sheet.test.tsx
apps/web/src/features/entities/components/EntityNotebookView.test.tsx
apps/web/src/features/entities/components/notebook/EntityNotebookLive.empty-state.test.tsx
apps/web/src/features/me/views/MeHome.test.tsx
apps/web/src/features/nudges/views/NudgesHome.test.tsx
apps/web/src/layouts/cockpitRails.test.tsx
backend/convex/domains/pipelines/pipelineTruthIsolation.test.ts
apps/web/src/features/agents/components/FastAgentPanel/__tests__/RunState.test.tsx
backend/convex/domains/agents/autonomy/autonomy.integration.test.ts
backend/convex/domains/agents/autonomy/autonomyTasteBench.integration.test.ts
Expand All @@ -108,6 +143,16 @@ jobs:
apps/web/src/features/redesign/components/UniversalComposer.test.tsx
apps/web/src/features/redesign/surfaces/ScratchnodeEventsSurface.test.tsx

- name: Shared code renderer contracts
run: >
npx vitest run
apps/web/src/components/ai-elements/code-block.test.tsx
apps/web/src/shared/components/LazyCodeBlock.test.tsx
apps/web/src/shared/components/LazyCodeBlock.load-failure.test.tsx
apps/web/src/features/strategy/views/ExecutionTraceView.test.tsx
apps/web/src/features/strategy/views/ProductDirectionMemoView.test.tsx
--maxWorkers=2 --minWorkers=1 --no-file-parallelism

scratchnode-launch-gates:
name: ScratchNode launch gates
runs-on: ubuntu-latest
Expand Down
18 changes: 7 additions & 11 deletions .github/workflows/convex-mcp-eval-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
paths:
- 'packages/convex-mcp-nodebench/**'
- 'scripts/eval-harness/**'
- '.github/workflows/convex-mcp-eval-gate.yml'
schedule:
# Nightly at 4 AM UTC
- cron: '0 4 * * *'
Expand All @@ -19,7 +20,7 @@ on:
default: 'tier1'
type: string
backend:
description: 'Agent backend (stub/anthropic/openai)'
description: 'Requested agent backend (anthropic/openai; execution not yet implemented)'
default: 'anthropic'
type: string

Expand Down Expand Up @@ -47,13 +48,10 @@ jobs:
working-directory: packages/convex-mcp-nodebench
run: npm test

- name: Run eval harness (Tier 1 deterministic)
- name: List evaluation task catalog (no agent execution)
run: |
echo "=== Eval Harness: Tier 1 Tasks ==="
npx tsx scripts/eval-harness/runner.ts --list
echo "---"
echo "Gate check: convex-mcp-nodebench builds clean and all 16 tools / 27 tests pass."
echo "Full eval runs require agent invocation which is done in nightly CI."
node packages/convex-mcp-nodebench/node_modules/tsx/dist/cli.mjs scripts/eval-harness/runner.ts --list
echo "Package build and tests are checked above. This catalog does not certify provider-backed evaluations."

- name: Upload eval results
if: always()
Expand Down Expand Up @@ -85,7 +83,7 @@ jobs:
working-directory: packages/convex-mcp-nodebench
run: npm run build

- name: Run nightly eval suite (real agent invocation)
- name: Require provider-backed evaluation execution
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
Expand All @@ -99,9 +97,7 @@ jobs:
echo "Backend: $EVAL_BACKEND"
echo "Seeds: $EVAL_SEEDS"
echo "Tasks: $EVAL_TASKS"
npx tsx scripts/eval-harness/runner.ts --list
# TODO: Replace --list with actual run once agentInvoker API calls are live:
# npx tsx scripts/eval-harness/runner.ts --task $EVAL_TASKS --seeds $EVAL_SEEDS
node packages/convex-mcp-nodebench/node_modules/tsx/dist/cli.mjs scripts/eval-harness/runner.ts --all --tasks "$EVAL_TASKS" --seeds "$EVAL_SEEDS"

- name: Upload nightly results
if: always()
Expand Down
120 changes: 66 additions & 54 deletions .github/workflows/nodebench-packet.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: NodeBench Packet
# Trigger: comment "@nodebench <company>" on any PR or issue
# Result: posts a structured intelligence packet as a comment
# A human comment "@nodebench <company>" requests a packet on an issue or PR.
# Event and response text stay data; this privileged job checks out no source.

on:
issue_comment:
Expand All @@ -12,65 +12,77 @@ permissions:

jobs:
nodebench-packet:
if: contains(github.event.comment.body, '@nodebench')
if: contains(github.event.comment.body, '@nodebench') && github.event.comment.user.type != 'Bot'
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- name: Extract query from comment
id: extract
run: |
COMMENT="${{ github.event.comment.body }}"
QUERY=$(echo "$COMMENT" | sed 's/.*@nodebench //' | head -1 | tr -d '\n')
echo "query=$QUERY" >> $GITHUB_OUTPUT
echo "Extracted query: $QUERY"

- name: Run NodeBench search
id: search
- name: Request and post packet
uses: actions/github-script@v9
env:
NODEBENCH_API: ${{ secrets.NODEBENCH_API_URL || 'https://langgraph-agent-873372783709.us-central1.run.app' }}
run: |
RESULT=$(curl -sS -X POST "$NODEBENCH_API/api/pipeline/search" \
-H "Content-Type: application/json" \
-d "{\"query\": \"${{ steps.extract.outputs.query }}\", \"lens\": \"founder\"}" \
--max-time 60)

ENTITY=$(echo "$RESULT" | jq -r '.entityName // "Unknown"')
CONFIDENCE=$(echo "$RESULT" | jq -r '.confidence // 0')
ANSWER=$(echo "$RESULT" | jq -r '.answer // "No results"' | head -5)
SIGNALS=$(echo "$RESULT" | jq -r '.variables // [] | length')
SOURCES=$(echo "$RESULT" | jq -r '.sourceRefs // [] | length')

# Build markdown comment
cat << 'COMMENT_EOF' > comment.md
## NodeBench Intelligence Packet

**Entity:** $ENTITY
**Confidence:** $CONFIDENCE%
**Sources:** $SOURCES | **Signals:** $SIGNALS

### Summary
$ANSWER

---
*Generated by [NodeBench](https://nodebenchai.com) Pipeline v2*
COMMENT_EOF

# Replace variables
sed -i "s/\$ENTITY/$ENTITY/g" comment.md
sed -i "s/\$CONFIDENCE/$CONFIDENCE/g" comment.md
sed -i "s/\$SOURCES/$SOURCES/g" comment.md
sed -i "s/\$SIGNALS/$SIGNALS/g" comment.md
sed -i "s/\$ANSWER/$ANSWER/g" comment.md

- name: Post comment
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
const body = fs.readFileSync('comment.md', 'utf8');
const issueNumber = context.issue.number;
const comment = context.payload.comment.body;
const query = comment.match(/[\s\S]*@nodebench([^\r\n]*)/i)?.[1]?.trim() || '';
if (!query || query.length > 2000) {
throw new Error('Supply a query of 1 to 2000 characters after @nodebench.');
}
const base = new URL(process.env.NODEBENCH_API);
if (base.protocol !== 'https:' || base.username || base.password ||
base.pathname !== '/' || base.search || base.hash) {
throw new Error('NODEBENCH_API must be a trusted HTTPS origin without credentials.');
}
const response = await fetch(new URL('/api/pipeline/search', base), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, lens: 'founder' }),
redirect: 'error',
signal: AbortSignal.timeout(60000),
});
if (!response.ok) {
await response.body?.cancel();
throw new Error(`NodeBench search failed with HTTP ${response.status}.`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8', { fatal: true });
let bytes = 0;
let text = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
bytes += value.byteLength;
if (bytes > 256 * 1024) throw new Error('NodeBench response exceeds 256 KiB.');
text += decoder.decode(value, { stream: true });
}
text += decoder.decode();
} finally {
await reader.cancel().catch(() => {});
reader.releaseLock();
}
const packet = JSON.parse(text);
if (!packet || typeof packet !== 'object' || Array.isArray(packet) ||
packet.success === false || typeof packet.answer !== 'string') {
throw new Error('NodeBench returned an unsuccessful or malformed packet.');
}
const confidence = Number.isFinite(packet.confidence) &&
packet.confidence >= 0 && packet.confidence <= 100
? `${packet.confidence}%` : 'Unavailable';
const entity = typeof packet.entityName === 'string'
? packet.entityName.slice(0, 300) : 'Not supplied';
const sources = Array.isArray(packet.sourceRefs) ? packet.sourceRefs.length : 'Unavailable';
const signals = Array.isArray(packet.variables) ? packet.variables.length : 'Unavailable';
const answer = packet.answer.split('\n', 5).join('\n').slice(0, 4000);
const body = [
'## NodeBench Intelligence Packet', '',
`**Entity:** ${entity}`, `**Confidence:** ${confidence}`,
`**Sources:** ${sources} | **Signals:** ${signals}`, '',
'### Summary', answer, '', '---',
'*Generated by [NodeBench](https://nodebenchai.com) Pipeline v2*',
].join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body: body,
issue_number: context.issue.number,
body,
});
2 changes: 1 addition & 1 deletion .github/workflows/vercel-preflight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
env:
CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY }}
VITE_CONVEX_URL: ${{ secrets.VITE_CONVEX_URL || vars.VITE_CONVEX_URL || vars.CONVEX_URL || secrets.CONVEX_URL }}
NODE_OPTIONS: --max-old-space-size=4096
NODE_OPTIONS: --max-old-space-size=6144
steps:
- uses: actions/checkout@v6

Expand Down
Loading
Loading