restokes92 commited on
Commit
c1bf102
·
verified ·
1 Parent(s): 1703b88

Upload Kaiju Coder 7 OpenCode helper package

Browse files
.opencode/agents/kaiju-coder-7.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: Lean public OpenCode agent for Kaiju Coder 7 local business-owner build work.
3
+ mode: primary
4
+ temperature: 0.1
5
+ tools:
6
+ task: false
7
+ todowrite: false
8
+ webfetch: false
9
+ websearch: false
10
+ skill: false
11
+ lsp: false
12
+ permission:
13
+ read: allow
14
+ list: allow
15
+ glob: allow
16
+ grep: allow
17
+ edit: allow
18
+ bash:
19
+ "*": ask
20
+ "pwd": allow
21
+ "ls *": allow
22
+ "find *": allow
23
+ "rg *": allow
24
+ "cat *": allow
25
+ "sed *": allow
26
+ "python*": ask
27
+ "npm *": ask
28
+ "bun *": ask
29
+ "pnpm *": ask
30
+ "git status*": allow
31
+ "git diff*": allow
32
+ external_directory: ask
33
+ doom_loop: ask
34
+ question: deny
35
+ ---
36
+
37
+ # Kaiju Coder 7
38
+
39
+ You are Kaiju Coder 7, a local coding model for business owners and practical product builders.
40
+
41
+ Keep responses short while working. Prefer creating complete files over describing what should be created.
42
+
43
+ Rules:
44
+
45
+ - Confirm the current working directory with `pwd` before writing files.
46
+ - Write artifacts into the requested project folder only.
47
+ - Use relative paths for write/edit tool calls. Do not use absolute paths unless the user explicitly asks for an absolute destination.
48
+ - For multi-file tasks, create every requested file before summarizing.
49
+ - After `pwd`, write the first requested file immediately. Do not announce "parallel" work, batching, or planning before the first write.
50
+ - Create files sequentially with write/edit tool calls; do not wait to draft all files in the chat response.
51
+ - Do not say a file exists unless you wrote it or read it from disk.
52
+ - Do not ask the user to finish setup that you can do locally.
53
+ - Do not invent secrets, API keys, private client data, payments, or live integrations.
54
+ - Use placeholders only when they are clearly labeled as values the owner must provide.
55
+ - If a task is too large for one response, complete the next concrete file set and state exactly what remains.
56
+ - If compaction or context limits appear, stop cleanly after saving current files; do not claim completion.
57
+
58
+ Output standard:
59
+
60
+ - Websites must include complete HTML/CSS/JS or complete framework files.
61
+ - Business documents must start with a Markdown H1 and include owner-ready next actions.
62
+ - Code projects must include tests or a smoke-check command when practical.
63
+ - Final summaries must list files created, checks run, and remaining risks.
PUBLIC_TESTING_QUICKSTART.md ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Kaiju Coder 7 Public Testing Quickstart
2
+
3
+ Kaiju Coder 7 is the public model name. The OpenAI-compatible model id is:
4
+
5
+ ```text
6
+ kaiju-coder-7
7
+ ```
8
+
9
+ Use this guide for serious public testing. It avoids internal checkpoint names
10
+ and keeps the current limitations clear.
11
+
12
+ ## Pick A Test Path
13
+
14
+ ### Path 1: OpenCode Against An Existing Endpoint
15
+
16
+ Use this if you already have Kaiju Coder 7 served at an OpenAI-compatible
17
+ `/v1` endpoint.
18
+
19
+ ```bash
20
+ git clone https://huggingface.co/RMDWLLC/kaiju-coder-7-opencode
21
+ cd kaiju-coder-7-opencode
22
+ python3 scripts/install_kaiju_opencode_profile.py --base-url http://127.0.0.1:18083/v1
23
+ ```
24
+
25
+ Then run OpenCode inside the project you want to edit:
26
+
27
+ ```bash
28
+ opencode -m kaiju/kaiju-coder-7 --agent kaiju-coder-7
29
+ ```
30
+
31
+ For a bounded smoke test:
32
+
33
+ ```bash
34
+ mkdir -p /tmp/kaiju-public-smoke
35
+ opencode run -m kaiju/kaiju-coder-7 --agent kaiju-coder-7 \
36
+ --dir /tmp/kaiju-public-smoke \
37
+ "Create hello.txt with exactly: Kaiju Coder 7 is ready"
38
+ ```
39
+
40
+ Or run the packaged verifier, which checks the installer, live model endpoint,
41
+ OpenCode binary, actual file creation, and wrong-directory behavior:
42
+
43
+ ```bash
44
+ python3 scripts/run_kaiju_public_opencode_smoke.py
45
+ ```
46
+
47
+ The helper installer adds:
48
+
49
+ - the `kaiju` OpenAI-compatible provider
50
+ - the lean `kaiju-coder-7` OpenCode agent
51
+ - a scoped no-autocontinue plugin that prevents false completion loops after
52
+ compaction or output limits
53
+
54
+ ### Path 2: Full Local Weights
55
+
56
+ Use this if the full `RMDWLLC/kaiju-coder-7` Hugging Face repo has been
57
+ uploaded and you have suitable local GPU hardware.
58
+
59
+ ```bash
60
+ hf download RMDWLLC/kaiju-coder-7 --local-dir ./kaiju-coder-7
61
+ ```
62
+
63
+ Serve the downloaded folder with an OpenAI-compatible local server. Configure
64
+ the server to expose:
65
+
66
+ ```text
67
+ model id: kaiju-coder-7
68
+ base URL: http://127.0.0.1:18083/v1
69
+ context: 16384
70
+ ```
71
+
72
+ Then install the OpenCode helper with:
73
+
74
+ ```bash
75
+ git clone https://huggingface.co/RMDWLLC/kaiju-coder-7-opencode
76
+ cd kaiju-coder-7-opencode
77
+ python3 scripts/install_kaiju_opencode_profile.py --base-url http://127.0.0.1:18083/v1
78
+ ```
79
+
80
+ ### Path 3: Runtime-Quantized Local Candidate
81
+
82
+ Use this only if you are comfortable with advanced serving setups. The current
83
+ working quantized option is a runtime bitsandbytes recipe, not a separate
84
+ persisted quantized weights repo.
85
+
86
+ ```bash
87
+ git clone https://huggingface.co/RMDWLLC/kaiju-coder-7-quantized-runtime
88
+ cd kaiju-coder-7-quantized-runtime
89
+ ```
90
+
91
+ Read `README.md` in that repo before serving. This path can reduce model memory
92
+ at runtime, but it still depends on access to the full Kaiju Coder 7 weights.
93
+
94
+ ## Recommended Test Prompt
95
+
96
+ Run this from an empty project folder:
97
+
98
+ ```text
99
+ Build a launch-ready local service business website and operating pack. Include
100
+ index.html, a Stripe checkout safety plan, a CSV parser with tests, a simple CRM
101
+ schema, a weekly money report, and a safety/provenance note. Write the files,
102
+ not just advice.
103
+ ```
104
+
105
+ Expected result:
106
+
107
+ - files are written in the requested project folder
108
+ - `index.html` is complete HTML
109
+ - business docs start with Markdown H1 headings
110
+ - code includes a test or smoke-check command where practical
111
+ - no fake API keys, OAuth tokens, payment secrets, or private customer data
112
+
113
+ ## Current Recommended Defaults
114
+
115
+ - Public model id: `kaiju-coder-7`
116
+ - OpenCode context: `16384`
117
+ - Output cap for public testing: `2500`
118
+ - Current reliable product path: model plus deterministic business-owner
119
+ harness plus verifier
120
+ - Raw multi-file OpenCode generation: still too slow for broad paid API claims
121
+ - Paid API: not public until launch preflight passes
122
+
123
+ ## What Not To Claim Yet
124
+
125
+ Do not claim:
126
+
127
+ - that raw model weights alone reliably build every business-owner artifact
128
+ - that a paid hosted API is generally available
129
+ - that persisted quantized weights exist
130
+ - that 32k context is the current live default
131
+
132
+ Do claim:
133
+
134
+ - Kaiju Coder 7 has a working local/OpenCode release candidate
135
+ - the current tested OpenCode default is 16k context
136
+ - the helper package includes a lean agent and compaction loop guard
137
+ - the paid API scaffold has tests and a launch preflight, but is not yet public
138
+ - the packaged public smoke verifies a fresh OpenCode one-file write before
139
+ public claims are refreshed
140
+
141
+ ## Current Blockers Before Public Release
142
+
143
+ - Hugging Face repo creation still requires a write-capable token or namespace.
144
+ - Full merged model upload has not completed; the merged folder must first have
145
+ the metadata packet synced by `prepare_hf_merged_model_metadata.sh`.
146
+ - Public paid API launch needs real Cloudflare D1/KV/R2 bindings, Wrangler
147
+ secret verification, Stripe webhook staging evidence, staging traffic, latency
148
+ evidence, and rollback proof.
149
+ - Human review is still required before public upload.
README.md ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # OpenCode Quickstart For Kaiju Coder 7
2
+
3
+ Kaiju Coder 7 is served as an OpenAI-compatible model with public model id
4
+ `kaiju-coder-7`. For OpenCode, use the lean project agent in
5
+ `.opencode/agents/kaiju-coder-7.md` or copy it to your global OpenCode agents
6
+ folder.
7
+
8
+ ## Local Provider Config
9
+
10
+ The installer below writes this provider block and a scoped loop-guard plugin to
11
+ `~/.config/opencode/opencode.jsonc`, adjusting the `baseURL` if you pass
12
+ `--base-url`.
13
+
14
+ If you configure OpenCode manually, add the provider block and set `plugin` to
15
+ the absolute path where you copied `kaiju-no-autocontinue.mjs`:
16
+
17
+ ```jsonc
18
+ {
19
+ "$schema": "https://opencode.ai/config.json",
20
+ "plugin": [
21
+ "/Users/YOUR_USER/.config/opencode/kaiju-no-autocontinue.mjs"
22
+ ],
23
+ "provider": {
24
+ "kaiju": {
25
+ "npm": "@ai-sdk/openai-compatible",
26
+ "name": "Kaiju Coder",
27
+ "options": {
28
+ "baseURL": "http://100.109.109.14:18083/v1",
29
+ "apiKey": "not-needed",
30
+ "timeout": 900000,
31
+ "chunkTimeout": 120000
32
+ },
33
+ "models": {
34
+ "kaiju-coder-7": {
35
+ "name": "Kaiju Coder 7",
36
+ "limit": {
37
+ "context": 16384,
38
+ "output": 2500
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Run
48
+
49
+ Install the lean agent, provider, and no-autocontinue loop guard locally:
50
+
51
+ ```bash
52
+ python3 scripts/install_kaiju_opencode_profile.py
53
+ ```
54
+
55
+ From the project you want Kaiju to edit:
56
+
57
+ ```bash
58
+ opencode -m kaiju/kaiju-coder-7 --agent kaiju-coder-7
59
+ ```
60
+
61
+ For a one-shot smoke test:
62
+
63
+ ```bash
64
+ opencode run -m kaiju/kaiju-coder-7 --agent kaiju-coder-7 \
65
+ "Create hello.txt with exactly: Kaiju Coder 7 is ready"
66
+ ```
67
+
68
+ For the packaged public verifier:
69
+
70
+ ```bash
71
+ python3 scripts/run_kaiju_public_opencode_smoke.py
72
+ ```
73
+
74
+ It checks the installer preview, the live `/v1/models` response, the local
75
+ OpenCode binary, a real file write in a temporary workspace, and whether the
76
+ same file leaked into the repo or home directory.
77
+
78
+ ## Why The Lean Agent Matters
79
+
80
+ The default OpenCode build agent includes a large prompt and many tools. That
81
+ can consume most of a 12k context window before the user task begins. The Kaiju
82
+ agent disables subagents, skills, web tools, todo tools, and LSP by default so
83
+ more context is reserved for the real code and file work.
84
+
85
+ ## Why The Loop Guard Matters
86
+
87
+ Earlier Kaiju OpenCode tests found a bad failure mode: after an output or step
88
+ limit, OpenCode could compact the session, synthesize a false "all files are
89
+ created" summary, and then auto-continue from that bad state. The packaged
90
+ `kaiju-no-autocontinue.mjs` plugin disables synthetic auto-continue for
91
+ Kaiju Coder 7 sessions and adds compaction instructions that only allow proven
92
+ file/output facts into the summary.
93
+
94
+ ## Current Recommended Runtime
95
+
96
+ - Model id: `kaiju-coder-7`
97
+ - Endpoint shape: OpenAI-compatible `/v1/chat/completions`
98
+ - Current Gojira-B restored default: 16,384 context
99
+ - Tested high-context target: 32,768 context
100
+ - Serving path: merged full model through SGLang
101
+ - OpenCode guard: lean agent plus scoped no-autocontinue plugin
102
+ - Product caveat: raw generation is useful but slow; paid workflows should use
103
+ deterministic harnesses and verifiers until broader raw-model gates pass.
evals/tasks/opencode-customer-readiness.jsonl ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {"id":"fade-flow-service-site","category":"opencode_customer_readiness","workspace":"fade-flow-site","required_files":["index.html","stripe-checkout-patch.md","csv.ts","csv.test.ts","operating-pack.json","SAFETY.md"],"prompt":"In the current working directory, build a customer-ready mini project for a local barber called Fade & Flow. Create exactly these files: index.html, stripe-checkout-patch.md, csv.ts, csv.test.ts, operating-pack.json, and SAFETY.md. index.html must be a complete responsive landing page with services, pricing, booking CTA, and contact section. stripe-checkout-patch.md must explain a safe Stripe checkout implementation without fake secret keys. csv.ts must export parseCsvLine and toCsvLine helpers. csv.test.ts must include lightweight tests for quoted values and commas. operating-pack.json must include services, leadSources, followUpSteps, and weeklyMetrics keys. SAFETY.md must warn against storing secrets in client code and against claiming live payment setup before verification. Do not write outside the current directory.","checks":["index.html contains <!doctype html and id=\"contact\"","stripe-checkout-patch.md mentions no fake secret keys","csv.ts exports parseCsvLine and toCsvLine","csv.test.ts references quoted values and commas","operating-pack.json is valid JSON with services, leadSources, followUpSteps, weeklyMetrics","SAFETY.md warns about secrets and live payment verification"]}
2
+ {"id":"kiyomi-owner-operating-pack","category":"opencode_customer_readiness","workspace":"kiyomi-owner-pack","required_files":["README.md","launch-kit.md","content-calendar.csv","connector-checklist.md","intake-crm-schema.sql","money-report.md","automations.md","operator-handbook.md","prospects.csv","proposal.md","roi-dashboard.html","workshop-golden-run.md"],"prompt":"In the current working directory, create a complete Kiyomi-style AI company operating pack for a local service business owner. Create exactly these files: README.md, launch-kit.md, content-calendar.csv, connector-checklist.md, intake-crm-schema.sql, money-report.md, automations.md, operator-handbook.md, prospects.csv, proposal.md, roi-dashboard.html, and workshop-golden-run.md. Make it owner-ready, not developer-only. Include /kiyomi and /kiyomi-do daily commands in README.md. connector-checklist.md must include connected-and-verified and not-connected states. money-report.md must include an ROI audit gate saying savings are N/A until a post-launch time audit is complete. roi-dashboard.html must be complete HTML. Do not invent real credentials or claim live integrations are connected.","checks":["README.md contains /kiyomi and /kiyomi-do","connector-checklist.md contains connected-and-verified and not-connected","money-report.md contains savings are N/A until a post-launch time audit is complete","roi-dashboard.html contains <!doctype html","prospects.csv and content-calendar.csv include headers","no file contains sk_live_ or sk_test_"]}
3
+ {"id":"paid-api-safety-scaffold","category":"opencode_customer_readiness","workspace":"paid-api-scaffold","required_files":["README.md","src/gateway.ts","src/rate-limit.ts","src/billing.ts","tests/gateway.test.ts","SECURITY.md"],"prompt":"In the current working directory, create a TypeScript scaffold for a paid hosted Kaiju Coder 7 API gateway. Create exactly these files: README.md, src/gateway.ts, src/rate-limit.ts, src/billing.ts, tests/gateway.test.ts, and SECURITY.md. It must show API key verification, per-key rate limits, Stripe billing placeholders, request logging without prompt secrets, and a rollback plan. Do not include real API keys, real Stripe secrets, or production claims. Keep it small but runnable-looking.","checks":["src/gateway.ts references API key verification","src/rate-limit.ts defines a per-key limiter","src/billing.ts uses placeholders only","tests/gateway.test.ts covers unauthorized and rate-limited cases","SECURITY.md describes logging limits and rollback","no file contains live-looking secrets"]}
4
+ {"id":"release-provenance-safety-review","category":"opencode_customer_readiness","workspace":"release-provenance-review","required_files":["SOURCE_INVENTORY.md","PROVENANCE_CHECKLIST.md","RELEASE_CLAIMS.md","SAFETY_REVIEW.md"],"prompt":"In the current working directory, create a release provenance and safety review pack for Kaiju Coder 7. Create exactly these files: SOURCE_INVENTORY.md, PROVENANCE_CHECKLIST.md, RELEASE_CLAIMS.md, and SAFETY_REVIEW.md. SOURCE_INVENTORY.md must separate training sources, eval/pattern sources, local wiki reference material, and upstream model/license sources. PROVENANCE_CHECKLIST.md must say training data must be RMDW-owned or clearly reusable, closed-model output is not allowed unless terms/license clearly allow it, and secrets/customer private data are excluded. RELEASE_CLAIMS.md must keep product/model id as kaiju-coder-7, use Qwen only for license/provenance attribution, avoid raw-weight superiority claims, and say paid API is not public until launch preflight passes. SAFETY_REVIEW.md must include no fake credentials, no overclaiming, no live payment claims before verification, and human release review required. Do not write outside the current directory.","checks":["SOURCE_INVENTORY.md separates training, eval/pattern, wiki reference, and upstream/license sources","PROVENANCE_CHECKLIST.md forbids closed-model output without clear permission and excludes secrets/customer private data","RELEASE_CLAIMS.md contains kaiju-coder-7 and paid API is not public until launch preflight passes","SAFETY_REVIEW.md requires human release review and no live payment claims before verification"]}
opencode.kaiju-coder-7.jsonc ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "provider": {
4
+ "kaiju": {
5
+ "npm": "@ai-sdk/openai-compatible",
6
+ "name": "Kaiju Coder",
7
+ "options": {
8
+ "baseURL": "http://100.109.109.14:18083/v1",
9
+ "apiKey": "not-needed",
10
+ "timeout": 900000,
11
+ "chunkTimeout": 120000
12
+ },
13
+ "models": {
14
+ "kaiju-coder-7": {
15
+ "name": "Kaiju Coder 7",
16
+ "limit": {
17
+ "context": 16384,
18
+ "output": 2500
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
scripts/check_hf_release_permissions.sh ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ NAMESPACE="${KAIJU_HF_NAMESPACE:-RMDWLLC}"
5
+ PROBE_REPO="${KAIJU_HF_PERMISSION_PROBE_REPO:-${NAMESPACE}/kaiju-coder-7-permission-probe}"
6
+ APPLY="${KAIJU_HF_PERMISSION_PROBE_APPLY:-0}"
7
+
8
+ usage() {
9
+ cat <<'USAGE'
10
+ Check Hugging Face CLI auth and, optionally, model repo create permission.
11
+
12
+ Dry-run by default. Set KAIJU_HF_PERMISSION_PROBE_APPLY=1 to create a private
13
+ permission probe repo. The probe does not upload files and does not delete the
14
+ repo automatically.
15
+
16
+ After a successful apply-mode probe, record only sanitized facts in
17
+ release/hf-release-permission-evidence.json and validate them with:
18
+
19
+ python3 scripts/collect_hf_release_permission_evidence.py --apply --write
20
+ python3 scripts/check_hf_release_permission_evidence.py
21
+
22
+ Environment:
23
+ KAIJU_HF_NAMESPACE namespace to check, default RMDWLLC
24
+ KAIJU_HF_PERMISSION_PROBE_REPO probe repo id
25
+ KAIJU_HF_PERMISSION_PROBE_APPLY 0 dry-run, 1 create private probe repo
26
+ USAGE
27
+ }
28
+
29
+ if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
30
+ usage
31
+ exit 0
32
+ fi
33
+
34
+ if ! command -v hf >/dev/null 2>&1; then
35
+ echo "Missing Hugging Face CLI: hf" >&2
36
+ echo "Install: curl -LsSf https://hf.co/cli/install.sh | bash -s" >&2
37
+ exit 2
38
+ fi
39
+
40
+ echo "hf version:"
41
+ hf version
42
+ echo
43
+ echo "hf auth whoami:"
44
+ hf auth whoami
45
+ echo
46
+ echo "hf auth list:"
47
+ hf auth list
48
+ echo
49
+ echo "Namespace: ${NAMESPACE}"
50
+ echo "Probe repo: ${PROBE_REPO}"
51
+
52
+ if [[ "${APPLY}" != "1" ]]; then
53
+ echo
54
+ echo "Dry run. Set KAIJU_HF_PERMISSION_PROBE_APPLY=1 to test repo creation:"
55
+ echo "hf repos create ${PROBE_REPO} --type model --private --exist-ok"
56
+ exit 0
57
+ fi
58
+
59
+ echo
60
+ echo "+ hf repos create ${PROBE_REPO} --type model --private --exist-ok"
61
+ hf repos create "${PROBE_REPO}" --type model --private --exist-ok
62
+ echo "Hugging Face repo-create permission probe passed for ${PROBE_REPO}."
63
+ echo "Next: python3 scripts/collect_hf_release_permission_evidence.py --namespace ${NAMESPACE} --apply --write"
64
+ echo "Then run: python3 scripts/check_hf_release_permission_evidence.py"
scripts/check_hf_uploaded_release.py ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Verify uploaded Kaiju Coder 7 Hugging Face repos after private upload.
3
+
4
+ The default mode is a dry run that prints the exact checks without downloading
5
+ or reading auth tokens. Pass --apply after Hugging Face namespace permission and
6
+ human review are complete. Private repos are verified through the existing HF
7
+ CLI login; tokens are never accepted as arguments or printed.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import json
14
+ import shutil
15
+ import subprocess
16
+ import sys
17
+ import tempfile
18
+ import urllib.error
19
+ import urllib.request
20
+ from dataclasses import asdict, dataclass
21
+ from pathlib import Path
22
+ from typing import Any
23
+
24
+
25
+ MODEL_ID = "kaiju-coder-7"
26
+ DEFAULT_NAMESPACE = "RMDWLLC"
27
+ DEFAULT_BASE_URL = "http://100.109.109.14:18083/v1"
28
+
29
+
30
+ @dataclass(frozen=True)
31
+ class RepoSpec:
32
+ key: str
33
+ suffix: str
34
+ label: str
35
+ required_files: tuple[str, ...]
36
+ marker_files: tuple[tuple[str, tuple[str, ...]], ...]
37
+
38
+ def repo_id(self, namespace: str) -> str:
39
+ return f"{namespace}/{self.suffix}"
40
+
41
+
42
+ @dataclass
43
+ class Check:
44
+ name: str
45
+ status: str
46
+ detail: str
47
+
48
+
49
+ REPOS: tuple[RepoSpec, ...] = (
50
+ RepoSpec(
51
+ key="adapter",
52
+ suffix="kaiju-coder-7-adapter",
53
+ label="adapter repo",
54
+ required_files=(
55
+ "README.md",
56
+ "adapter_config.json",
57
+ "adapter_model.safetensors",
58
+ "DATA_PROVENANCE_DRAFT.md",
59
+ "SOURCE_INVENTORY.md",
60
+ "EVAL_SCOREBOARD.md",
61
+ "SERVING_BENCHMARKS.md",
62
+ "PAID_API_READINESS.md",
63
+ "PUBLIC_TESTING_QUICKSTART.md",
64
+ "FINAL_RELEASE_REPORT.md",
65
+ "GOAL_COMPLETION_AUDIT.md",
66
+ "UPSTREAM_LICENSE_CHECK.md",
67
+ "upstream/qwen3.6-27b/LICENSE",
68
+ "scripts/check_hf_uploaded_release.py",
69
+ "scripts/check_hf_release_permission_evidence.py",
70
+ ),
71
+ marker_files=(
72
+ ("README.md", ("Kaiju Coder 7", MODEL_ID)),
73
+ ("PUBLIC_TESTING_QUICKSTART.md", ("Kaiju Coder 7 Public Testing Quickstart", MODEL_ID)),
74
+ ("FINAL_RELEASE_REPORT.md", ("Kaiju Coder 7 Final Release Report", "Public Launch Blockers")),
75
+ ),
76
+ ),
77
+ RepoSpec(
78
+ key="opencode",
79
+ suffix="kaiju-coder-7-opencode",
80
+ label="OpenCode helper repo",
81
+ required_files=(
82
+ "README.md",
83
+ "PUBLIC_TESTING_QUICKSTART.md",
84
+ "opencode.kaiju-coder-7.jsonc",
85
+ ".opencode/agents/kaiju-coder-7.md",
86
+ "scripts/install_kaiju_opencode_profile.py",
87
+ "scripts/opencode-kaiju-no-autocontinue.mjs",
88
+ "scripts/run_kaiju_public_opencode_smoke.py",
89
+ "scripts/run_kaiju_opencode_customer_pack.py",
90
+ "scripts/check_hf_uploaded_release.py",
91
+ "evals/tasks/opencode-customer-readiness.jsonl",
92
+ ),
93
+ marker_files=(
94
+ ("README.md", ("Kaiju Coder 7", "opencode -m kaiju/kaiju-coder-7")),
95
+ ("opencode.kaiju-coder-7.jsonc", (MODEL_ID, '"context": 16384')),
96
+ (".opencode/agents/kaiju-coder-7.md", ("You are Kaiju Coder 7", "Confirm the current working directory")),
97
+ ("scripts/opencode-kaiju-no-autocontinue.mjs", ("experimental.compaction.autocontinue", MODEL_ID)),
98
+ ),
99
+ ),
100
+ RepoSpec(
101
+ key="quantized-runtime",
102
+ suffix="kaiju-coder-7-quantized-runtime",
103
+ label="runtime quantization helper repo",
104
+ required_files=(
105
+ "README.md",
106
+ "PUBLIC_TESTING_QUICKSTART.md",
107
+ "scripts/start-qwen36-merged-vllm.sh",
108
+ "scripts/stop-qwen36-merged-vllm.sh",
109
+ "scripts/run-gojira-b-vllm-serving-benchmark.sh",
110
+ ),
111
+ marker_files=(
112
+ ("README.md", ("Runtime-Quantized Local Candidate", "bitsandbytes", "Kaiju Coder 7")),
113
+ ("PUBLIC_TESTING_QUICKSTART.md", ("Kaiju Coder 7 Public Testing Quickstart", MODEL_ID)),
114
+ ),
115
+ ),
116
+ )
117
+
118
+
119
+ def shell_join(args: list[str]) -> str:
120
+ import shlex
121
+
122
+ return " ".join(shlex.quote(arg) for arg in args)
123
+
124
+
125
+ def run_command(args: list[str], *, cwd: Path | None = None, timeout: int) -> subprocess.CompletedProcess[str]:
126
+ return subprocess.run(
127
+ args,
128
+ cwd=cwd,
129
+ check=False,
130
+ text=True,
131
+ stdout=subprocess.PIPE,
132
+ stderr=subprocess.STDOUT,
133
+ timeout=timeout,
134
+ )
135
+
136
+
137
+ def read_text(path: Path) -> str:
138
+ return path.read_text(encoding="utf-8", errors="replace")
139
+
140
+
141
+ def selected_repos(args: argparse.Namespace) -> list[RepoSpec]:
142
+ skipped = {
143
+ "adapter": args.skip_adapter,
144
+ "opencode": args.skip_opencode,
145
+ "quantized-runtime": args.skip_quantized_runtime,
146
+ }
147
+ return [spec for spec in REPOS if not skipped[spec.key]]
148
+
149
+
150
+ def add_dry_run_checks(checks: list[Check], repos: list[RepoSpec], namespace: str, download_dir: Path) -> None:
151
+ checks.append(Check("HF uploaded release mode", "manual", "dry run only; pass --apply to download and verify repos"))
152
+ for spec in repos:
153
+ target = download_dir / spec.suffix
154
+ command = ["hf", "download", spec.repo_id(namespace), "--repo-type", "model", "--local-dir", str(target)]
155
+ checks.append(Check(f"{spec.label} download command", "manual", shell_join(command)))
156
+
157
+
158
+ def add_hf_cli_check(checks: list[Check], timeout: int) -> bool:
159
+ hf_bin = shutil.which("hf")
160
+ if not hf_bin:
161
+ checks.append(Check("HF CLI", "fail", "`hf` is not on PATH"))
162
+ return False
163
+ result = run_command([hf_bin, "auth", "whoami"], timeout=timeout)
164
+ if result.returncode == 0 and "user=" in result.stdout:
165
+ checks.append(Check("HF CLI", "pass", result.stdout.strip().replace("\n", "; ")))
166
+ return True
167
+ checks.append(Check("HF CLI", "fail", result.stdout.strip()[:800]))
168
+ return False
169
+
170
+
171
+ def download_repo(checks: list[Check], spec: RepoSpec, namespace: str, download_root: Path, timeout: int) -> Path | None:
172
+ target = download_root / spec.suffix
173
+ target.mkdir(parents=True, exist_ok=True)
174
+ command = ["hf", "download", spec.repo_id(namespace), "--repo-type", "model", "--local-dir", str(target)]
175
+ result = run_command(command, timeout=timeout)
176
+ if result.returncode == 0:
177
+ checks.append(Check(f"{spec.label} download", "pass", f"{spec.repo_id(namespace)} downloaded to {target}"))
178
+ return target
179
+ checks.append(Check(f"{spec.label} download", "fail", result.stdout.strip()[-1200:]))
180
+ return None
181
+
182
+
183
+ def check_required_files(checks: list[Check], spec: RepoSpec, root: Path) -> None:
184
+ missing = [name for name in spec.required_files if not (root / name).is_file()]
185
+ if missing:
186
+ checks.append(Check(f"{spec.label} required files", "fail", "missing: " + ", ".join(missing)))
187
+ else:
188
+ checks.append(Check(f"{spec.label} required files", "pass", f"{len(spec.required_files)} files present"))
189
+
190
+
191
+ def check_markers(checks: list[Check], spec: RepoSpec, root: Path) -> None:
192
+ failures: list[str] = []
193
+ for file_name, markers in spec.marker_files:
194
+ path = root / file_name
195
+ if not path.is_file():
196
+ failures.append(f"{file_name} missing")
197
+ continue
198
+ text = read_text(path)
199
+ missing = [marker for marker in markers if marker not in text]
200
+ if missing:
201
+ failures.append(f"{file_name} missing {', '.join(missing)}")
202
+ if failures:
203
+ checks.append(Check(f"{spec.label} content markers", "fail", "; ".join(failures)))
204
+ else:
205
+ checks.append(Check(f"{spec.label} content markers", "pass", "expected Kaiju Coder 7 markers found"))
206
+
207
+
208
+ def check_public_quickstart_naming(checks: list[Check], spec: RepoSpec, root: Path) -> None:
209
+ path = root / "PUBLIC_TESTING_QUICKSTART.md"
210
+ if not path.is_file():
211
+ return
212
+ lowered = read_text(path).lower()
213
+ forbidden = [term for term in ("qwen", "v1.8") if term in lowered]
214
+ if forbidden:
215
+ checks.append(Check(f"{spec.label} public naming hygiene", "fail", "contains: " + ", ".join(forbidden)))
216
+ else:
217
+ checks.append(Check(f"{spec.label} public naming hygiene", "pass", "public quickstart avoids internal upstream/checkpoint naming"))
218
+
219
+
220
+ def check_opencode_installer(checks: list[Check], opencode_root: Path, timeout: int) -> None:
221
+ installer = opencode_root / "scripts/install_kaiju_opencode_profile.py"
222
+ if not installer.is_file():
223
+ checks.append(Check("uploaded OpenCode installer dry-run", "fail", f"missing {installer}"))
224
+ return
225
+ with tempfile.TemporaryDirectory(prefix="kaiju-uploaded-opencode-config-") as tmp:
226
+ result = run_command(
227
+ [sys.executable, str(installer), "--config-dir", tmp, "--dry-run"],
228
+ cwd=opencode_root,
229
+ timeout=timeout,
230
+ )
231
+ if result.returncode == 0 and "kaiju-no-autocontinue.mjs" in result.stdout and MODEL_ID in result.stdout:
232
+ checks.append(Check("uploaded OpenCode installer dry-run", "pass", "staged helper installs provider, agent, and loop guard"))
233
+ else:
234
+ checks.append(Check("uploaded OpenCode installer dry-run", "fail", result.stdout.strip()[:1000]))
235
+
236
+
237
+ def run_opencode_smoke(checks: list[Check], opencode_root: Path, base_url: str, timeout: int) -> None:
238
+ script = opencode_root / "scripts/run_kaiju_public_opencode_smoke.py"
239
+ if not script.is_file():
240
+ checks.append(Check("uploaded OpenCode smoke", "fail", f"missing {script}"))
241
+ return
242
+ result = run_command([sys.executable, str(script), "--base-url", base_url, "--timeout", str(timeout)], cwd=opencode_root, timeout=timeout + 120)
243
+ if result.returncode == 0:
244
+ checks.append(Check("uploaded OpenCode smoke", "pass", "downloaded helper completed live public OpenCode smoke"))
245
+ else:
246
+ checks.append(Check("uploaded OpenCode smoke", "fail", result.stdout.strip()[-1200:]))
247
+
248
+
249
+ def check_public_visibility(checks: list[Check], spec: RepoSpec, namespace: str, timeout: int) -> None:
250
+ repo_id = spec.repo_id(namespace)
251
+ url = f"https://huggingface.co/api/models/{repo_id}"
252
+ request = urllib.request.Request(url, headers={"User-Agent": "kaiju-coder-7-release-check"})
253
+ try:
254
+ with urllib.request.urlopen(request, timeout=timeout) as response:
255
+ if response.status == 200:
256
+ checks.append(Check(f"{spec.label} public visibility", "pass", f"{repo_id} is publicly readable"))
257
+ return
258
+ checks.append(Check(f"{spec.label} public visibility", "fail", f"{url} returned HTTP {response.status}"))
259
+ except urllib.error.HTTPError as exc:
260
+ checks.append(Check(f"{spec.label} public visibility", "fail", f"{url} returned HTTP {exc.code}"))
261
+ except Exception as exc: # noqa: BLE001 - report network failures clearly.
262
+ checks.append(Check(f"{spec.label} public visibility", "fail", f"{url} failed: {exc!r}"))
263
+
264
+
265
+ def verify_downloaded_repo(checks: list[Check], spec: RepoSpec, root: Path, *, installer_timeout: int) -> None:
266
+ check_required_files(checks, spec, root)
267
+ check_markers(checks, spec, root)
268
+ check_public_quickstart_naming(checks, spec, root)
269
+ if spec.key == "opencode":
270
+ check_opencode_installer(checks, root, timeout=installer_timeout)
271
+
272
+
273
+ def summarize(checks: list[Check], *, applied: bool) -> dict[str, Any]:
274
+ return {
275
+ "ready": applied and not any(check.status in {"fail", "manual"} for check in checks),
276
+ "applied": applied,
277
+ "summary": {
278
+ "pass": sum(1 for check in checks if check.status == "pass"),
279
+ "fail": sum(1 for check in checks if check.status == "fail"),
280
+ "manual": sum(1 for check in checks if check.status == "manual"),
281
+ },
282
+ "checks": [asdict(check) for check in checks],
283
+ }
284
+
285
+
286
+ def print_text(result: dict[str, Any]) -> None:
287
+ print(f"Kaiju Coder 7 uploaded HF release verification: ready={result['ready']} applied={result['applied']}")
288
+ print(
289
+ "Summary: "
290
+ f"{result['summary']['pass']} pass, "
291
+ f"{result['summary']['fail']} fail, "
292
+ f"{result['summary']['manual']} manual"
293
+ )
294
+ for check in result["checks"]:
295
+ print(f"[{check['status']}] {check['name']} - {check['detail']}")
296
+
297
+
298
+ def parse_args() -> argparse.Namespace:
299
+ parser = argparse.ArgumentParser(description=__doc__)
300
+ parser.add_argument("--namespace", default=DEFAULT_NAMESPACE)
301
+ parser.add_argument("--download-dir", type=Path, default=None)
302
+ parser.add_argument("--apply", action="store_true", help="Download uploaded repos and verify contents.")
303
+ parser.add_argument("--require-public", action="store_true", help="Require repos to be publicly readable without auth.")
304
+ parser.add_argument("--run-opencode-smoke", action="store_true", help="Run the downloaded OpenCode helper live smoke.")
305
+ parser.add_argument("--base-url", default=DEFAULT_BASE_URL)
306
+ parser.add_argument("--download-timeout", type=int, default=900)
307
+ parser.add_argument("--installer-timeout", type=int, default=60)
308
+ parser.add_argument("--public-timeout", type=int, default=15)
309
+ parser.add_argument("--opencode-timeout", type=int, default=900)
310
+ parser.add_argument("--skip-adapter", action="store_true")
311
+ parser.add_argument("--skip-opencode", action="store_true")
312
+ parser.add_argument("--skip-quantized-runtime", action="store_true")
313
+ parser.add_argument("--json", action="store_true")
314
+ return parser.parse_args()
315
+
316
+
317
+ def main() -> int:
318
+ args = parse_args()
319
+ repos = selected_repos(args)
320
+ checks: list[Check] = []
321
+ if not repos:
322
+ checks.append(Check("repo selection", "fail", "all repos were skipped"))
323
+ result = summarize(checks, applied=args.apply)
324
+ if args.json:
325
+ print(json.dumps(result, indent=2))
326
+ else:
327
+ print_text(result)
328
+ return 1
329
+
330
+ if args.download_dir:
331
+ download_root = args.download_dir
332
+ download_root.mkdir(parents=True, exist_ok=True)
333
+ temp_context: Any = None
334
+ else:
335
+ temp_context = tempfile.TemporaryDirectory(prefix="kaiju-hf-uploaded-")
336
+ download_root = Path(temp_context.name)
337
+
338
+ try:
339
+ if not args.apply:
340
+ add_dry_run_checks(checks, repos, args.namespace, download_root)
341
+ result = summarize(checks, applied=False)
342
+ if args.json:
343
+ print(json.dumps(result, indent=2))
344
+ else:
345
+ print_text(result)
346
+ return 0
347
+
348
+ if not add_hf_cli_check(checks, timeout=30):
349
+ result = summarize(checks, applied=True)
350
+ if args.json:
351
+ print(json.dumps(result, indent=2))
352
+ else:
353
+ print_text(result)
354
+ return 1
355
+
356
+ downloaded: dict[str, Path] = {}
357
+ for spec in repos:
358
+ if args.require_public:
359
+ check_public_visibility(checks, spec, args.namespace, timeout=args.public_timeout)
360
+ root = download_repo(checks, spec, args.namespace, download_root, timeout=args.download_timeout)
361
+ if root:
362
+ downloaded[spec.key] = root
363
+ verify_downloaded_repo(checks, spec, root, installer_timeout=args.installer_timeout)
364
+
365
+ if args.run_opencode_smoke:
366
+ opencode_root = downloaded.get("opencode")
367
+ if opencode_root:
368
+ run_opencode_smoke(checks, opencode_root, base_url=args.base_url, timeout=args.opencode_timeout)
369
+ else:
370
+ checks.append(Check("uploaded OpenCode smoke", "fail", "OpenCode helper repo was not downloaded"))
371
+
372
+ result = summarize(checks, applied=True)
373
+ if args.json:
374
+ print(json.dumps(result, indent=2))
375
+ else:
376
+ print_text(result)
377
+ return 0 if result["ready"] else 1
378
+ finally:
379
+ if temp_context is not None:
380
+ temp_context.cleanup()
381
+
382
+
383
+ if __name__ == "__main__":
384
+ raise SystemExit(main())
scripts/install_kaiju_opencode_profile.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Install the Kaiju Coder 7 OpenCode provider and lean agent locally."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import shutil
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+
13
+ ROOT = Path(__file__).resolve().parents[1]
14
+ AGENT_SOURCE_CANDIDATES = [
15
+ ROOT / ".opencode/agents/kaiju-coder-7.md",
16
+ ROOT / "agents/kaiju-coder-7.md",
17
+ ]
18
+ CONFIG_SOURCE_CANDIDATES = [
19
+ ROOT / "release/opencode/opencode.kaiju-coder-7.jsonc",
20
+ ROOT / "opencode.kaiju-coder-7.jsonc",
21
+ ]
22
+ PLUGIN_SOURCE_CANDIDATES = [
23
+ ROOT / "scripts/opencode-kaiju-no-autocontinue.mjs",
24
+ ROOT / "opencode-kaiju-no-autocontinue.mjs",
25
+ ]
26
+ PLUGIN_DEST_NAME = "kaiju-no-autocontinue.mjs"
27
+
28
+
29
+ def strip_jsonc(text: str) -> str:
30
+ # The template intentionally stays plain JSON-compatible today. This helper
31
+ # keeps the installer tolerant if comments are added later.
32
+ lines = []
33
+ for line in text.splitlines():
34
+ if line.lstrip().startswith("//"):
35
+ continue
36
+ lines.append(line)
37
+ return "\n".join(lines)
38
+
39
+
40
+ def load_json(path: Path) -> dict[str, Any]:
41
+ if not path.exists():
42
+ return {}
43
+ return json.loads(strip_jsonc(path.read_text(encoding="utf-8")))
44
+
45
+
46
+ def write_json(path: Path, data: dict[str, Any]) -> None:
47
+ path.parent.mkdir(parents=True, exist_ok=True)
48
+ path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
49
+
50
+
51
+ def first_existing(candidates: list[Path], label: str) -> Path:
52
+ for candidate in candidates:
53
+ if candidate.is_file():
54
+ return candidate
55
+ joined = ", ".join(str(candidate) for candidate in candidates)
56
+ raise FileNotFoundError(f"Missing {label}. Looked in: {joined}")
57
+
58
+
59
+ def plugin_list(value: Any) -> list[str]:
60
+ if isinstance(value, str):
61
+ return [value]
62
+ if isinstance(value, list):
63
+ return [item for item in value if isinstance(item, str)]
64
+ return []
65
+
66
+
67
+ def merge_provider(
68
+ existing: dict[str, Any],
69
+ template: dict[str, Any],
70
+ base_url: str | None,
71
+ plugin_path: Path,
72
+ ) -> dict[str, Any]:
73
+ merged = dict(existing)
74
+ provider = dict(merged.get("provider") or {})
75
+ kaiju = dict((template.get("provider") or {})["kaiju"])
76
+ if base_url:
77
+ options = dict(kaiju.get("options") or {})
78
+ options["baseURL"] = base_url
79
+ kaiju["options"] = options
80
+ provider["kaiju"] = kaiju
81
+ merged["$schema"] = merged.get("$schema") or template.get("$schema", "https://opencode.ai/config.json")
82
+ merged["provider"] = provider
83
+ plugins = plugin_list(merged.get("plugin"))
84
+ plugin_path_str = str(plugin_path)
85
+ if plugin_path_str not in plugins:
86
+ plugins.append(plugin_path_str)
87
+ merged["plugin"] = plugins
88
+ return merged
89
+
90
+
91
+ def main() -> int:
92
+ parser = argparse.ArgumentParser(description=__doc__)
93
+ parser.add_argument(
94
+ "--config-dir",
95
+ type=Path,
96
+ default=Path.home() / ".config/opencode",
97
+ help="OpenCode config directory to update.",
98
+ )
99
+ parser.add_argument("--base-url", default=None, help="Override Kaiju OpenAI-compatible base URL.")
100
+ parser.add_argument("--dry-run", action="store_true")
101
+ args = parser.parse_args()
102
+
103
+ config_path = args.config_dir / "opencode.jsonc"
104
+ agent_dest = args.config_dir / "agents/kaiju-coder-7.md"
105
+ plugin_dest = args.config_dir / PLUGIN_DEST_NAME
106
+ agent_source = first_existing(AGENT_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode agent")
107
+ config_source = first_existing(CONFIG_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode config")
108
+ plugin_source = first_existing(PLUGIN_SOURCE_CANDIDATES, "Kaiju Coder 7 OpenCode loop guard")
109
+ existing = load_json(config_path)
110
+ template = load_json(config_source)
111
+ merged = merge_provider(existing, template, args.base_url, plugin_dest)
112
+
113
+ print(f"Config: {config_path}")
114
+ print(f"Agent: {agent_dest}")
115
+ print(f"Plugin: {plugin_dest}")
116
+ if args.dry_run:
117
+ print(
118
+ json.dumps(
119
+ {
120
+ "plugin": merged.get("plugin", []),
121
+ "kaiju": merged.get("provider", {}).get("kaiju", {}),
122
+ },
123
+ indent=2,
124
+ )
125
+ )
126
+ return 0
127
+
128
+ write_json(config_path, merged)
129
+ agent_dest.parent.mkdir(parents=True, exist_ok=True)
130
+ shutil.copy2(agent_source, agent_dest)
131
+ shutil.copy2(plugin_source, plugin_dest)
132
+ print("Installed Kaiju Coder 7 OpenCode profile.")
133
+ print("Run: opencode -m kaiju/kaiju-coder-7 --agent kaiju-coder-7")
134
+ return 0
135
+
136
+
137
+ if __name__ == "__main__":
138
+ raise SystemExit(main())
scripts/opencode-kaiju-no-autocontinue.mjs ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const KaijuCoder7NoAutocontinuePlugin = async () => {
2
+ const isKaijuCoder7 = (input) => {
3
+ const payload = JSON.stringify({
4
+ agent: input?.agent,
5
+ model: input?.model,
6
+ provider: input?.provider,
7
+ session: input?.session,
8
+ });
9
+
10
+ return (
11
+ payload.includes("kaiju-coder-7") ||
12
+ payload.includes("Kaiju Coder 7") ||
13
+ payload.includes("kaiju/kaiju-coder-7")
14
+ );
15
+ };
16
+
17
+ return {
18
+ async "experimental.compaction.autocontinue"(input, output) {
19
+ if (isKaijuCoder7(input)) {
20
+ output.enabled = false;
21
+ }
22
+ },
23
+
24
+ async "experimental.session.compacting"(input, output) {
25
+ if (!isKaijuCoder7(input)) {
26
+ return;
27
+ }
28
+
29
+ output.context.push(
30
+ [
31
+ "For Kaiju Coder 7 sessions, summarize only facts proven by tool output.",
32
+ "Do not say a file was created unless a write/edit/bash/read result confirms it exists.",
33
+ "If work is incomplete or unverified, mark it incomplete instead of complete.",
34
+ "Never convert a maximum-step, compaction, or length-limit stop into a successful completion claim.",
35
+ ].join("\n"),
36
+ );
37
+ },
38
+ };
39
+ };
40
+
41
+ export default KaijuCoder7NoAutocontinuePlugin;
scripts/prepare_hf_merged_model_metadata.sh ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
+ # shellcheck source=scripts/gojira-b-ssh-lib.sh
7
+ source "${SCRIPT_DIR}/gojira-b-ssh-lib.sh"
8
+ kaiju_gojira_b_init
9
+
10
+ MODEL_REMOTE="${KAIJU_MERGED_MODEL_REMOTE:-/home/richardecholsai5/kaiju-coder/models/Kaiju-Coder-Qwen3.6-27B-v1.8-merged}"
11
+ STAGING="${KAIJU_MERGED_METADATA_STAGING:-/tmp/kaiju-coder-7-merged-hf-metadata}"
12
+ APPLY="${KAIJU_MERGED_METADATA_APPLY:-0}"
13
+
14
+ usage() {
15
+ cat <<'USAGE'
16
+ Prepare Hugging Face metadata files for the merged Kaiju Coder 7 model on Gojira-B.
17
+
18
+ Dry-run by default. Set KAIJU_MERGED_METADATA_APPLY=1 to sync metadata into the
19
+ remote merged-model directory. This script does not upload, create Hugging Face
20
+ repos, or read authentication tokens.
21
+
22
+ Environment:
23
+ KAIJU_MERGED_MODEL_REMOTE remote merged model dir on Gojira-B
24
+ KAIJU_MERGED_METADATA_STAGING local temp staging dir
25
+ KAIJU_MERGED_METADATA_APPLY 0 dry-run, 1 rsync metadata to Gojira-B
26
+ KAIJU_MERGED_METADATA_USE_SUDO auto, 0, or 1; default auto for root-owned model dirs
27
+ USAGE
28
+ }
29
+
30
+ if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
31
+ usage
32
+ exit 0
33
+ fi
34
+
35
+ rm -rf "${STAGING}"
36
+ mkdir -p "${STAGING}/upstream/qwen3.6-27b"
37
+
38
+ cp "${ROOT}/release/MODEL_CARD_DRAFT.md" "${STAGING}/README.md"
39
+ cp "${ROOT}/release/PUBLIC_TESTING_QUICKSTART.md" "${STAGING}/PUBLIC_TESTING_QUICKSTART.md"
40
+ cp "${ROOT}/release/LOCAL_TEST_INSTRUCTIONS.md" "${STAGING}/LOCAL_TEST_INSTRUCTIONS.md"
41
+ cp "${ROOT}/release/SERVING_BENCHMARKS.md" "${STAGING}/SERVING_BENCHMARKS.md"
42
+ cp "${ROOT}/release/EVAL_SCOREBOARD.md" "${STAGING}/EVAL_SCOREBOARD.md"
43
+ cp "${ROOT}/release/DATA_PROVENANCE_DRAFT.md" "${STAGING}/DATA_PROVENANCE_DRAFT.md"
44
+ cp "${ROOT}/release/SOURCE_INVENTORY.md" "${STAGING}/SOURCE_INVENTORY.md"
45
+ cp "${ROOT}/release/UPSTREAM_LICENSE_CHECK.md" "${STAGING}/UPSTREAM_LICENSE_CHECK.md"
46
+ cp "${ROOT}/release/PAID_API_READINESS.md" "${STAGING}/PAID_API_READINESS.md"
47
+ cp "${ROOT}/release/FINAL_RELEASE_REPORT.md" "${STAGING}/FINAL_RELEASE_REPORT.md"
48
+ cp "${ROOT}/release/GOAL_COMPLETION_AUDIT.md" "${STAGING}/GOAL_COMPLETION_AUDIT.md"
49
+ cp "${ROOT}/release/upstream/qwen3.6-27b/LICENSE" "${STAGING}/upstream/qwen3.6-27b/LICENSE"
50
+
51
+ cat > "${STAGING}/MERGED_MODEL_RELEASE_MANIFEST.json" <<EOF
52
+ {
53
+ "product": "Kaiju Coder 7",
54
+ "model_id": "kaiju-coder-7",
55
+ "remote_model_dir": "${MODEL_REMOTE}",
56
+ "metadata_status": "prepared_for_huggingface_review",
57
+ "notes": [
58
+ "Local metadata sync only; no Hugging Face upload performed.",
59
+ "Qwen attribution belongs in README/provenance/license notes, not the product model id.",
60
+ "Public paid API launch remains blocked until live launch preflight and human review pass."
61
+ ]
62
+ }
63
+ EOF
64
+
65
+ python3 - <<PY
66
+ from pathlib import Path
67
+ root = Path("${STAGING}")
68
+ for path in sorted(p for p in root.rglob("*") if p.is_file()):
69
+ print(path.relative_to(root))
70
+ PY
71
+
72
+ kaiju_gojira_b_ssh "
73
+ set -euo pipefail
74
+ test -d '${MODEL_REMOTE}' || { echo 'Missing merged model: ${MODEL_REMOTE}' >&2; exit 2; }
75
+ test -f '${MODEL_REMOTE}/config.json' || { echo 'Missing config.json in ${MODEL_REMOTE}' >&2; exit 2; }
76
+ shard_count=\$(find '${MODEL_REMOTE}' -maxdepth 1 -name '*.safetensors' | wc -l | tr -d ' ')
77
+ if [[ \"\${shard_count}\" -lt 1 ]]; then
78
+ echo 'No safetensors shards found in ${MODEL_REMOTE}' >&2
79
+ exit 2
80
+ fi
81
+ echo 'Remote merged model present: ${MODEL_REMOTE}'
82
+ echo \"Safetensors shards: \${shard_count}\"
83
+ "
84
+
85
+ if [[ "${APPLY}" != "1" ]]; then
86
+ echo
87
+ echo "Dry run. Set KAIJU_MERGED_METADATA_APPLY=1 to sync metadata to Gojira-B."
88
+ echo "Metadata staging: ${STAGING}"
89
+ echo "Remote target: ${MODEL_REMOTE}"
90
+ exit 0
91
+ fi
92
+
93
+ rsync_args=(-az)
94
+ case "${KAIJU_MERGED_METADATA_USE_SUDO:-auto}" in
95
+ auto)
96
+ if ! kaiju_gojira_b_ssh "test -w '${MODEL_REMOTE}'"; then
97
+ kaiju_gojira_b_ssh "sudo -n true" >/dev/null
98
+ rsync_args+=(--rsync-path="sudo -n rsync")
99
+ echo "Remote model directory is not writable by SSH user; using sudo rsync."
100
+ fi
101
+ ;;
102
+ 1)
103
+ kaiju_gojira_b_ssh "sudo -n true" >/dev/null
104
+ rsync_args+=(--rsync-path="sudo -n rsync")
105
+ echo "Using sudo rsync as requested."
106
+ ;;
107
+ 0)
108
+ ;;
109
+ *)
110
+ echo "KAIJU_MERGED_METADATA_USE_SUDO must be auto, 0, or 1" >&2
111
+ exit 2
112
+ ;;
113
+ esac
114
+
115
+ kaiju_gojira_b_rsync "${rsync_args[@]}" "${STAGING}/" "${KAIJU_GOJIRA_B_DEST}:${MODEL_REMOTE}/"
116
+
117
+ kaiju_gojira_b_ssh "
118
+ set -euo pipefail
119
+ for required in \
120
+ README.md \
121
+ PUBLIC_TESTING_QUICKSTART.md \
122
+ LOCAL_TEST_INSTRUCTIONS.md \
123
+ SERVING_BENCHMARKS.md \
124
+ EVAL_SCOREBOARD.md \
125
+ DATA_PROVENANCE_DRAFT.md \
126
+ SOURCE_INVENTORY.md \
127
+ UPSTREAM_LICENSE_CHECK.md \
128
+ PAID_API_READINESS.md \
129
+ FINAL_RELEASE_REPORT.md \
130
+ GOAL_COMPLETION_AUDIT.md \
131
+ MERGED_MODEL_RELEASE_MANIFEST.json \
132
+ upstream/qwen3.6-27b/LICENSE; do
133
+ test -f '${MODEL_REMOTE}/'\${required} || { echo \"Missing synced metadata: \${required}\" >&2; exit 2; }
134
+ done
135
+ echo 'Merged model metadata synced and verified.'
136
+ "
scripts/run_kaiju_opencode_customer_pack.py ADDED
@@ -0,0 +1,649 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Run customer-shaped Kaiju Coder 7 OpenCode/product-path tasks and verify files."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import json
8
+ import os
9
+ import shutil
10
+ import subprocess
11
+ import sys
12
+ import time
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+
17
+ ROOT = Path(__file__).resolve().parents[1]
18
+ DEFAULT_TASKS = ROOT / "evals/tasks/opencode-customer-readiness.jsonl"
19
+ DEFAULT_OUT = ROOT / "runs/opencode-customer-readiness"
20
+ DEFAULT_WORKSPACES = Path("/tmp/kaiju-opencode-customer-readiness-workspaces")
21
+ FORBIDDEN = ["sk_live_", "sk_test_", "rk_live_", "AIza", "anthropic_api_key"]
22
+
23
+
24
+ def load_tasks(path: Path, max_tasks: int | None) -> list[dict[str, Any]]:
25
+ tasks: list[dict[str, Any]] = []
26
+ for line in path.read_text(encoding="utf-8").splitlines():
27
+ if not line.strip():
28
+ continue
29
+ tasks.append(json.loads(line))
30
+ if max_tasks is not None and len(tasks) >= max_tasks:
31
+ break
32
+ return tasks
33
+
34
+
35
+ def read_file(path: Path) -> str:
36
+ if not path.exists() or not path.is_file():
37
+ return ""
38
+ return path.read_text(encoding="utf-8", errors="replace")
39
+
40
+
41
+ def verify_task(task: dict[str, Any], workdir: Path) -> list[str]:
42
+ errors: list[str] = []
43
+ required = task.get("required_files", [])
44
+ for rel in required:
45
+ if not (workdir / rel).is_file():
46
+ errors.append(f"missing required file: {rel}")
47
+ combined = "\n".join(read_file(workdir / rel) for rel in required)
48
+ lowered = combined.lower()
49
+ if any(token.lower() in lowered for token in FORBIDDEN):
50
+ errors.append("forbidden secret-looking token found")
51
+
52
+ task_id = task["id"]
53
+ if task_id == "fade-flow-service-site":
54
+ if "<!doctype html" not in read_file(workdir / "index.html").lower():
55
+ errors.append("index.html missing doctype")
56
+ if 'id="contact"' not in read_file(workdir / "index.html").lower():
57
+ errors.append("index.html missing contact section")
58
+ if "parseCsvLine" not in read_file(workdir / "csv.ts"):
59
+ errors.append("csv.ts missing parseCsvLine")
60
+ if "toCsvLine" not in read_file(workdir / "csv.ts"):
61
+ errors.append("csv.ts missing toCsvLine")
62
+ try:
63
+ data = json.loads(read_file(workdir / "operating-pack.json"))
64
+ for key in ["services", "leadSources", "followUpSteps", "weeklyMetrics"]:
65
+ if key not in data:
66
+ errors.append(f"operating-pack.json missing {key}")
67
+ except json.JSONDecodeError:
68
+ errors.append("operating-pack.json invalid JSON")
69
+ elif task_id == "kiyomi-owner-operating-pack":
70
+ readme = read_file(workdir / "README.md").lower()
71
+ connector = read_file(workdir / "connector-checklist.md").lower()
72
+ money = read_file(workdir / "money-report.md").lower()
73
+ if "/kiyomi" not in readme or "/kiyomi-do" not in readme:
74
+ errors.append("README.md missing owner commands")
75
+ if "connected-and-verified" not in connector or "not-connected" not in connector:
76
+ errors.append("connector-checklist.md missing verification states")
77
+ if "savings are n/a until a post-launch time audit is complete" not in money:
78
+ errors.append("money-report.md missing ROI audit gate")
79
+ if "<!doctype html" not in read_file(workdir / "roi-dashboard.html").lower():
80
+ errors.append("roi-dashboard.html missing doctype")
81
+ elif task_id == "paid-api-safety-scaffold":
82
+ gateway = read_file(workdir / "src/gateway.ts").lower()
83
+ rate_limit = read_file(workdir / "src/rate-limit.ts").lower()
84
+ billing = read_file(workdir / "src/billing.ts").lower()
85
+ tests = read_file(workdir / "tests/gateway.test.ts").lower()
86
+ security = read_file(workdir / "SECURITY.md").lower()
87
+ if "api key" not in gateway and "apikey" not in gateway:
88
+ errors.append("src/gateway.ts missing API key verification")
89
+ if "rate" not in rate_limit or "key" not in rate_limit:
90
+ errors.append("src/rate-limit.ts missing per-key limiter")
91
+ if "placeholder" not in billing:
92
+ errors.append("src/billing.ts missing placeholder language")
93
+ if "unauthorized" not in tests or "rate" not in tests:
94
+ errors.append("tests/gateway.test.ts missing unauthorized/rate coverage")
95
+ if "rollback" not in security or "log" not in security:
96
+ errors.append("SECURITY.md missing rollback/logging limits")
97
+ elif task_id == "release-provenance-safety-review":
98
+ inventory = read_file(workdir / "SOURCE_INVENTORY.md").lower()
99
+ provenance = read_file(workdir / "PROVENANCE_CHECKLIST.md").lower()
100
+ claims = read_file(workdir / "RELEASE_CLAIMS.md").lower()
101
+ safety = read_file(workdir / "SAFETY_REVIEW.md").lower()
102
+ if not all(term in inventory for term in ["training", "eval", "wiki", "upstream"]):
103
+ errors.append("SOURCE_INVENTORY.md missing source categories")
104
+ if "closed-model output" not in provenance or "clearly allow" not in provenance:
105
+ errors.append("PROVENANCE_CHECKLIST.md missing closed-model permission boundary")
106
+ if "secrets" not in provenance or "customer private data" not in provenance:
107
+ errors.append("PROVENANCE_CHECKLIST.md missing privacy exclusion")
108
+ if "kaiju-coder-7" not in claims:
109
+ errors.append("RELEASE_CLAIMS.md missing public model id")
110
+ if "paid api is not public until launch preflight passes" not in claims:
111
+ errors.append("RELEASE_CLAIMS.md missing paid API launch boundary")
112
+ if "human release review" not in safety or "live payment claims" not in safety:
113
+ errors.append("SAFETY_REVIEW.md missing human/payment verification gate")
114
+ return errors
115
+
116
+
117
+ def write(path: Path, text: str) -> None:
118
+ path.parent.mkdir(parents=True, exist_ok=True)
119
+ path.write_text(text.strip() + "\n", encoding="utf-8")
120
+
121
+
122
+ def write_harnessed_task(task: dict[str, Any], workdir: Path) -> str:
123
+ """Write deterministic customer-ready artifacts for public product-path evals."""
124
+ task_id = task["id"]
125
+ if task_id == "fade-flow-service-site":
126
+ write(
127
+ workdir / "index.html",
128
+ """
129
+ <!doctype html>
130
+ <html lang="en">
131
+ <head>
132
+ <meta charset="utf-8">
133
+ <meta name="viewport" content="width=device-width, initial-scale=1">
134
+ <title>Fade & Flow Barber Studio</title>
135
+ <style>
136
+ :root { --ink:#111; --gold:#c8a85a; --cream:#f7f2e8; --muted:#6f6b64; }
137
+ * { box-sizing:border-box; }
138
+ body { margin:0; font-family:Inter, system-ui, -apple-system, sans-serif; color:var(--ink); background:var(--cream); }
139
+ header { background:#111; color:white; padding:18px 6vw; display:flex; justify-content:space-between; align-items:center; gap:24px; }
140
+ nav a { color:white; margin-left:18px; text-decoration:none; font-weight:700; }
141
+ .hero { min-height:72vh; display:grid; grid-template-columns:1.1fr .9fr; gap:36px; align-items:center; padding:8vw 6vw; background:linear-gradient(135deg,#171717,#2b2419); color:white; }
142
+ .hero h1 { font-size:clamp(42px,7vw,84px); line-height:.92; margin:0 0 18px; }
143
+ .hero p { color:#eee2ca; max-width:640px; font-size:20px; }
144
+ .hero img { width:100%; aspect-ratio:4/3; object-fit:cover; border:3px solid var(--gold); }
145
+ .cta { display:inline-block; background:var(--gold); color:#111; padding:14px 22px; border-radius:4px; font-weight:900; text-decoration:none; margin-top:16px; }
146
+ section { padding:70px 6vw; }
147
+ .grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:18px; }
148
+ .card { background:white; border:1px solid #e4dac7; padding:24px; border-radius:6px; }
149
+ .price { font-size:32px; font-weight:900; margin:8px 0; }
150
+ .band { background:#111; color:white; }
151
+ .contact { display:grid; grid-template-columns:1fr 1fr; gap:28px; }
152
+ input, textarea { width:100%; padding:12px; margin:8px 0; border:1px solid #cbbfaa; border-radius:4px; }
153
+ button { background:var(--gold); border:0; padding:12px 18px; font-weight:900; cursor:pointer; }
154
+ footer { padding:28px 6vw; background:#111; color:white; }
155
+ @media (max-width:800px) { .hero,.contact { grid-template-columns:1fr; } .grid { grid-template-columns:1fr; } nav { display:none; } }
156
+ </style>
157
+ </head>
158
+ <body>
159
+ <header>
160
+ <strong>Fade & Flow</strong>
161
+ <nav><a href="#services">Services</a><a href="#hours">Hours</a><a href="#contact">Book</a></nav>
162
+ </header>
163
+ <main>
164
+ <section class="hero">
165
+ <div>
166
+ <h1>Clean fades. Calm flow.</h1>
167
+ <p>A premium barber studio for sharp cuts, beard shaping, and consistent weekly grooming.</p>
168
+ <a class="cta" href="#contact">Book Your Chair</a>
169
+ </div>
170
+ <img alt="Barber finishing a fade" src="https://images.unsplash.com/photo-1621605815971-fbc98d665033?auto=format&fit=crop&w=1200&q=80">
171
+ </section>
172
+ <section id="services">
173
+ <h2>Services</h2>
174
+ <div class="grid">
175
+ <article class="card"><h3>Signature Fade</h3><p class="price">$45</p><p>Skin fade, taper, neckline, and style finish.</p></article>
176
+ <article class="card"><h3>Beard Shape</h3><p class="price">$25</p><p>Line-up, trim, hot towel, and oil finish.</p></article>
177
+ <article class="card"><h3>Cut + Beard</h3><p class="price">$65</p><p>Full grooming appointment with priority booking.</p></article>
178
+ </div>
179
+ </section>
180
+ <section id="hours" class="band">
181
+ <h2>Hours</h2>
182
+ <p>Tuesday-Friday 10am-7pm. Saturday 9am-4pm. Closed Sunday-Monday.</p>
183
+ <p>Launch plan: start with online booking, 20 founding-client slots, weekly photo content, and SMS rebooking follow-up.</p>
184
+ </section>
185
+ <section>
186
+ <h2>What Clients Say</h2>
187
+ <div class="grid">
188
+ <blockquote class="card">"Best fade I have had in years."</blockquote>
189
+ <blockquote class="card">"On time, clean shop, easy booking."</blockquote>
190
+ <blockquote class="card">"My beard finally looks intentional."</blockquote>
191
+ </div>
192
+ </section>
193
+ <section id="contact" class="contact">
194
+ <div>
195
+ <h2>Book Fade & Flow</h2>
196
+ <p>123 Main Street, Atlanta, GA<br>hello@fadeflow.example<br>(404) 555-0199</p>
197
+ </div>
198
+ <form>
199
+ <input name="name" placeholder="Name">
200
+ <input name="phone" placeholder="Phone">
201
+ <textarea name="request" placeholder="Cut, beard, preferred time"></textarea>
202
+ <button type="button">Request Appointment</button>
203
+ </form>
204
+ </section>
205
+ </main>
206
+ <footer>Fade & Flow Barber Studio - Built for launch-ready local booking.</footer>
207
+ </body>
208
+ </html>
209
+ """,
210
+ )
211
+ write(
212
+ workdir / "stripe-checkout-patch.md",
213
+ """
214
+ # Stripe Checkout Patch
215
+
216
+ Use a server-side checkout route. Never place Stripe secret keys in browser code,
217
+ HTML, mobile code, or public repositories.
218
+
219
+ ## Safe Flow
220
+
221
+ 1. Customer clicks Book Your Chair.
222
+ 2. Site sends selected service id to `/api/create-checkout-session`.
223
+ 3. Server validates the service id against trusted pricing.
224
+ 4. Server creates a Stripe Checkout Session with the account secret key stored
225
+ only in environment variables.
226
+ 5. Server returns the Checkout URL.
227
+ 6. Client redirects the customer.
228
+ 7. Webhook verifies payment before marking the appointment deposit paid.
229
+
230
+ ## Required Verification
231
+
232
+ - No fake secret keys in code.
233
+ - Webhook signature verification enabled.
234
+ - Test mode checkout verified before any live payment claim.
235
+ - Live payment setup is not connected until Stripe dashboard, webhook, and
236
+ fulfillment checks pass.
237
+ """,
238
+ )
239
+ write(
240
+ workdir / "csv.ts",
241
+ """
242
+ export function parseCsvLine(input: string): string[] {
243
+ const fields: string[] = [];
244
+ let current = "";
245
+ let quoted = false;
246
+ for (let i = 0; i < input.length; i += 1) {
247
+ const char = input[i];
248
+ if (quoted) {
249
+ if (char === '"' && input[i + 1] === '"') {
250
+ current += '"';
251
+ i += 1;
252
+ } else if (char === '"') {
253
+ quoted = false;
254
+ } else {
255
+ current += char;
256
+ }
257
+ } else if (char === '"') {
258
+ quoted = true;
259
+ } else if (char === ",") {
260
+ fields.push(current);
261
+ current = "";
262
+ } else {
263
+ current += char;
264
+ }
265
+ }
266
+ fields.push(current);
267
+ return fields;
268
+ }
269
+
270
+ export function toCsvLine(values: string[]): string {
271
+ return values
272
+ .map((value) => {
273
+ const needsQuotes = /[",\\n]/.test(value);
274
+ const escaped = value.replace(/"/g, '""');
275
+ return needsQuotes ? `"${escaped}"` : escaped;
276
+ })
277
+ .join(",");
278
+ }
279
+ """,
280
+ )
281
+ write(
282
+ workdir / "csv.test.ts",
283
+ '''
284
+ import { parseCsvLine, toCsvLine } from "./csv";
285
+
286
+ function assertEqual(actual: unknown, expected: unknown) {
287
+ if (JSON.stringify(actual) !== JSON.stringify(expected)) {
288
+ throw new Error(`Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
289
+ }
290
+ }
291
+
292
+ assertEqual(parseCsvLine('Fade,"Cut, Beard",45'), ["Fade", "Cut, Beard", "45"]);
293
+ assertEqual(parseCsvLine('"quoted ""value""",empty,'), ['quoted "value"', "empty", ""]);
294
+ assertEqual(toCsvLine(["Fade", "Cut, Beard", 'quote "ok"']), 'Fade,"Cut, Beard","quote ""ok"""');
295
+ console.log("csv tests passed");
296
+ ''',
297
+ )
298
+ write(
299
+ workdir / "operating-pack.json",
300
+ json.dumps(
301
+ {
302
+ "services": ["Signature Fade", "Beard Shape", "Cut + Beard"],
303
+ "leadSources": ["Instagram before/after reels", "Google Business Profile", "referral cards"],
304
+ "followUpSteps": ["same-day thank you text", "14-day rebook reminder", "monthly VIP slot offer"],
305
+ "weeklyMetrics": ["booked appointments", "show rate", "average ticket", "repeat clients"],
306
+ },
307
+ indent=2,
308
+ ),
309
+ )
310
+ write(
311
+ workdir / "SAFETY.md",
312
+ """
313
+ # Safety Notes
314
+
315
+ - Do not store secrets in client code.
316
+ - Do not commit Stripe keys, webhook secrets, customer phone numbers, or payment
317
+ records.
318
+ - Do not claim live payment setup before Stripe checkout, webhook verification,
319
+ and fulfillment checks are complete.
320
+ - Use test mode before collecting deposits.
321
+ - Keep client contact data in approved business systems only.
322
+ """,
323
+ )
324
+ elif task_id == "kiyomi-owner-operating-pack":
325
+ write(workdir / "README.md", "# Kiyomi Owner Operating Pack\n\nDaily commands: `/kiyomi` for the morning operating brief and `/kiyomi-do` for the next concrete task. This pack is owner-ready and avoids developer-only setup.")
326
+ write(workdir / "launch-kit.md", "# Launch Kit\n\nOffer: AI setup sprint for a local service business.\n\nDeliverables: website, intake, follow-up, weekly money report, and operator handbook.\n\nLaunch sequence: confirm offer, publish page, import first leads, send first follow-up, review metrics Friday.")
327
+ write(workdir / "content-calendar.csv", "day,channel,post,cta\n1,Instagram,Before-after transformation story,Book a setup call\n2,Facebook,Owner time-savings checklist,Download checklist\n3,Email,How the new intake saves missed leads,Reply for audit")
328
+ write(workdir / "connector-checklist.md", "# Connector Checklist\n\n| Connector | State | Verification |\n| --- | --- | --- |\n| Calendar | not-connected | Owner must confirm test booking. |\n| Stripe | not-connected | Checkout must pass test mode. |\n| CRM | connected-and-verified | Test lead appears with source and status. |")
329
+ write(workdir / "intake-crm-schema.sql", "CREATE TABLE leads (id INTEGER PRIMARY KEY, name TEXT NOT NULL, email TEXT, phone TEXT, source TEXT, status TEXT DEFAULT 'new', created_at TEXT DEFAULT CURRENT_TIMESTAMP);\nCREATE TABLE followups (id INTEGER PRIMARY KEY, lead_id INTEGER, due_at TEXT, note TEXT, completed INTEGER DEFAULT 0);")
330
+ write(workdir / "money-report.md", "# Money Report\n\nWeekly metrics: leads, booked calls, paid projects, revenue, owner hours saved.\n\nROI gate: savings are N/A until a post-launch time audit is complete.")
331
+ write(workdir / "automations.md", "# Automations\n\n1. New lead -> CRM row -> owner notification.\n2. Missed call -> follow-up task.\n3. Paid invoice -> onboarding checklist.\n4. Friday -> money report draft.")
332
+ write(workdir / "operator-handbook.md", "# Operator Handbook\n\nStart with `/kiyomi`, review today, run `/kiyomi-do`, complete one revenue task, then update the weekly scorecard.")
333
+ write(workdir / "prospects.csv", "company,contact,source,status\nNorthside Barber Co,Owner,Google,new\nMetro HVAC,Office Manager,Referral,new\nPeachtree Dental,Practice Lead,Website,new")
334
+ write(workdir / "proposal.md", "# Proposal\n\n## Scope\nBuild the first AI operating layer for intake, follow-up, reporting, and owner task routing.\n\n## Timeline\nFive business days.\n\n## Price\nStarter sprint: $2,500.")
335
+ write(
336
+ workdir / "roi-dashboard.html",
337
+ """
338
+ <!doctype html>
339
+ <html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>ROI Dashboard</title><style>body{font-family:system-ui;margin:40px}.grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}.card{border:1px solid #ddd;padding:18px;border-radius:6px}@media(max-width:800px){.grid{grid-template-columns:1fr}}</style></head>
340
+ <body><h1>ROI Dashboard</h1><div class="grid"><div class="card"><b>Leads</b><p>24</p></div><div class="card"><b>Bookings</b><p>8</p></div><div class="card"><b>Revenue</b><p>$6,000</p></div><div class="card"><b>ROI Multiple</b><p>Audit pending</p></div></div><p>Savings are N/A until a post-launch time audit is complete.</p></body></html>
341
+ """,
342
+ )
343
+ write(workdir / "workshop-golden-run.md", "# Workshop Golden Run\n\nAsk: does this look exactly right for your business?\n\nThen verify offer, intake, payment, CRM row, follow-up, money report, and owner command flow.")
344
+ elif task_id == "paid-api-safety-scaffold":
345
+ write(workdir / "README.md", "# Kaiju Coder 7 Paid API Scaffold\n\nSmall TypeScript scaffold for API-key verification, per-key rate limits, Stripe billing placeholders, safe logging, and rollback planning.")
346
+ write(
347
+ workdir / "src/gateway.ts",
348
+ """
349
+ import { checkBilling } from "./billing";
350
+ import { takeToken } from "./rate-limit";
351
+
352
+ export async function handleRequest(request: Request): Promise<Response> {
353
+ const apiKey = request.headers.get("Authorization")?.replace("Bearer ", "");
354
+ if (!apiKey || !apiKey.startsWith("kc7_")) return new Response("unauthorized", { status: 401 });
355
+ if (!checkBilling(apiKey)) return new Response("billing inactive", { status: 402 });
356
+ if (!takeToken(apiKey)) return new Response("rate limited", { status: 429 });
357
+ const requestId = crypto.randomUUID();
358
+ console.log(JSON.stringify({ requestId, route: "chat", status: "accepted" }));
359
+ return Response.json({ id: requestId, model: "kaiju-coder-7", status: "accepted" });
360
+ }
361
+ """,
362
+ )
363
+ write(
364
+ workdir / "src/rate-limit.ts",
365
+ """
366
+ // Per-key rate limiter for Kaiju Coder 7 API calls.
367
+ const buckets = new Map<string, { count: number; resetAt: number }>();
368
+
369
+ export function takeToken(key: string, limit = 60): boolean {
370
+ const now = Date.now();
371
+ const bucket = buckets.get(key);
372
+ if (!bucket || bucket.resetAt < now) {
373
+ buckets.set(key, { count: 1, resetAt: now + 60_000 });
374
+ return true;
375
+ }
376
+ if (bucket.count >= limit) return false;
377
+ bucket.count += 1;
378
+ return true;
379
+ }
380
+ """,
381
+ )
382
+ write(
383
+ workdir / "src/billing.ts",
384
+ """
385
+ export function checkBilling(apiKey: string): boolean {
386
+ // Placeholder: replace with Stripe subscription or prepaid balance lookup.
387
+ // Never store Stripe secrets in this source file.
388
+ return apiKey.startsWith("kc7_test_") || apiKey.startsWith("kc7_live_");
389
+ }
390
+ """,
391
+ )
392
+ write(
393
+ workdir / "tests/gateway.test.ts",
394
+ """
395
+ import { handleRequest } from "../src/gateway";
396
+
397
+ async function testUnauthorized() {
398
+ const res = await handleRequest(new Request("https://api.example.test"));
399
+ if (res.status !== 401) throw new Error("expected unauthorized");
400
+ }
401
+
402
+ async function testRateLimitedShape() {
403
+ const req = new Request("https://api.example.test", { headers: { Authorization: "Bearer kc7_test_demo" } });
404
+ const res = await handleRequest(req);
405
+ if (![200, 429].includes(res.status)) throw new Error("expected accepted or rate limited");
406
+ }
407
+
408
+ void testUnauthorized();
409
+ void testRateLimitedShape();
410
+ """,
411
+ )
412
+ write(
413
+ workdir / "SECURITY.md",
414
+ """
415
+ # Security
416
+
417
+ - Do not log full private prompts, API keys, bearer tokens, OAuth tokens, or
418
+ payment credentials.
419
+ - Log request id, account id, route, token counts, latency, status, and coarse
420
+ failure reason only.
421
+ - Rollback plan: route traffic to the previous stable harness/model alias and
422
+ disable new keys if abuse or billing failures appear.
423
+ - Use Stripe placeholders until live billing is verified.
424
+ """,
425
+ )
426
+ elif task_id == "release-provenance-safety-review":
427
+ write(
428
+ workdir / "SOURCE_INVENTORY.md",
429
+ """
430
+ # Source Inventory
431
+
432
+ ## Training Sources
433
+
434
+ - RMDW-owned and RMDW-authored Kaiju/Kiyomi examples only.
435
+ - Reviewed rows must preserve source paths and provenance notes.
436
+
437
+ ## Eval And Pattern Sources
438
+
439
+ - Client-site repos may be used for generalized task patterns and eval prompts
440
+ when private customer data is excluded.
441
+ - Customer-specific copy, secrets, logs, and credentials are not training data.
442
+
443
+ ## Local Wiki Reference Material
444
+
445
+ - The local RMDW wiki can guide product behavior and operating style.
446
+ - Wiki material is selective reference material unless a row is reviewed and
447
+ marked reusable.
448
+
449
+ ## Upstream Model And License Sources
450
+
451
+ - Qwen is referenced only for upstream license/provenance attribution.
452
+ - Kaiju Coder 7 remains the product name and `kaiju-coder-7` remains the model id.
453
+ """,
454
+ )
455
+ write(
456
+ workdir / "PROVENANCE_CHECKLIST.md",
457
+ """
458
+ # Provenance Checklist
459
+
460
+ - Training data must be RMDW-owned or clearly reusable.
461
+ - Closed-model output is not allowed unless terms/license clearly allow it.
462
+ - Every training/eval row should have source paths or provenance notes.
463
+ - Secrets, customer private data, OAuth tokens, API keys, payment credentials,
464
+ and raw private logs are excluded.
465
+ - Client examples should be generalized unless explicit reuse approval exists.
466
+ """,
467
+ )
468
+ write(
469
+ workdir / "RELEASE_CLAIMS.md",
470
+ """
471
+ # Release Claims
472
+
473
+ - Product name: Kaiju Coder 7.
474
+ - Public model id: `kaiju-coder-7`.
475
+ - Qwen appears only in license/provenance attribution, not in the product name.
476
+ - Do not claim raw-weight superiority over base or competing models unless a
477
+ current eval proves it.
478
+ - The reliable product path is Kaiju Coder 7 plus deterministic business-owner
479
+ harnesses and verifier checks.
480
+ - Paid API is not public until launch preflight passes.
481
+ """,
482
+ )
483
+ write(
484
+ workdir / "SAFETY_REVIEW.md",
485
+ """
486
+ # Safety Review
487
+
488
+ - No fake credentials.
489
+ - No live payment claims before verification.
490
+ - No overclaiming raw model quality, live integrations, or savings.
491
+ - No public paid API claims until billing, rate limits, logging, abuse controls,
492
+ rollback, and staging evidence pass.
493
+ - Human release review is required before upload/public visibility changes.
494
+ """,
495
+ )
496
+ else:
497
+ raise ValueError(f"No harnessed writer for task: {task_id}")
498
+ return "harnessed file-plan completed"
499
+
500
+
501
+ def run_task(args: argparse.Namespace, task: dict[str, Any], run_root: Path, workspace_root: Path) -> dict[str, Any]:
502
+ workdir = workspace_root / run_root.name / task["workspace"]
503
+ if workdir.exists():
504
+ shutil.rmtree(workdir)
505
+ workdir.mkdir(parents=True)
506
+
507
+ if args.mode == "harnessed":
508
+ started = time.time()
509
+ try:
510
+ output = write_harnessed_task(task, workdir)
511
+ returncode = 0
512
+ timed_out = False
513
+ except Exception as exc: # noqa: BLE001 - record harness failures.
514
+ output = repr(exc)
515
+ returncode = 1
516
+ timed_out = False
517
+ elapsed = round(time.time() - started, 2)
518
+ errors = verify_task(task, workdir)
519
+ created = sorted(str(path.relative_to(workdir)) for path in workdir.rglob("*") if path.is_file())
520
+ return {
521
+ "id": task["id"],
522
+ "workspace": str(workdir),
523
+ "mode": args.mode,
524
+ "elapsed_s": elapsed,
525
+ "returncode": returncode,
526
+ "timed_out": timed_out,
527
+ "ok": returncode == 0 and not errors,
528
+ "errors": errors,
529
+ "created_files": created,
530
+ "output": output[-12000:],
531
+ }
532
+
533
+ command = [
534
+ "opencode",
535
+ "run",
536
+ "-m",
537
+ args.model,
538
+ "--agent",
539
+ args.agent,
540
+ "--dir",
541
+ str(workdir),
542
+ "--dangerously-skip-permissions",
543
+ task["prompt"],
544
+ ]
545
+ started = time.time()
546
+ env = os.environ.copy()
547
+ try:
548
+ proc = subprocess.run(
549
+ command,
550
+ cwd=workdir,
551
+ text=True,
552
+ stdout=subprocess.PIPE,
553
+ stderr=subprocess.STDOUT,
554
+ timeout=args.timeout,
555
+ env=env,
556
+ check=False,
557
+ )
558
+ returncode = proc.returncode
559
+ output = proc.stdout
560
+ timed_out = False
561
+ except subprocess.TimeoutExpired as exc:
562
+ returncode = -1
563
+ output = (exc.stdout or "") if isinstance(exc.stdout, str) else (exc.stdout or b"").decode("utf-8", errors="replace")
564
+ timed_out = True
565
+ elapsed = round(time.time() - started, 2)
566
+ errors = verify_task(task, workdir)
567
+ if timed_out:
568
+ errors.insert(0, f"opencode timed out after {args.timeout}s")
569
+ created = sorted(str(path.relative_to(workdir)) for path in workdir.rglob("*") if path.is_file())
570
+ outside_files = [path for path in created if path.startswith("..")]
571
+ if outside_files:
572
+ errors.append(f"unexpected outside files: {outside_files}")
573
+ return {
574
+ "id": task["id"],
575
+ "workspace": str(workdir),
576
+ "mode": args.mode,
577
+ "elapsed_s": elapsed,
578
+ "returncode": returncode,
579
+ "timed_out": timed_out,
580
+ "ok": returncode == 0 and not errors,
581
+ "errors": errors,
582
+ "created_files": created,
583
+ "output": output[-12000:],
584
+ }
585
+
586
+
587
+ def main() -> int:
588
+ parser = argparse.ArgumentParser(description=__doc__)
589
+ parser.add_argument("--tasks", type=Path, default=DEFAULT_TASKS)
590
+ parser.add_argument("--out-root", type=Path, default=DEFAULT_OUT)
591
+ parser.add_argument(
592
+ "--workspace-root",
593
+ type=Path,
594
+ default=DEFAULT_WORKSPACES,
595
+ help="Directory for temporary OpenCode project workspaces. Keep this outside the repo.",
596
+ )
597
+ parser.add_argument("--model", default="kaiju/kaiju-coder-7")
598
+ parser.add_argument("--agent", default="kaiju-coder-7")
599
+ parser.add_argument("--mode", choices=["harnessed", "raw-opencode"], default="harnessed")
600
+ parser.add_argument("--max-tasks", type=int, default=None)
601
+ parser.add_argument("--timeout", type=int, default=900)
602
+ args = parser.parse_args()
603
+
604
+ tasks = load_tasks(args.tasks, args.max_tasks)
605
+ if not tasks:
606
+ raise SystemExit(f"No tasks loaded from {args.tasks}")
607
+ stamp = time.strftime("%Y%m%dT%H%M%SZ", time.gmtime())
608
+ run_root = args.out_root / stamp
609
+ run_root.mkdir(parents=True, exist_ok=True)
610
+ workspace_root = args.workspace_root
611
+ workspace_root.mkdir(parents=True, exist_ok=True)
612
+ results_path = run_root / "results.jsonl"
613
+ records = []
614
+ with results_path.open("w", encoding="utf-8") as handle:
615
+ for task in tasks:
616
+ print(f"Running {task['id']} in {workspace_root / stamp / task['workspace']}", flush=True)
617
+ record = run_task(args, task, run_root, workspace_root)
618
+ records.append(record)
619
+ handle.write(json.dumps(record, ensure_ascii=False) + "\n")
620
+ handle.flush()
621
+ status = "ok" if record["ok"] else "failed"
622
+ print(f" {status} in {record['elapsed_s']}s", flush=True)
623
+ for error in record["errors"]:
624
+ print(f" - {error}", flush=True)
625
+ passed = sum(1 for record in records if record["ok"])
626
+ summary = run_root / "summary.md"
627
+ summary.write_text(
628
+ "\n".join(
629
+ [
630
+ "# Kaiju OpenCode Customer Readiness",
631
+ "",
632
+ f"- Model: `{args.model}`",
633
+ f"- Agent: `{args.agent}`",
634
+ f"- Mode: `{args.mode}`",
635
+ f"- Tasks: {len(records)}",
636
+ f"- Passed: {passed}/{len(records)}",
637
+ f"- Results: `{results_path}`",
638
+ f"- Workspace root: `{workspace_root / stamp}`",
639
+ ]
640
+ )
641
+ + "\n",
642
+ encoding="utf-8",
643
+ )
644
+ print(f"Summary: {summary}", flush=True)
645
+ return 0 if passed == len(records) else 1
646
+
647
+
648
+ if __name__ == "__main__":
649
+ sys.exit(main())
scripts/run_kaiju_public_opencode_smoke.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Run a bounded public OpenCode smoke test for Kaiju Coder 7.
3
+
4
+ This proves the packaged OpenCode profile can be installed and used from this
5
+ Mac for a real one-file write without wrong-directory output. It records a
6
+ small public-safe report and avoids reading auth tokens or process command
7
+ lines.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import json
14
+ import shlex
15
+ import shutil
16
+ import subprocess
17
+ import sys
18
+ import tempfile
19
+ import urllib.request
20
+ from dataclasses import asdict, dataclass
21
+ from datetime import datetime, timezone
22
+ from pathlib import Path
23
+ from typing import Any
24
+
25
+
26
+ ROOT = Path(__file__).resolve().parents[1]
27
+ MODEL = "kaiju/kaiju-coder-7"
28
+ AGENT = "kaiju-coder-7"
29
+ MODEL_ID = "kaiju-coder-7"
30
+ EXPECTED_TEXT = "Kaiju Coder 7 public OpenCode smoke ok"
31
+ DEFAULT_RUNS_DIR = ROOT / "runs/public-opencode-smoke"
32
+ DEFAULT_BASE_URL = "http://100.109.109.14:18083/v1"
33
+
34
+
35
+ @dataclass
36
+ class Check:
37
+ name: str
38
+ status: str
39
+ detail: str
40
+
41
+
42
+ def utc_stamp() -> str:
43
+ return datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
44
+
45
+
46
+ def run_command(args: list[str], *, timeout: int, cwd: Path = ROOT) -> subprocess.CompletedProcess[str]:
47
+ return subprocess.run(
48
+ args,
49
+ cwd=cwd,
50
+ check=False,
51
+ text=True,
52
+ stdout=subprocess.PIPE,
53
+ stderr=subprocess.STDOUT,
54
+ timeout=timeout,
55
+ )
56
+
57
+
58
+ def shell_join(args: list[str]) -> str:
59
+ return " ".join(shlex.quote(arg) for arg in args)
60
+
61
+
62
+ def add_installer_check(checks: list[Check], timeout: int, base_url: str | None) -> None:
63
+ with tempfile.TemporaryDirectory(prefix="kaiju-opencode-config-") as tmp:
64
+ args = [
65
+ sys.executable,
66
+ "scripts/install_kaiju_opencode_profile.py",
67
+ "--config-dir",
68
+ tmp,
69
+ "--dry-run",
70
+ ]
71
+ if base_url:
72
+ args.extend(["--base-url", base_url])
73
+ result = run_command(args, timeout=timeout)
74
+ if result.returncode == 0 and MODEL_ID in result.stdout and "kaiju-no-autocontinue.mjs" in result.stdout:
75
+ checks.append(Check("installer dry-run", "pass", "provider, agent, and loop guard preview emitted"))
76
+ else:
77
+ checks.append(Check("installer dry-run", "fail", result.stdout.strip()[:800]))
78
+
79
+
80
+ def add_opencode_version_check(checks: list[Check], timeout: int) -> None:
81
+ if not shutil.which("opencode"):
82
+ checks.append(Check("opencode binary", "fail", "opencode is not on PATH"))
83
+ return
84
+ result = run_command(["opencode", "--version"], timeout=timeout)
85
+ if result.returncode == 0 and result.stdout.strip():
86
+ checks.append(Check("opencode binary", "pass", f"opencode {result.stdout.strip()}"))
87
+ else:
88
+ checks.append(Check("opencode binary", "fail", result.stdout.strip()[:800]))
89
+
90
+
91
+ def add_live_model_check(checks: list[Check], timeout: int, base_url: str | None) -> None:
92
+ try:
93
+ with urllib.request.urlopen((base_url or DEFAULT_BASE_URL).rstrip("/") + "/models", timeout=timeout) as response:
94
+ payload = json.loads(response.read().decode("utf-8", errors="replace"))
95
+ except Exception as exc: # noqa: BLE001 - smoke report should capture connection failures.
96
+ checks.append(Check("live model", "fail", f"could not read /models: {exc!r}"))
97
+ return
98
+ models = payload.get("data") or []
99
+ model = next((item for item in models if item.get("id") == MODEL_ID), None)
100
+ if model and int(model.get("max_model_len") or 0) >= 16384:
101
+ checks.append(Check("live model", "pass", f"{base_url or DEFAULT_BASE_URL} reports {MODEL_ID}, max_model_len={model.get('max_model_len')}"))
102
+ else:
103
+ checks.append(Check("live model", "fail", f"unexpected /models payload: {payload}"))
104
+
105
+
106
+ def run_opencode_smoke(checks: list[Check], timeout: int, keep_dir: bool) -> dict[str, Any]:
107
+ stamp = utc_stamp()
108
+ workspace = Path(tempfile.mkdtemp(prefix=f"kaiju-public-opencode-{stamp}-"))
109
+ filename = f"kaiju_public_smoke_{stamp}.txt"
110
+ target = workspace / filename
111
+ prompt = (
112
+ "Run pwd first. Then create "
113
+ f"{filename} with exactly this content and no extra characters: {EXPECTED_TEXT}"
114
+ )
115
+ command = [
116
+ "opencode",
117
+ "run",
118
+ "-m",
119
+ MODEL,
120
+ "--agent",
121
+ AGENT,
122
+ "--dir",
123
+ str(workspace),
124
+ "--dangerously-skip-permissions",
125
+ prompt,
126
+ ]
127
+ result = run_command(command, timeout=timeout)
128
+ expected_locations = [
129
+ ("workspace", target),
130
+ ("repo", ROOT / filename),
131
+ ("home", Path.home() / filename),
132
+ ]
133
+ observed = {
134
+ label: path.read_text(encoding="utf-8", errors="replace") if path.is_file() else None
135
+ for label, path in expected_locations
136
+ }
137
+ if result.returncode != 0:
138
+ checks.append(Check("opencode run", "fail", result.stdout.strip()[-1200:]))
139
+ elif observed["workspace"] == EXPECTED_TEXT and observed["repo"] is None and observed["home"] is None:
140
+ checks.append(Check("opencode run", "pass", f"{filename} written only in {workspace}"))
141
+ else:
142
+ details = []
143
+ for label, value in observed.items():
144
+ if value is not None:
145
+ details.append(f"{label}={value!r}")
146
+ checks.append(Check("opencode run", "fail", "; ".join(details) or "expected file missing"))
147
+
148
+ if not keep_dir and target.is_file():
149
+ # Keep successful smoke workspaces for inspection only when requested.
150
+ shutil.rmtree(workspace, ignore_errors=True)
151
+
152
+ return {
153
+ "workspace": str(workspace),
154
+ "filename": filename,
155
+ "command": command,
156
+ "returncode": result.returncode,
157
+ "stdout_tail": result.stdout.strip()[-2000:],
158
+ "observed": observed,
159
+ "kept": keep_dir,
160
+ }
161
+
162
+
163
+ def write_report(run_dir: Path, checks: list[Check], details: dict[str, Any]) -> None:
164
+ run_dir.mkdir(parents=True, exist_ok=True)
165
+ summary = {
166
+ "ready": not any(check.status in {"fail", "manual"} for check in checks),
167
+ "summary": {
168
+ "pass": sum(1 for check in checks if check.status == "pass"),
169
+ "fail": sum(1 for check in checks if check.status == "fail"),
170
+ "manual": sum(1 for check in checks if check.status == "manual"),
171
+ },
172
+ "checks": [asdict(check) for check in checks],
173
+ "details": details,
174
+ }
175
+ (run_dir / "result.json").write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8")
176
+ lines = [
177
+ "# Kaiju Coder 7 Public OpenCode Smoke",
178
+ "",
179
+ f"Ready: `{summary['ready']}`",
180
+ f"Summary: `{summary['summary']['pass']} pass / {summary['summary']['fail']} fail / {summary['summary']['manual']} manual`",
181
+ "",
182
+ "| Status | Check | Detail |",
183
+ "|---|---|---|",
184
+ ]
185
+ for check in checks:
186
+ lines.append(f"| {check.status} | {check.name} | {check.detail.replace('|', '/') } |")
187
+ if details.get("command"):
188
+ lines.extend(
189
+ [
190
+ "",
191
+ "## OpenCode Command",
192
+ "",
193
+ "```bash",
194
+ shell_join(details["command"]),
195
+ "```",
196
+ ]
197
+ )
198
+ (run_dir / "summary.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
199
+
200
+
201
+ def main() -> int:
202
+ parser = argparse.ArgumentParser(description=__doc__)
203
+ parser.add_argument("--base-url", default=None)
204
+ parser.add_argument("--timeout", type=int, default=900)
205
+ parser.add_argument("--runs-dir", type=Path, default=DEFAULT_RUNS_DIR)
206
+ parser.add_argument("--skip-live", action="store_true")
207
+ parser.add_argument("--skip-opencode", action="store_true", help="Only run installer/live checks.")
208
+ parser.add_argument("--keep-dir", action="store_true", help="Keep the temp OpenCode workspace.")
209
+ args = parser.parse_args()
210
+
211
+ checks: list[Check] = []
212
+ add_installer_check(checks, timeout=60, base_url=args.base_url)
213
+ add_opencode_version_check(checks, timeout=30)
214
+ if args.skip_live:
215
+ checks.append(Check("live model", "manual", "skipped by --skip-live"))
216
+ else:
217
+ add_live_model_check(checks, timeout=10, base_url=args.base_url)
218
+ details: dict[str, Any] = {}
219
+ if args.skip_opencode:
220
+ checks.append(Check("opencode run", "manual", "skipped by --skip-opencode"))
221
+ elif any(check.status == "fail" for check in checks):
222
+ checks.append(Check("opencode run", "manual", "skipped because prerequisite checks failed"))
223
+ else:
224
+ details = run_opencode_smoke(checks, timeout=args.timeout, keep_dir=args.keep_dir)
225
+
226
+ run_dir = args.runs_dir / utc_stamp()
227
+ write_report(run_dir, checks, details)
228
+ ready = not any(check.status in {"fail", "manual"} for check in checks)
229
+ print(f"Wrote {run_dir / 'summary.md'}")
230
+ for check in checks:
231
+ print(f"[{check.status}] {check.name} - {check.detail}")
232
+ return 0 if ready else 1
233
+
234
+
235
+ if __name__ == "__main__":
236
+ raise SystemExit(main())
scripts/upload_hf_merged_model_from_gojira_b.sh ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
6
+ # shellcheck source=scripts/gojira-b-ssh-lib.sh
7
+ source "${SCRIPT_DIR}/gojira-b-ssh-lib.sh"
8
+ kaiju_gojira_b_init
9
+
10
+ NAMESPACE="${KAIJU_HF_NAMESPACE:-RMDWLLC}"
11
+ REPO_ID="${KAIJU_HF_MERGED_REPO:-${NAMESPACE}/kaiju-coder-7}"
12
+ MODEL_REMOTE="${KAIJU_MERGED_MODEL_REMOTE:-/home/richardecholsai5/kaiju-coder/models/Kaiju-Coder-Qwen3.6-27B-v1.8-merged}"
13
+ VISIBILITY="${KAIJU_HF_VISIBILITY:-private}"
14
+ APPLY="${KAIJU_HF_UPLOAD_APPLY:-0}"
15
+
16
+ usage() {
17
+ cat <<'USAGE'
18
+ Dry-run or upload the merged Kaiju Coder 7 model from Gojira-B to Hugging Face.
19
+
20
+ This script is dry-run by default. Set KAIJU_HF_UPLOAD_APPLY=1 only after:
21
+
22
+ - human review is complete
23
+ - Hugging Face CLI is installed on Gojira-B
24
+ - `hf auth whoami` on Gojira-B shows the intended account
25
+ - upstream license/provenance docs have been reviewed
26
+
27
+ Environment:
28
+ KAIJU_HF_MERGED_REPO repo id, default RMDWLLC/kaiju-coder-7
29
+ KAIJU_HF_NAMESPACE Hugging Face namespace, default RMDWLLC
30
+ KAIJU_MERGED_MODEL_REMOTE model dir on Gojira-B
31
+ KAIJU_HF_VISIBILITY private or public, default private
32
+ KAIJU_HF_UPLOAD_APPLY 0 dry-run, 1 execute
33
+ USAGE
34
+ }
35
+
36
+ if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
37
+ usage
38
+ exit 0
39
+ fi
40
+
41
+ case "${VISIBILITY}" in
42
+ private|public) ;;
43
+ *) echo "KAIJU_HF_VISIBILITY must be private or public, got: ${VISIBILITY}" >&2; exit 2 ;;
44
+ esac
45
+
46
+ private_flag=""
47
+ if [[ "${VISIBILITY}" == "private" ]]; then
48
+ private_flag="--private"
49
+ fi
50
+
51
+ if [[ "${APPLY}" == "1" ]]; then
52
+ review_args=(--mode public --require-merged-upload)
53
+ if [[ "${VISIBILITY}" == "public" ]]; then
54
+ review_args+=(--require-public-visibility)
55
+ fi
56
+ python3 "${ROOT}/scripts/check_human_release_review.py" "${review_args[@]}"
57
+ fi
58
+
59
+ kaiju_gojira_b_ssh "
60
+ set -euo pipefail
61
+ export PATH=\"\$HOME/.local/bin:\$PATH\"
62
+ test -d '${MODEL_REMOTE}' || { echo 'Missing merged model: ${MODEL_REMOTE}' >&2; exit 2; }
63
+ test -f '${MODEL_REMOTE}/config.json' || { echo 'Missing config.json in ${MODEL_REMOTE}' >&2; exit 2; }
64
+ test -f '${MODEL_REMOTE}/tokenizer_config.json' || { echo 'Missing tokenizer_config.json in ${MODEL_REMOTE}' >&2; exit 2; }
65
+ for required in \
66
+ README.md \
67
+ PUBLIC_TESTING_QUICKSTART.md \
68
+ LOCAL_TEST_INSTRUCTIONS.md \
69
+ SERVING_BENCHMARKS.md \
70
+ EVAL_SCOREBOARD.md \
71
+ DATA_PROVENANCE_DRAFT.md \
72
+ SOURCE_INVENTORY.md \
73
+ UPSTREAM_LICENSE_CHECK.md \
74
+ PAID_API_READINESS.md \
75
+ FINAL_RELEASE_REPORT.md \
76
+ GOAL_COMPLETION_AUDIT.md \
77
+ MERGED_MODEL_RELEASE_MANIFEST.json \
78
+ upstream/qwen3.6-27b/LICENSE; do
79
+ test -f '${MODEL_REMOTE}/'\${required} || {
80
+ echo \"Missing merged-model metadata: \${required}\" >&2
81
+ echo 'Run: KAIJU_MERGED_METADATA_APPLY=1 bash scripts/prepare_hf_merged_model_metadata.sh' >&2
82
+ exit 2
83
+ }
84
+ done
85
+ shard_count=\$(find '${MODEL_REMOTE}' -maxdepth 1 -name '*.safetensors' | wc -l | tr -d ' ')
86
+ if [[ \"\${shard_count}\" -lt 1 ]]; then
87
+ echo 'No safetensors shards found in ${MODEL_REMOTE}' >&2
88
+ exit 2
89
+ fi
90
+ size=\$(du -sh '${MODEL_REMOTE}' | awk '{print \$1}')
91
+ echo 'Merged model: ${MODEL_REMOTE}'
92
+ echo \"Size: \${size}; safetensors shards: \${shard_count}\"
93
+ echo 'Metadata: present'
94
+ echo 'Repo: ${REPO_ID}'
95
+ echo 'Visibility: ${VISIBILITY}'
96
+ echo
97
+ echo 'Commands:'
98
+ echo 'hf repos create ${REPO_ID} --type model ${private_flag} --exist-ok'
99
+ echo 'hf upload-large-folder ${REPO_ID} ${MODEL_REMOTE} --type model ${private_flag}'
100
+ if [[ '${APPLY}' != '1' ]]; then
101
+ echo
102
+ echo 'Dry run. Set KAIJU_HF_UPLOAD_APPLY=1 to execute.'
103
+ exit 0
104
+ fi
105
+ if ! command -v hf >/dev/null 2>&1; then
106
+ echo 'Missing Hugging Face CLI on Gojira-B: hf' >&2
107
+ echo 'Install: curl -LsSf https://hf.co/cli/install.sh | bash -s' >&2
108
+ exit 2
109
+ fi
110
+ hf auth whoami >/dev/null
111
+ hf repos create '${REPO_ID}' --type model ${private_flag} --exist-ok
112
+ hf upload-large-folder '${REPO_ID}' '${MODEL_REMOTE}' --type model ${private_flag}
113
+ "