AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
독립 포트폴리오 시제품: 스티커 주문 시 발생하는 아트워크 문제를 검사·정리·수정·검증·증명하는 에이전트
Independent portfolio prototype: an agent that resolves artwork blockers on simulated sticker orders (inspect, clarify, repair, verify, proof).
개발 도구Go · PythonGitHub @ns-0437온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Resolves an artwork blocker on a simulated sticker order: inspect the file, clarify customer intent when needed, perform one eligible repair, verify it, prepare a proof, and persist the case so work survives a crash or a delayed reply.
Independent portfolio prototype. No access to any real company's production pipeline, customer files, printer profiles, or operational metrics. Makes no claim of measured savings or private integration.README 전문 보기 ↗Resolves an artwork blocker on a simulated sticker order: inspect the file, clarify customer intent when needed, perform one eligible repair, verify it, prepare a proof, and persist the case so work survives a crash or a delayed reply.
Independent portfolio prototype. No access to any real company's production pipeline, customer files, printer profiles, or operational metrics. Makes no claim of measured savings or private integration.
ns-0437.github.io/artwork-agent - the real stack, not a mock: static frontend on GitHub Pages, api-go + worker + image-python on Cloud Run (asia-south1, project artwork-agent-demo), Postgres on a free-tier Neon instance, artifacts in a GCS bucket with a 7-day deletion lifecycle.
Deployed revision: commit 2abca30 (master, 2026-09-17) - artwork-agent-api-00006-9f2, artwork-agent-worker-00005-9c5, artwork-agent-image-python-00004-xnm on Cloud Run. Verified against the live deployment, not just locally: an unauthenticated request to image-python returns 403; the full upload -> inspect -> repair -> proof loop was driven end to end through the deployed frontend and reached RESOLVED / AWAITING_CUSTOMER_APPROVAL. The provider-error-vs-model-escalation distinction (see below) was verified separately: a local integration test against the real Groq API with a deliberately invalid key (a genuine 401 from Groq, not a stubbed/mocked response), run against the local stack rather than the live deployment - see evals/scripts/run_eval.py's no_provider_error check.
image-python's "private Python" requirement (per the brief) is enforced by IAM alone (roles/run.invoker granted only to the calling service's own service account, never allUsers/allAuthenticatedUsers) - not by network ingress. ingress: internal was tried first and reverted: Cloud Run only treats a caller as "internal" if it's attached to a Serverless VPC connector or uses Direct VPC egress, neither of which is set up here, so a sibling Cloud Run service's call left over the public internet and got rejected identically to an outside caller. ingress: all + IAM-only auth was the chosen tradeoff for a portfolio demo's cost/complexity budget: it avoids needing a VPC connector. That is a narrower claim than "free" - Cloud Run's own compute/request billing, and any connector's cost if one is added later, are separate from this tradeoff and weren't estimated here.
Public, unauthenticated, read-only by default. There's no ownership check on orders (known gap, below), so the live deployment sets READ_ONLY_DEMO=true: every GraphQL mutation is rejected server-side (graph.Resolver.guarded, checked before any of the 7 mutations' own logic runs), with reads left open - no credentials in the frontend bundle, nothing for the client to bypass. This is stronger than the order-count cap (MAX_DEMO_ORDERS=150) alone, which only limits creating new orders and does nothing to stop repeated writes against an existing one. maxScale=5 on every Cloud Run service caps concurrent instances, not total spend - it's a parallelism limit, not a cost ceiling. The recorded demo shows the actual write flow (repair -> proof, escalation) against a locally-run stack, or the live deployment with READ_ONLY_DEMO temporarily unset for that recording.
Two things the demo intentionally doesn't do: this is a single-instance walkthrough, not a load-bearing service - don't expect it to stay up under sustained traffic; and the worker's agent_decide step calls a live Groq model, so repeated runs against the same synthetic test image can land on request_repair or escalate inconsistently (the same non-determinism the evaluation harness's methodology section already documents), which is expected model behavior, not a deployment fault.
34 fixtures (16 dev, 18 held-out), driven through the real stack end to end, three ways. Full methodology and honest boundaries: docs/case_study.md.
| agent (Groq) | rules only, no agent | rules + deterministic script | |
|---|---|---|---|
| evaluation cases passed | 34/34 | n/a | n/a |
| orders resolved | 18/34 | 12/34 | 18/34 |
orders escalated (NEEDS_REVIEW) | 16/34 | 14/34 | 16/34 |
| orders left stuck | 0 | 8 | 0 |
| provider tokens used | 19,650 | 0 | 0 |
"Passed" and "resolved" are different claims - a correctly-escalated case passes without the order ever resolving. Once the script had the same escalation capability the agent has, it matched the agent exactly on all 34 fixtures. This project does not claim the LLM improved resolution over a well-designed deterministic workflow - for this fixture set, it didn't. A separate, smaller check on 4 held-out fixtures reserved specifically for a genuinely blind pass (never run until the comparison logic above was frozen) also passed 4/4, 2/4 resolved - a small check (n=4), not broad proof.
"I built and deployed a durable artwork exception-resolution workflow. My evaluation found that a deterministic script matched the agent on the tested cases, so I would favor the scripted path for this scope while retaining the agent version for further evaluation."
Frozen evaluation commit (tagged for reproducibility): git checkout eval-frozen-day5. Raw results: evals/results/*.json. What changed and why between runs: evals/CHANGES.md.
docs/demo_script.md is a three-minute walkthrough script (clarification → verified repair → proof → escalation), matching the build brief's demo structure. Every beat in it was rehearsed live against the running stack immediately before being written down - not simulated from memory.
docker compose -f infra/docker-compose.yml up --build
This starts Postgres (migrations applied automatically on first init), the Python image-inspection service, the Go API + worker, and the web UI. Updating from an older checkout with a schema mismatch: docker compose -f infra/docker-compose.yml down -v first (Postgres only applies migrations to a fresh volume).
No .env file is required for local use - infra/docker-compose.yml bakes in working defaults. See .env.example for what each variable does.
Not included in this repository - the agent tooling used to build and verify this project could drive the UI and confirm behavior via its text output, but could not reliably capture screen images in this session. The demo script above documents the exact UI states (clarification prompt, job list, findings, final status) a live run produces. The live demo above is the fastest way to see it directly; docker compose up (below) reproduces it locally in under five minutes.
The active decision-making provider is Groq, not Claude and not xAI's Grok - the Anthropic account available for this build had no usable credits, so Groq was substituted as a documented, honest stand-in. Groq and Grok are unrelated companies with similar-sounding names. The provider is a single, swappable interface (internal/agent.Provider); trying a different model means implementing that interface again.
CLAUDE.md points 21 and 48.ownerId is a free-text, unverified client field) - dev ports are bound to 127.0.0.1 specifically because of this. The live deployment sets READ_ONLY_DEMO=true (all mutations rejected server-side) rather than leaving this open - a read-only boundary, not a substitute for real per-owner access control, which remains a genuine known gap.