@agilno-tech/rivet 0.1.0-alpha.0
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/LICENSE +202 -0
- package/NOTICE +6 -0
- package/README.md +59 -0
- package/bin/cli.js +42 -0
- package/dist/agents/backend-django-agent/SKILL.md +35 -0
- package/dist/agents/backend-nestjs-agent/SKILL.md +36 -0
- package/dist/agents/boss-agent/SKILL.md +28 -0
- package/dist/agents/bounded-worker/SKILL.md +28 -0
- package/dist/agents/data-performance-agent/SKILL.md +32 -0
- package/dist/agents/delivery-ticketing-agent/SKILL.md +36 -0
- package/dist/agents/devops-agent/SKILL.md +34 -0
- package/dist/agents/engineering-manager/SKILL.md +28 -0
- package/dist/agents/frontend-nextjs-agent/SKILL.md +34 -0
- package/dist/agents/frontend-web-agent/SKILL.md +31 -0
- package/dist/agents/incident-response-agent/SKILL.md +42 -0
- package/dist/agents/jest-agent/SKILL.md +77 -0
- package/dist/agents/mobile-agent/SKILL.md +32 -0
- package/dist/agents/playwright-agent/SKILL.md +54 -0
- package/dist/agents/product-design-manager/SKILL.md +27 -0
- package/dist/agents/qa-agent/SKILL.md +29 -0
- package/dist/agents/quality-manager/SKILL.md +28 -0
- package/dist/agents/vitest-agent/SKILL.md +77 -0
- package/dist/governance/pre-push-rules.md +75 -0
- package/dist/governance/prompt-hygiene.md +22 -0
- package/dist/governance/review-checklist.md +24 -0
- package/dist/governance/safety-and-data.md +27 -0
- package/dist/governance/usage-rules.md +21 -0
- package/dist/mandatory/address-pr-feedback/SKILL.md +196 -0
- package/dist/mandatory/agentic-goal/SKILL.md +42 -0
- package/dist/mandatory/agentic-status/SKILL.md +74 -0
- package/dist/mandatory/apply-design/SKILL.md +228 -0
- package/dist/mandatory/check-ac/SKILL.md +124 -0
- package/dist/mandatory/create-pr-and-commit/SKILL.md +304 -0
- package/dist/mandatory/design/SKILL.md +312 -0
- package/dist/mandatory/feature-workflow/SKILL.md +87 -0
- package/dist/mandatory/hotfix/SKILL.md +195 -0
- package/dist/mandatory/pre-push/SKILL.md +272 -0
- package/dist/mandatory/project-context/SKILL.md +180 -0
- package/dist/mandatory/release-docs/SKILL.md +191 -0
- package/dist/mandatory/review-pr/SKILL.md +323 -0
- package/dist/mandatory/security-review/SKILL.md +157 -0
- package/dist/skills/api-contract/SKILL.md +77 -0
- package/dist/skills/backend-django/SKILL.md +27 -0
- package/dist/skills/backend-nestjs/SKILL.md +65 -0
- package/dist/skills/bug-ticket-creation/SKILL.md +43 -0
- package/dist/skills/cloudwatch-troubleshooting/SKILL.md +73 -0
- package/dist/skills/database-migration/SKILL.md +97 -0
- package/dist/skills/debugging/SKILL.md +32 -0
- package/dist/skills/devops-infra/SKILL.md +26 -0
- package/dist/skills/documentation/SKILL.md +24 -0
- package/dist/skills/frontend-nextjs/SKILL.md +27 -0
- package/dist/skills/incident-postmortem/SKILL.md +38 -0
- package/dist/skills/kubernetes-troubleshooting/SKILL.md +71 -0
- package/dist/skills/mobile-react-native/SKILL.md +37 -0
- package/dist/skills/postgres-analytics/SKILL.md +29 -0
- package/dist/skills/product-jira-ticketing/SKILL.md +28 -0
- package/dist/skills/qa-bug-analysis/SKILL.md +27 -0
- package/dist/skills/refactoring/SKILL.md +32 -0
- package/dist/skills/sprint-planning/SKILL.md +32 -0
- package/dist/skills/testing-quality/SKILL.md +62 -0
- package/dist/v2/protocols/agent-orchestration.md +49 -0
- package/dist/v2/protocols/delivery.md +45 -0
- package/dist/v2/protocols/design-authority.md +29 -0
- package/dist/v2/protocols/goal-graph.md +44 -0
- package/dist/v2/protocols/pattern-first-development.md +29 -0
- package/dist/v2/protocols/qa-evidence.md +29 -0
- package/dist/v2/protocols/security.md +29 -0
- package/dist/v2/schemas/event.schema.json +86 -0
- package/dist/v2/schemas/evidence.schema.json +94 -0
- package/dist/v2/schemas/feature-decomposition.schema.json +48 -0
- package/dist/v2/schemas/feature-plan.schema.json +95 -0
- package/dist/v2/schemas/goal-graph.schema.json +61 -0
- package/dist/v2/schemas/integration.schema.json +119 -0
- package/dist/v2/schemas/orchestration.schema.json +69 -0
- package/dist/v2/schemas/project.schema.json +209 -0
- package/dist/v2/schemas/providers.schema.json +142 -0
- package/dist/v2/schemas/quality.schema.json +50 -0
- package/dist/v2/schemas/work-action.schema.json +44 -0
- package/dist/v2/schemas/work-request.schema.json +253 -0
- package/dist/v2/templates/evidence/qa-bundle.json +194 -0
- package/dist/v2/templates/github-actions/rivet-deploy.yml +98 -0
- package/dist/v2/templates/harness/SKILL.md +90 -0
- package/dist/v2/templates/project/.rivet/orchestration.yaml +42 -0
- package/dist/v2/templates/project/.rivet/project.yaml +14 -0
- package/dist/v2/templates/project/.rivet/providers.yaml +8 -0
- package/dist/v2/templates/project/.rivet/quality.yaml +16 -0
- package/package.json +58 -0
- package/protocols/agent-orchestration.md +49 -0
- package/protocols/delivery.md +45 -0
- package/protocols/design-authority.md +29 -0
- package/protocols/goal-graph.md +44 -0
- package/protocols/pattern-first-development.md +29 -0
- package/protocols/qa-evidence.md +29 -0
- package/protocols/security.md +29 -0
- package/schemas/event.schema.json +86 -0
- package/schemas/evidence.schema.json +94 -0
- package/schemas/feature-decomposition.schema.json +48 -0
- package/schemas/feature-plan.schema.json +95 -0
- package/schemas/goal-graph.schema.json +61 -0
- package/schemas/integration.schema.json +119 -0
- package/schemas/orchestration.schema.json +69 -0
- package/schemas/project.schema.json +209 -0
- package/schemas/providers.schema.json +142 -0
- package/schemas/quality.schema.json +50 -0
- package/schemas/work-action.schema.json +44 -0
- package/schemas/work-request.schema.json +253 -0
- package/src/adapters/confluence.js +138 -0
- package/src/adapters/contract.js +657 -0
- package/src/adapters/factory.js +122 -0
- package/src/adapters/figma.js +178 -0
- package/src/adapters/fixtures.js +183 -0
- package/src/adapters/github.js +314 -0
- package/src/adapters/http.js +704 -0
- package/src/adapters/jira.js +195 -0
- package/src/adapters/linear.js +171 -0
- package/src/adapters/node-transport.js +59 -0
- package/src/cli/integration-setup-prompt.js +32 -0
- package/src/cli/interrupt.js +25 -0
- package/src/cli/main.js +596 -0
- package/src/cli/output.js +174 -0
- package/src/cli/parse-args.js +246 -0
- package/src/cli/project-discovery.js +70 -0
- package/src/cli/task-confirmation.js +38 -0
- package/src/cli/task-presentation.js +22 -0
- package/src/clients/claude.js +214 -0
- package/src/clients/codex.js +180 -0
- package/src/clients/compatibility.js +23 -0
- package/src/clients/contract.js +224 -0
- package/src/clients/fake.js +170 -0
- package/src/clients/process-runner.js +657 -0
- package/src/clients/result-contract.js +78 -0
- package/src/commands/delivery-publish.js +80 -0
- package/src/commands/delivery-remote.js +230 -0
- package/src/commands/delivery-review-update.js +39 -0
- package/src/commands/delivery-tracker.js +94 -0
- package/src/commands/delivery-transition.js +79 -0
- package/src/commands/delivery.js +223 -0
- package/src/commands/dependency-approval.js +21 -0
- package/src/commands/doctor.js +191 -0
- package/src/commands/evidence.js +44 -0
- package/src/commands/feature.js +212 -0
- package/src/commands/goals.js +231 -0
- package/src/commands/human-run.js +208 -0
- package/src/commands/human-task.js +278 -0
- package/src/commands/init.js +848 -0
- package/src/commands/install.js +814 -0
- package/src/commands/integration-setup.js +65 -0
- package/src/commands/integrations.js +54 -0
- package/src/commands/models.js +158 -0
- package/src/commands/orchestrate.js +61 -0
- package/src/commands/preflight.js +125 -0
- package/src/commands/protocols.js +228 -0
- package/src/commands/repositories.js +77 -0
- package/src/commands/setup-remote.js +41 -0
- package/src/commands/setup.js +214 -0
- package/src/commands/status.js +224 -0
- package/src/commands/support.js +44 -0
- package/src/commands/task-completion.js +104 -0
- package/src/commands/uninstall.js +234 -0
- package/src/commands/verify.js +171 -0
- package/src/commands/work.js +220 -0
- package/src/commands/worktrees.js +52 -0
- package/src/config/command-readiness.js +218 -0
- package/src/config/commands.js +206 -0
- package/src/config/defaults.js +55 -0
- package/src/config/load.js +230 -0
- package/src/config/validate.js +560 -0
- package/src/delivery/bitbucket-review.js +123 -0
- package/src/delivery/branch-publication.js +23 -0
- package/src/delivery/contract.js +379 -0
- package/src/delivery/github-deployment.js +132 -0
- package/src/delivery/github-review.js +5 -0
- package/src/delivery/github.js +382 -0
- package/src/delivery/gitlab-review.js +5 -0
- package/src/delivery/gitlab.js +395 -0
- package/src/delivery/prepare.js +90 -0
- package/src/delivery/publication-process.js +33 -0
- package/src/delivery/publication-transport.js +112 -0
- package/src/delivery/review-request.js +184 -0
- package/src/delivery/review-update.js +74 -0
- package/src/delivery/service.js +400 -0
- package/src/delivery/store.js +76 -0
- package/src/delivery/tracker-target.js +51 -0
- package/src/delivery/tracker-transition.js +158 -0
- package/src/delivery/tracker.js +164 -0
- package/src/discovery/git.js +85 -0
- package/src/discovery/portable.js +108 -0
- package/src/discovery/project.js +345 -0
- package/src/discovery/tools.js +145 -0
- package/src/evaluations/approval.js +20 -0
- package/src/evaluations/cost-policy.js +20 -0
- package/src/evaluations/harness-attempt.js +113 -0
- package/src/evaluations/live-runner.js +55 -0
- package/src/evaluations/profile.js +28 -0
- package/src/evaluations/report.js +11 -0
- package/src/evaluations/text-attempt.js +18 -0
- package/src/evidence/checksum.js +87 -0
- package/src/evidence/collect.js +727 -0
- package/src/evidence/validate.js +354 -0
- package/src/feature/accepted-integration.js +46 -0
- package/src/feature/actions.js +37 -0
- package/src/feature/client-profile.js +56 -0
- package/src/feature/decomposition-contract.js +58 -0
- package/src/feature/host-execution.js +633 -0
- package/src/feature/host-lock-recovery.js +96 -0
- package/src/feature/host-run-lock.js +32 -0
- package/src/feature/local-approval.js +183 -0
- package/src/feature/plan-contract.js +215 -0
- package/src/feature/planner.js +253 -0
- package/src/feature/run-store.js +241 -0
- package/src/feature/runtime-bridge.js +840 -0
- package/src/feature/verification-report.js +168 -0
- package/src/feature/workflow.js +375 -0
- package/src/git/client.js +509 -0
- package/src/git/integration-worktree.js +153 -0
- package/src/git/reconcile.js +222 -0
- package/src/git/reservations.js +450 -0
- package/src/git/worktrees.js +478 -0
- package/src/graph/completion.js +189 -0
- package/src/graph/fixtures.js +116 -0
- package/src/graph/reducer.js +124 -0
- package/src/graph/scheduler.js +252 -0
- package/src/graph/validate.js +106 -0
- package/src/install/managed.js +579 -0
- package/src/install/project-reference.js +33 -0
- package/src/install/project-runtime.js +142 -0
- package/src/install/runtime-integrity.cjs +141 -0
- package/src/integrations/capabilities.js +69 -0
- package/src/integrations/host-observation.js +26 -0
- package/src/integrations/registry.js +56 -0
- package/src/models/delegate.js +102 -0
- package/src/models/profiles.js +53 -0
- package/src/models/protocols.js +208 -0
- package/src/models/registry.js +83 -0
- package/src/models/transport.js +59 -0
- package/src/policy/approvals.js +251 -0
- package/src/policy/authority.js +282 -0
- package/src/policy/budget.js +149 -0
- package/src/policy/command-bootstrap.js +219 -0
- package/src/policy/commands.js +803 -0
- package/src/prompts/launch-contract.js +43 -0
- package/src/prompts/planning-contract.js +92 -0
- package/src/protocols/presentation.js +53 -0
- package/src/protocols/project.js +289 -0
- package/src/quality/runner.js +497 -0
- package/src/quality/traceability.js +215 -0
- package/src/repositories/identity.js +59 -0
- package/src/repositories/index.js +2 -0
- package/src/repositories/provider.js +210 -0
- package/src/runtime/application.js +353 -0
- package/src/runtime/dependency-directory.js +33 -0
- package/src/runtime/harness-discovery.js +121 -0
- package/src/runtime/heartbeat.js +47 -0
- package/src/runtime/instance-store.js +112 -0
- package/src/runtime/orchestrator.js +1133 -0
- package/src/runtime/portable-dependencies.js +94 -0
- package/src/runtime/recovery.js +190 -0
- package/src/runtime/retry.js +54 -0
- package/src/runtime/supervisor.js +166 -0
- package/src/runtime/worktree-bootstrap.js +169 -0
- package/src/state/event-store.js +333 -0
- package/src/state/lock.js +266 -0
- package/src/state/paths.js +274 -0
- package/src/state/redact.js +106 -0
- package/src/state/snapshot-store.js +310 -0
- package/src/status/public/app.js +96 -0
- package/src/status/public/index.html +37 -0
- package/src/status/public/styles.css +50 -0
- package/src/status/server.js +323 -0
- package/src/status/view-model.js +356 -0
- package/src/support/bundle.js +195 -0
- package/src/support/failure-report.js +96 -0
- package/src/work-request/contract.js +250 -0
- package/src/work-request/host.js +78 -0
- package/src/work-request/local.js +163 -0
- package/src/work-request/tracker.js +105 -0
- package/templates/evidence/qa-bundle.json +194 -0
- package/templates/github-actions/rivet-deploy.yml +98 -0
- package/templates/harness/SKILL.md +90 -0
- package/templates/project/.rivet/orchestration.yaml +42 -0
- package/templates/project/.rivet/project.yaml +14 -0
- package/templates/project/.rivet/providers.yaml +8 -0
- package/templates/project/.rivet/quality.yaml +16 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { loadLiveScenario } from '../../evals/live-catalog.mjs';
|
|
3
|
+
import { resolveLiveProfile,liveProfileDigest } from './profile.js';
|
|
4
|
+
import { capture,ensure,LiveEvaluationError } from './cost-policy.js';
|
|
5
|
+
import { evaluationReport,reportDigest } from './report.js';
|
|
6
|
+
import { waitForApproval } from './approval.js';
|
|
7
|
+
import { runTextAttempt } from './text-attempt.js';
|
|
8
|
+
import { runPublicationProcess } from '../delivery/publication-process.js';
|
|
9
|
+
async function sourceIdentity() {
|
|
10
|
+
const cwd=fileURLToPath(new URL('../../',import.meta.url));
|
|
11
|
+
const options={cwd,env:{PATH:'/usr/bin:/bin',GIT_CONFIG_NOSYSTEM:'1',GIT_CONFIG_GLOBAL:'/dev/null',GIT_NO_REPLACE_OBJECTS:'1'},timeoutMs:3000};
|
|
12
|
+
const commit=await runPublicationProcess('/usr/bin/git',['rev-parse','HEAD'],options);
|
|
13
|
+
const status=await runPublicationProcess('/usr/bin/git',['-c','core.fsmonitor=false','status','--porcelain','--untracked-files=all'],options);
|
|
14
|
+
ensure(commit.code===0&&status.code===0,'source-unavailable');
|
|
15
|
+
return Object.freeze({commit:commit.stdout.trim(),dirty:status.stdout.length>0,sourceScope:'current-working-tree',observedAt:'start'});
|
|
16
|
+
}
|
|
17
|
+
export async function runLiveEvaluation(input,dependencies={}) {
|
|
18
|
+
const args=capture(input,['scenario','profile']);
|
|
19
|
+
const deps=capture(dependencies,['interactive','confirm','confirmActivation','environment','signal','transport','clients']);
|
|
20
|
+
ensure(deps.interactive===true&&typeof deps.confirm==='function','interactive-approval-required');
|
|
21
|
+
const profile=resolveLiveProfile(args.profile),scenario=await loadLiveScenario(args.scenario);
|
|
22
|
+
ensure(profile.kind===scenario.kind,'scenario-profile-mismatch');
|
|
23
|
+
const checkCancelled=()=>ensure(!deps.signal?.aborted,'cancelled');checkCancelled();
|
|
24
|
+
const source=await sourceIdentity();
|
|
25
|
+
const proposal=Object.freeze({schemaVersion:1,scenario:scenario.id,fixtureDigest:scenario.digest,profileDigest:liveProfileDigest(profile),models:profile.models,destination:profile.destination,limits:profile.limits,cost:profile.cost,source,providerWrites:false,workspace:profile.kind==='harness'?'new disposable local repository and bare local remote; no external push; retained for inspection':null,notice:'This fixed-fixture trial calls the selected installed harness or model endpoint. Calls may incur account charges or local compute costs under your explicit policy. There is no enforced dollar cap. Human pilot and live delivery qualification remain separate.'});
|
|
26
|
+
const digest=reportDigest(proposal);
|
|
27
|
+
const controller=new AbortController();const abort=()=>controller.abort();deps.signal?.addEventListener('abort',abort,{once:true});
|
|
28
|
+
if(deps.signal?.aborted)controller.abort();
|
|
29
|
+
const started=Date.now(),startedAt=new Date(started).toISOString();let timedOut=false;
|
|
30
|
+
const timer=setTimeout(()=>{timedOut=true;controller.abort()},profile.limits.timeoutMs);
|
|
31
|
+
try {
|
|
32
|
+
try {
|
|
33
|
+
ensure(await waitForApproval(deps.confirm,Object.freeze({...proposal,digest}),controller.signal)===true,'approval-declined');
|
|
34
|
+
ensure(!controller.signal.aborted,timedOut?'timeout':'cancelled');
|
|
35
|
+
ensure((await sourceIdentity()).commit===source.commit,'source-revision-changed');
|
|
36
|
+
ensure(!controller.signal.aborted,timedOut?'timeout':'cancelled');
|
|
37
|
+
ensure(liveProfileDigest(resolveLiveProfile(args.profile))===proposal.profileDigest,'profile-changed');
|
|
38
|
+
ensure((await loadLiveScenario(args.scenario)).digest===scenario.digest,'fixture-changed');
|
|
39
|
+
ensure(!controller.signal.aborted,timedOut?'timeout':'cancelled');
|
|
40
|
+
} catch(error) {
|
|
41
|
+
if(controller.signal.aborted)throw new LiveEvaluationError(timedOut?'timeout':'cancelled');
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
let result;
|
|
45
|
+
try {
|
|
46
|
+
if(profile.kind==='text')result=await runTextAttempt({profile,scenario,environment:deps.environment??{},signal:controller.signal,transport:deps.transport});
|
|
47
|
+
else {
|
|
48
|
+
const {runHarnessAttempt}=await import('./harness-attempt.js');
|
|
49
|
+
result=await runHarnessAttempt({profile,scenario,environment:deps.environment??process.env,signal:controller.signal,confirmActivation:deps.confirmActivation,clients:deps.clients,assertCurrent:()=>ensure(liveProfileDigest(resolveLiveProfile(args.profile))===proposal.profileDigest,'profile-changed')});
|
|
50
|
+
}
|
|
51
|
+
if(controller.signal.aborted)result={...result,outcome:'cancelled',reason:timedOut?'timeout':'cancelled'};
|
|
52
|
+
} catch(error) {result={outcome:controller.signal.aborted?'cancelled':'failed',reason:timedOut?'timeout':controller.signal.aborted?'cancelled':error instanceof LiveEvaluationError?error.reason:typeof error.code==='string'?error.code:'attempt-failed'};}
|
|
53
|
+
return evaluationReport({profile,scenario,source,startedAt,elapsedMs:Date.now()-started,result,injected:deps.transport!==undefined||deps.clients!==undefined});
|
|
54
|
+
} finally {clearTimeout(timer);deps.signal?.removeEventListener('abort',abort);}
|
|
55
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createModelRegistry } from '../models/registry.js';
|
|
3
|
+
import { buildModelRequest } from '../models/protocols.js';
|
|
4
|
+
import { capture, ensure, resolveCostPolicy } from './cost-policy.js';
|
|
5
|
+
const HARNESSES=new Set(['claude','codex']);
|
|
6
|
+
const TEXT=new Set(['anthropic','openai','gemini','ollama','openai-compatible']);
|
|
7
|
+
function integer(value,fallback,min,max) { const result=value??fallback;ensure(Number.isSafeInteger(result)&&result>=min&&result<=max);return result; }
|
|
8
|
+
function model(value) { ensure(typeof value==='string' && /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$/.test(value));return value; }
|
|
9
|
+
export function resolveLiveProfile(input) {
|
|
10
|
+
const value=capture(input,['id','model','workerModel','endpoint','credentialEnv','timeoutMs','maxOutputTokens','costPolicy']);
|
|
11
|
+
ensure(HARNESSES.has(value.id)||TEXT.has(value.id));
|
|
12
|
+
const cost=resolveCostPolicy(value.costPolicy,value.id);
|
|
13
|
+
if(HARNESSES.has(value.id)) {
|
|
14
|
+
ensure(value.model===undefined&&value.endpoint===undefined&&value.credentialEnv===undefined&&value.maxOutputTokens===undefined);
|
|
15
|
+
ensure(value.id==='codex'||value.workerModel===undefined);
|
|
16
|
+
const worker=value.id==='claude'?'sonnet':value.workerModel===undefined?'harness-default':model(value.workerModel);
|
|
17
|
+
ensure(value.workerModel===undefined||/^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/.test(value.workerModel));
|
|
18
|
+
return Object.freeze({schemaVersion:1,id:value.id,kind:'harness',models:Object.freeze({planning:value.id==='claude'?'sonnet':'harness-default',worker}),destination:`installed-${value.id}-authenticated-account`,limits:Object.freeze({timeoutMs:integer(value.timeoutMs,300000,1000,600000),planningTimeoutMs:120000,maxModelCalls:2,maxWorkers:1,maxRetries:0,maxOutputBytes:524288}),cost});
|
|
19
|
+
}
|
|
20
|
+
ensure(value.workerModel===undefined);
|
|
21
|
+
const profile=createModelRegistry().resolve({provider:value.id,model:model(value.model),timeoutMs:integer(value.timeoutMs,60000,1000,120000),maxOutputTokens:integer(value.maxOutputTokens,4096,64,16384),...(value.endpoint===undefined?{}:{endpoint:value.endpoint}),...(value.credentialEnv===undefined?{}:{credentialEnv:value.credentialEnv})}).profile;
|
|
22
|
+
ensure(!['anthropic','openai','gemini'].includes(value.id)||profile.credentialEnv!==undefined,'credential-reference-required');
|
|
23
|
+
// Derive the displayed destination from the exact production protocol. This
|
|
24
|
+
// constructs a request with a dummy credential; it sends nothing.
|
|
25
|
+
const destination=buildModelRequest(profile,'Evaluation destination preview.','preview-only').url;
|
|
26
|
+
return Object.freeze({schemaVersion:1,id:value.id,kind:'text',models:Object.freeze({planning:null,worker:profile.model}),destination,modelProfile:profile,limits:Object.freeze({timeoutMs:profile.timeoutMs,maxOutputTokens:profile.maxOutputTokens,maxModelCalls:1,maxRetries:0}),cost});
|
|
27
|
+
}
|
|
28
|
+
export function liveProfileDigest(profile) { return createHash('sha256').update(JSON.stringify(profile)).digest('hex'); }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export function reportDigest(value) { return createHash('sha256').update(JSON.stringify(value)).digest('hex'); }
|
|
3
|
+
export function evaluationReport({profile,scenario,source,startedAt,elapsedMs,result,injected}) {
|
|
4
|
+
return Object.freeze({schemaVersion:1,mode:'live',measurement:injected?'injected-client-rehearsal':'live-attempt',scenario:scenario.id,fixtureDigest:scenario.digest,source,
|
|
5
|
+
profileId:profile.id,profileDigest:reportDigest(profile),startedAt,elapsedMs,retryCount:0,retryScope:'model-dispatch',runtimeRetryCount:null,limits:profile.limits,timeoutSemantics:'abort deadline; cleanup can extend return latency',costPolicy:profile.cost,
|
|
6
|
+
actualCostUsd:null,actualCostProvenance:'not-observed',model:{requested:profile.models,observed:result.observedModel??null},
|
|
7
|
+
harness:result.harness??null,usage:result.usage??{provenance:'not-observed',value:null},outcome:result.outcome,
|
|
8
|
+
acceptance:result.acceptance??{total:scenario.acceptanceIds.length,passed:null,checks:[]},gates:result.gates??[],
|
|
9
|
+
metrics:{unsupportedClaims:null,humanInterventions:null,...result.metrics},evidence:result.evidence??{},
|
|
10
|
+
...(result.reason?{reason:result.reason}:{}),qualification:{freshUserPilot:false,sharedMemory:'not-implemented',sharedMemoryScope:'post-MVP',deliveryProvider:'not-evaluated'}});
|
|
11
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { delegateText } from '../models/delegate.js';
|
|
2
|
+
import { redactSecrets } from '../state/redact.js';
|
|
3
|
+
export async function runTextAttempt({profile,scenario,environment,signal,transport}) {
|
|
4
|
+
const response=await delegateText({profile:profile.modelProfile,prompt:scenario.files['prompt.md'],environment,signal,...(transport===undefined?{}:{transport})});
|
|
5
|
+
let parsed;try{parsed=JSON.parse(response.text)}catch{}
|
|
6
|
+
const structurallyValid=parsed && !Array.isArray(parsed) && Object.keys(parsed).length===2 && Array.isArray(parsed.findings) && parsed.findings.length<=8 && typeof parsed.executedTests==='boolean'
|
|
7
|
+
&& parsed.findings.every(item=>item && Object.keys(item).length===3 && scenario.acceptanceIds.includes(item.id) && item.line===2 && typeof item.explanation==='string' && item.explanation.trim().length>=10 && item.explanation.length<=1000)
|
|
8
|
+
&& new Set(parsed.findings.map(item=>item.id)).size===parsed.findings.length;
|
|
9
|
+
const checks=scenario.acceptanceIds.map(id=>({id,passed:!!structurallyValid&&parsed.findings.some(item=>item.id===id)}));
|
|
10
|
+
const claims=structurallyValid?(parsed.executedTests?1:0):null;
|
|
11
|
+
const redacted=Buffer.from(redactSecrets(response.text,{environment}),'utf8');
|
|
12
|
+
const findings=structurallyValid?redactSecrets(parsed.findings,{environment}).map(item=>({...item,explanation:item.explanation.slice(0,1000)})):[];
|
|
13
|
+
return {outcome:checks.every(item=>item.passed)&&claims===0?'passed':'failed',observedModel:response.model,
|
|
14
|
+
usage:{provenance:'provider-response',value:response.usage},acceptance:{total:checks.length,passed:checks.filter(item=>item.passed).length,checks,scope:'fixed finding IDs, location and response structure; semantic quality requires human review'},
|
|
15
|
+
metrics:{unsupportedTestExecutionClaims:claims},evidence:{responseVerified:false,responseBytes:Buffer.byteLength(response.text),toolsDispatched:0,
|
|
16
|
+
review:{trust:'untrusted-model-output',semanticReview:'required',findings,
|
|
17
|
+
rawExcerpt:redacted.subarray(0,16384).toString('utf8'),excerptTruncated:redacted.length>16384}}};
|
|
18
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { constants } from 'node:fs';
|
|
3
|
+
import { lstat, open } from 'node:fs/promises';
|
|
4
|
+
import { isAbsolute } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_MAX_BYTES = 32 * 1024 * 1024;
|
|
7
|
+
const MAX_BYTES = 128 * 1024 * 1024;
|
|
8
|
+
|
|
9
|
+
export class EvidenceChecksumError extends Error {
|
|
10
|
+
constructor(reason = 'invalid-file') {
|
|
11
|
+
const messages = {
|
|
12
|
+
'invalid-file': 'Evidence checksum input must be a bounded regular file.',
|
|
13
|
+
'file-changed': 'Evidence file changed while its checksum was calculated.',
|
|
14
|
+
};
|
|
15
|
+
super(messages[reason] ?? messages['invalid-file']);
|
|
16
|
+
this.name = 'EvidenceChecksumError';
|
|
17
|
+
this.code = 'ERR_EVIDENCE_CHECKSUM';
|
|
18
|
+
this.safeMessage = this.message;
|
|
19
|
+
this.details = Object.freeze({ reason });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function fail(reason) { throw new EvidenceChecksumError(reason); }
|
|
24
|
+
|
|
25
|
+
function sameFile(left, right) {
|
|
26
|
+
return left.dev === right.dev && left.ino === right.ino
|
|
27
|
+
&& left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function fileLimit(options) {
|
|
31
|
+
let keys;
|
|
32
|
+
try { keys = Reflect.ownKeys(options); } catch { fail('invalid-file'); }
|
|
33
|
+
if (keys.some(key => key !== 'maxBytes')) fail('invalid-file');
|
|
34
|
+
let value = DEFAULT_MAX_BYTES;
|
|
35
|
+
if (keys.includes('maxBytes')) {
|
|
36
|
+
let descriptor;
|
|
37
|
+
try { descriptor = Object.getOwnPropertyDescriptor(options, 'maxBytes'); } catch { fail('invalid-file'); }
|
|
38
|
+
if (!descriptor?.enumerable || !Object.hasOwn(descriptor, 'value')) fail('invalid-file');
|
|
39
|
+
value = descriptor.value;
|
|
40
|
+
}
|
|
41
|
+
if (!Number.isSafeInteger(value) || value <= 0 || value > MAX_BYTES) fail('invalid-file');
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function sha256(value) {
|
|
46
|
+
if (typeof value !== 'string' && !ArrayBuffer.isView(value)) {
|
|
47
|
+
throw new EvidenceChecksumError('invalid-file');
|
|
48
|
+
}
|
|
49
|
+
return createHash('sha256').update(value).digest('hex');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function readFileWithChecksum(path, options = {}) {
|
|
53
|
+
const maxBytes = fileLimit(options);
|
|
54
|
+
if (typeof path !== 'string' || path.length < 2 || path.length > 1_024
|
|
55
|
+
|| !isAbsolute(path) || /[\u0000\r\n]/.test(path)) fail('invalid-file');
|
|
56
|
+
let before;
|
|
57
|
+
try { before = await lstat(path, { bigint: true }); } catch { fail('invalid-file'); }
|
|
58
|
+
if (!before.isFile() || before.isSymbolicLink() || before.nlink !== 1n
|
|
59
|
+
|| before.size < 0n || before.size > BigInt(maxBytes)) fail('invalid-file');
|
|
60
|
+
|
|
61
|
+
let handle;
|
|
62
|
+
try {
|
|
63
|
+
handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
64
|
+
const opened = await handle.stat({ bigint: true });
|
|
65
|
+
if (!opened.isFile() || opened.nlink !== 1n || !sameFile(before, opened)) fail('file-changed');
|
|
66
|
+
const bytes = await handle.readFile();
|
|
67
|
+
const after = await handle.stat({ bigint: true });
|
|
68
|
+
if (!sameFile(opened, after) || bytes.byteLength !== Number(after.size)) fail('file-changed');
|
|
69
|
+
const current = await lstat(path, { bigint: true });
|
|
70
|
+
if (current.isSymbolicLink() || !sameFile(after, current)) fail('file-changed');
|
|
71
|
+
return Object.freeze({
|
|
72
|
+
bytes,
|
|
73
|
+
sha256: sha256(bytes),
|
|
74
|
+
size: bytes.byteLength,
|
|
75
|
+
});
|
|
76
|
+
} catch (error) {
|
|
77
|
+
if (error instanceof EvidenceChecksumError) throw error;
|
|
78
|
+
fail('invalid-file');
|
|
79
|
+
} finally {
|
|
80
|
+
await handle?.close().catch(() => {});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function checksumFile(path, options = {}) {
|
|
85
|
+
const result = await readFileWithChecksum(path, options);
|
|
86
|
+
return Object.freeze({ sha256: result.sha256, bytes: result.size });
|
|
87
|
+
}
|