From d3e7f5149d098a64b0322a59623115ff2cfa5f3c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 4 Aug 2026 22:27:31 +0900 Subject: [PATCH 01/11] ci: schedule commercial readiness with OpenCode and NVIDIA NIM --- .../hourly-opencode-commercial-readiness.yml | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 .github/workflows/hourly-opencode-commercial-readiness.yml diff --git a/.github/workflows/hourly-opencode-commercial-readiness.yml b/.github/workflows/hourly-opencode-commercial-readiness.yml new file mode 100644 index 00000000..0a6b7f86 --- /dev/null +++ b/.github/workflows/hourly-opencode-commercial-readiness.yml @@ -0,0 +1,236 @@ +name: Hourly OpenCode commercial readiness + +on: + schedule: + - cron: "17 * * * *" + workflow_dispatch: + +permissions: read-all + +concurrency: + group: hourly-opencode-commercial-readiness-${{ github.repository }} + cancel-in-progress: false + +jobs: + commercial_readiness: + name: Review, repair, verify, and advance one protected slice + if: github.repository_owner == 'ContextualWisdomLab' + runs-on: ubuntu-latest + timeout-minutes: 55 + permissions: + actions: read + checks: read + contents: write + issues: write + pull-requests: write + env: + OPENCODE_NIM_MODEL: ${{ vars.OPENCODE_NIM_MODEL || 'qwen/qwen3-coder-480b-a35b-instruct' }} + OPENCODE_VERSION: ${{ vars.OPENCODE_VERSION || 'latest' }} + steps: + - name: Check out the protected repository baseline + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Set up the supported Node.js runtime + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + with: + node-version: 22.13.0 + cache: npm + + - name: Select one trusted pull request or the next product slice + id: target + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + mkdir -p .opencode + default_branch="$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.default_branch')" + test -n "$default_branch" + + gh pr list --repo "$GITHUB_REPOSITORY" --state open --limit 100 \ + --json number,title,isDraft,headRefName,headRefOid,headRepositoryOwner,author,authorAssociation,updatedAt \ + > .opencode/open-pull-requests.json + + python3 <<'PY' > .opencode/selected-target.json + import json + from pathlib import Path + + trusted_associations = {"OWNER", "MEMBER", "COLLABORATOR"} + pulls = json.loads(Path(".opencode/open-pull-requests.json").read_text(encoding="utf-8")) + trusted = [ + pull + for pull in pulls + if pull.get("authorAssociation") in trusted_associations + and (pull.get("headRepositoryOwner") or {}).get("login") == "ContextualWisdomLab" + ] + trusted.sort(key=lambda pull: (pull.get("isDraft", False), pull.get("updatedAt", ""), pull["number"])) + selected = trusted[0] if trusted else None + Path(".opencode/selected-target.json").write_text( + json.dumps({"selected": selected}, ensure_ascii=False, indent=2) + "\n", + encoding="utf-8", + ) + print(json.dumps({"selected": selected}, ensure_ascii=False)) + PY + + pr_number="$(jq -r '.selected.number // empty' .opencode/selected-target.json)" + if [[ -n "$pr_number" ]]; then + head_branch="$(jq -r '.selected.headRefName' .opencode/selected-target.json)" + head_sha="$(jq -r '.selected.headRefOid' .opencode/selected-target.json)" + gh pr view "$pr_number" --repo "$GITHUB_REPOSITORY" \ + --json number,title,body,isDraft,mergeStateStatus,reviewDecision,reviews,comments,statusCheckRollup,files \ + > .opencode/pull-request-context.json + gh pr checkout "$pr_number" --repo "$GITHUB_REPOSITORY" --branch "$head_branch" + test "$(git rev-parse HEAD)" = "$head_sha" + printf 'mode=pull_request\n' >> "$GITHUB_OUTPUT" + printf 'pr_number=%s\n' "$pr_number" >> "$GITHUB_OUTPUT" + printf 'head_branch=%s\n' "$head_branch" >> "$GITHUB_OUTPUT" + else + branch_name="opencode/commercial-readiness-${GITHUB_RUN_ID}" + git checkout -b "$branch_name" "origin/${default_branch}" + gh issue list --repo "$GITHUB_REPOSITORY" --state open --limit 100 \ + --json number,title,body,labels,createdAt,updatedAt \ + > .opencode/open-issues.json + printf 'mode=product_gap\n' >> "$GITHUB_OUTPUT" + printf 'pr_number=\n' >> "$GITHUB_OUTPUT" + printf 'head_branch=%s\n' "$branch_name" >> "$GITHUB_OUTPUT" + fi + printf 'start_sha=%s\n' "$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + + - name: Build the bounded commercial-readiness assignment + shell: bash + env: + TARGET_MODE: ${{ steps.target.outputs.mode }} + TARGET_PR: ${{ steps.target.outputs.pr_number }} + run: | + set -euo pipefail + cat > .opencode/assignment.md <<'EOF' + You are the implementation agent for ContextualWisdomLab/scopeweave. Work autonomously on exactly the checked-out target and stop before 45 minutes. + + Operating order: + 1. Read AGENTS.md, the selected PR or issue context under .opencode/, current source, tests, CHANGELOG.md, and documentation. + 2. For an existing PR, inspect every review comment and failing or pending check represented in the captured context. Reproduce each actionable failure before changing production code. Resolve comments in code rather than explaining them away. + 3. For an empty PR queue, select one bounded buyer-visible gap from the captured open issues. Do not invent a broad platform rewrite. Start with a failing realistic test, then implement the smallest complete vertical slice. + 4. Follow strict red-green-refactor TDD. Never weaken, skip, delete, or mark a meaningful test expected-to-fail merely to obtain green output. + 5. Preserve standalone ScopeWeave operation and framework-independent module seams suitable for ContextualWisdomLab/.github, naruon, or a future MSA adapter. + 6. Every new function, exported constant, security invariant, and non-obvious branch requires beginner-readable JSDoc. New or materially changed production modules require 100% statement, branch, function, and line coverage. + 7. Use multi-word snake_case for every new database table, column, index, trigger, constraint, and migration object. + 8. Add realistic API, concurrency, tenant-boundary, failure, privacy, and recovery tests appropriate to the feature. LLM-dependent tests must use NVIDIA_NIM_API_KEY through the repository's established contextual-orchestrator boundary; do not hard-code credentials or call GitHub Copilot. + 9. Ground design choices in current authoritative standards or peer-reviewed research, add APA 7th references to the relevant documentation, and update CHANGELOG.md. Do not fabricate citations. + 10. Do not edit, replace, copy, or weaken the existing CodeRabbit, Noema, OpenCode-review, Strix, security-review, or organization-central workflow/key system. Do not modify branch protection or use administrator bypass. + 11. Run npm ci, focused tests, complete unit and API suites, coverage, docstring evidence, cloud E2E where the changed behavior is user-visible, security checks available locally, and git diff --check. Fix every failure. + 12. Commit coherent changes locally with conventional commit messages. Do not push, merge, mark a PR ready, or create a release; the trusted publication step owns those operations. + + Never print, persist, summarize, or place credentials in logs, commits, prompts, test fixtures, URLs, issue comments, audit data, or generated artifacts. + EOF + printf '\nTarget mode: %s\nTarget PR: %s\n' "$TARGET_MODE" "${TARGET_PR:-none}" >> .opencode/assignment.md + + - name: Install the configured OpenCode release + shell: bash + run: | + set -euo pipefail + if [[ "$OPENCODE_VERSION" != "latest" && ! "$OPENCODE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then + echo 'OPENCODE_VERSION must be latest or an explicit semantic version.' >&2 + exit 1 + fi + npm install --global --ignore-scripts "opencode-ai@${OPENCODE_VERSION}" + resolved_version="$(opencode --version)" + test -n "$resolved_version" + printf 'OpenCode version: `%s`\n' "$resolved_version" >> "$GITHUB_STEP_SUMMARY" + + - name: Execute OpenCode with NVIDIA NIM + shell: bash + env: + NVIDIA_NIM_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }} + OPENCODE_CONFIG_CONTENT: >- + {"$schema":"https://opencode.ai/config.json","model":"nvidia_nim/${{ env.OPENCODE_NIM_MODEL }}","provider":{"nvidia_nim":{"npm":"@ai-sdk/openai-compatible","name":"NVIDIA NIM","options":{"baseURL":"https://integrate.api.nvidia.com/v1","apiKey":"{env:NVIDIA_NIM_API_KEY}"},"models":{"${{ env.OPENCODE_NIM_MODEL }}":{"name":"NVIDIA NIM commercial-readiness model"}}}},"permission":{"bash":"allow","edit":"allow","write":"allow","read":"allow","glob":"allow","grep":"allow"}} + run: | + set -euo pipefail + test -n "$NVIDIA_NIM_API_KEY" + opencode run \ + --model "nvidia_nim/${OPENCODE_NIM_MODEL}" \ + --format json \ + "$(cat .opencode/assignment.md)" \ + | tee "${RUNNER_TEMP}/opencode-commercial-readiness.jsonl" + + - name: Enforce repository and review-agent safety boundaries + shell: bash + env: + START_SHA: ${{ steps.target.outputs.start_sha }} + run: | + set -euo pipefail + git diff --check "$START_SHA"...HEAD + changed_files="$(git diff --name-only "$START_SHA"...HEAD; git diff --name-only)" + if printf '%s\n' "$changed_files" | grep -E '^\.github/workflows/.*(coderabbit|noema|opencode-review|review-agent|strix|security-review).*\.ya?ml$'; then + echo 'The commercial-readiness agent modified a protected review-agent workflow.' >&2 + exit 1 + fi + if git diff "$START_SHA"...HEAD | grep -E '(^|[^A-Za-z])(NVIDIA_NIM_API_KEY|ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})[[:space:]]*[:=][[:space:]]*[^$<{[:space:]]'; then + echo 'A credential-like literal was introduced.' >&2 + exit 1 + fi + git status --short + + - name: Run the complete product verification contract + shell: bash + env: + CI: 'true' + run: | + set -euo pipefail + npm ci + npm run test:unit + npm run test:api + npm run coverage + node scripts/ci/static_coverage_evidence.mjs docstrings + if npm run | grep -q 'test:e2e:cloud'; then + npm run test:e2e:cloud + fi + git diff --check + + - name: Publish the verified exact head without exposing credentials to the agent + id: publish + shell: bash + env: + GH_TOKEN: ${{ github.token }} + HEAD_BRANCH: ${{ steps.target.outputs.head_branch }} + TARGET_MODE: ${{ steps.target.outputs.mode }} + TARGET_PR: ${{ steps.target.outputs.pr_number }} + run: | + set -euo pipefail + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A + if git diff --cached --quiet; then + echo 'No verified source change was produced.' + else + git commit -m 'fix: advance verified commercial readiness' + fi + git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git push origin "HEAD:${HEAD_BRANCH}" + git remote set-url origin "https://github.com/${GITHUB_REPOSITORY}.git" + + if [[ "$TARGET_MODE" == 'product_gap' ]]; then + pr_url="$(gh pr create --repo "$GITHUB_REPOSITORY" --base "$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.default_branch')" --head "$HEAD_BRANCH" --draft \ + --title 'feat: advance the next commercial-readiness slice' \ + --body 'Automated OpenCode/NVIDIA NIM development slice. Remains Draft until all exact-head required checks, independent reviews, coverage, documentation, and release gates pass.')" + TARGET_PR="${pr_url##*/}" + fi + printf 'pr_number=%s\n' "$TARGET_PR" >> "$GITHUB_OUTPUT" + + - name: Request current-head review and arm protected auto-merge only for Ready work + shell: bash + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ steps.publish.outputs.pr_number }} + run: | + set -euo pipefail + test -n "$PR_NUMBER" + head_sha="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json headRefOid --jq '.headRefOid')" + gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" \ + --body "@coderabbitai review\n\nOpenCode/NVIDIA NIM completed the bounded implementation and local verification contract on exact head \`${head_sha}\`. Repository and organization-required checks and independent review remain authoritative." + is_draft="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json isDraft --jq '.isDraft')" + if [[ "$is_draft" == 'false' ]]; then + gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --squash --auto || true + fi From 6a65103f46abf47732dc988501259597e5fc8724 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:14:58 +0900 Subject: [PATCH 02/11] ci: harden hourly OpenCode development with NVIDIA NIM --- .../hourly-opencode-commercial-readiness.yml | 518 ++++++++++++------ 1 file changed, 356 insertions(+), 162 deletions(-) diff --git a/.github/workflows/hourly-opencode-commercial-readiness.yml b/.github/workflows/hourly-opencode-commercial-readiness.yml index 0a6b7f86..31cdb014 100644 --- a/.github/workflows/hourly-opencode-commercial-readiness.yml +++ b/.github/workflows/hourly-opencode-commercial-readiness.yml @@ -1,182 +1,354 @@ -name: Hourly OpenCode commercial readiness +name: Hourly ScopeWeave OpenCode Commercial Readiness on: - schedule: - - cron: "17 * * * *" workflow_dispatch: - -permissions: read-all + inputs: + dry_run: + description: Evaluate the gate and prompt without running OpenCode + required: false + default: false + type: boolean + schedule: + - cron: "41 * * * *" concurrency: - group: hourly-opencode-commercial-readiness-${{ github.repository }} + group: scopeweave-hourly-opencode-commercial-readiness cancel-in-progress: false +# The default token is read-only. The single trusted publication step uses the +# job-scoped write token after the OpenCode process has exited. OpenCode receives +# only NVIDIA_API_KEY, which is sourced from NVIDIA_NIM_API_KEY. +permissions: + contents: read + jobs: - commercial_readiness: - name: Review, repair, verify, and advance one protected slice - if: github.repository_owner == 'ContextualWisdomLab' + develop-one-bounded-slice: + if: github.repository == 'ContextualWisdomLab/scopeweave' runs-on: ubuntu-latest timeout-minutes: 55 permissions: - actions: read - checks: read contents: write - issues: write + issues: read pull-requests: write env: - OPENCODE_NIM_MODEL: ${{ vars.OPENCODE_NIM_MODEL || 'qwen/qwen3-coder-480b-a35b-instruct' }} - OPENCODE_VERSION: ${{ vars.OPENCODE_VERSION || 'latest' }} + DEFAULT_BRANCH: develop + DRY_RUN: ${{ inputs.dry_run || false }} + OPENCODE_VERSION: "1.17.13" + OPENCODE_SHA256: 157afa289d1a8d9372de0ce19ac726119b937a1f6b201808d46f06e4e59bb348 + OPENCODE_MODEL_CANDIDATES: >- + nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5 + nvidia-nim/nvidia/nemotron-3-super-120b-a12b + nvidia-nim/deepseek-ai/deepseek-v4-pro + OPENCODE_RUN_TIMEOUT_SECONDS: "2400" steps: - - name: Check out the protected repository baseline - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Enforce pull-request-first single-flight gate + id: gate + shell: bash + env: + GH_TOKEN: ${{ github.token }} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }} + run: | + set -euo pipefail + + if ! open_prs="$( + gh pr list \ + --repo "$GITHUB_REPOSITORY" \ + --state open \ + --limit 1 \ + --json number,url + )"; then + { + echo "dispatch=false" + echo "reason=pull_request_inventory_unavailable" + } >>"$GITHUB_OUTPUT" + echo "Pull-request inventory was unavailable; failing closed." \ + >>"$GITHUB_STEP_SUMMARY" + exit 0 + fi + + if [ "$(jq 'length' <<<"$open_prs")" -gt 0 ]; then + { + echo "dispatch=false" + echo "reason=open_pull_request" + } >>"$GITHUB_OUTPUT" + echo "An open pull request exists; central PR governance owns this hour." \ + >>"$GITHUB_STEP_SUMMARY" + exit 0 + fi + + if [ -z "${NVIDIA_API_KEY:-}" ]; then + { + echo "dispatch=false" + echo "reason=nim_api_key_unavailable" + } >>"$GITHUB_OUTPUT" + cat >>"$GITHUB_STEP_SUMMARY" <<'SUMMARY' + Autonomous development is disabled because `NVIDIA_NIM_API_KEY` is not configured. + No Copilot subscription, Agent Tasks API, or fine-grained user token is used. + SUMMARY + exit 0 + fi + + { + echo "dispatch=true" + echo "reason=ready" + } >>"$GITHUB_OUTPUT" + + - name: Prepare bounded commercial-quality assignment + if: steps.gate.outputs.dispatch == 'true' + shell: bash + run: | + cat >"$RUNNER_TEMP/scopeweave-agent-prompt.md" <<'PROMPT' + Continue product development for ContextualWisdomLab/scopeweave on the develop branch. + + Start by reading AGENTS.md, README.md, CHANGELOG.md, docs/doctoring, + docs/operations, the trusted open-issue and recently-merged-PR snapshots under + .opencode-context, current source, tests, package contracts, service adapters, + database schema, and release evidence. Select exactly one highest-impact, + buyer-visible product, reliability, interoperability, security, evaluation, + accessibility, or operations gap that can be completed as one bounded pull request. + Do not create another repository or a broad platform rewrite. + + Preserve standalone ScopeWeave operation while keeping framework-independent seams + suitable for ContextualWisdomLab/.github, naruon, Clearfolio, + contextual-orchestrator, and future MSA adapters. Use or improve + contextual-orchestrator for every product LLM path instead of adding a direct, + provider-specific client. Treat all model output as untrusted, bounded, auditable + input that requires deterministic validation before persistence or user-visible use. + + Work test-first: establish a failing realistic regression or executable contract + before production code, confirm that it fails for the intended reason, and then + implement the smallest coherent vertical slice. Never weaken, skip, delete, + suppress, or mark a meaningful release-gate test expected-to-fail merely to obtain + green output. Maintain 100% production statement, branch, function, and line + coverage for each new or materially changed production module. Every public module, + class, function, method, property, exported constant, security invariant, input, + output, and exception must have beginner-readable JSDoc or docstrings. + + New database tables, columns, indexes, triggers, constraints, migration objects, + and durable queues must use descriptive two-word-or-longer snake_case names. Preserve + tenant isolation, least privilege, bounded resource use, idempotency, deterministic + behavior where applicable, migration rollback, immutable audit evidence, and + secret-free logs. Tests must model realistic multi-tenant projects, concurrent edits + or requests, partial downstream failure, restart and migration behavior, large WBS + inputs, accessibility, recovery, and customer-visible outputs as appropriate. + + Use the latest authoritative international standard, primary technical + specification, or peer-reviewed paper for every material decision. Record the + decision, limitations, executable evidence, and APA 7th references under + docs/doctoring/. Distinguish source-supported claims, measurements, assumptions, and + inference. Do not claim certification or compliance beyond executable evidence. + + Use Figma or Product Design only when the selected slice has a real buyer-facing UI. + For such a slice, account for loading, empty, validation, error, keyboard, + screen-reader, touch, narrow-viewport, and permission states. Do not manufacture + design work for a backend-only or library-only increment. + + If an LLM-dependent test is genuinely necessary, use the established + contextual-orchestrator boundary and NVIDIA_NIM_API_KEY in GitHub Actions; keep + deterministic non-LLM tests as the required merge gate. Do not edit, copy, replace, + or weaken CodeRabbit, Noema, OpenCode-review, Strix, security-review, organization + rules, reviewer credentials, `.trivyignore`, or branch protection. + + Run focused tests, npm ci, complete unit and API suites, coverage and docstring + gates, cloud browser E2E for user-visible changes, syntax and dependency checks, + relevant adversarial/security tests, and git diff --check. Update CHANGELOG.md and + all affected product, architecture, operations, security, accessibility, evaluation, + migration, and rollback documentation. Change package versions only when the + integrated repository is genuinely release-ready. Do not merge, publish, release, + push, or commit. Leave one bounded verified working-tree increment and create + PR_MESSAGE.md at the repository root: first line is the proposed title, followed by + a body with buyer impact, exact verification evidence, standards references, risks, + compatibility, and residual gaps. A trusted workflow step will publish the branch; + central PR governance owns review, repair, exact-head checks, approval, and merge. + PROMPT + + - name: Record dry-run decision + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN == 'true' + shell: bash + run: | + { + echo "Dry run: one bounded OpenCode/NVIDIA NIM development session would start." + echo + cat "$RUNNER_TEMP/scopeweave-agent-prompt.md" + } >>"$GITHUB_STEP_SUMMARY" + + - name: Check out develop without persisted credentials + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 with: + ref: develop fetch-depth: 0 persist-credentials: false - name: Set up the supported Node.js runtime - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 with: node-version: 22.13.0 cache: npm - - name: Select one trusted pull request or the next product slice - id: target + - name: Materialize trusted repository context + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash env: GH_TOKEN: ${{ github.token }} run: | set -euo pipefail - mkdir -p .opencode - default_branch="$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.default_branch')" - test -n "$default_branch" - - gh pr list --repo "$GITHUB_REPOSITORY" --state open --limit 100 \ - --json number,title,isDraft,headRefName,headRefOid,headRepositoryOwner,author,authorAssociation,updatedAt \ - > .opencode/open-pull-requests.json - - python3 <<'PY' > .opencode/selected-target.json - import json - from pathlib import Path - - trusted_associations = {"OWNER", "MEMBER", "COLLABORATOR"} - pulls = json.loads(Path(".opencode/open-pull-requests.json").read_text(encoding="utf-8")) - trusted = [ - pull - for pull in pulls - if pull.get("authorAssociation") in trusted_associations - and (pull.get("headRepositoryOwner") or {}).get("login") == "ContextualWisdomLab" - ] - trusted.sort(key=lambda pull: (pull.get("isDraft", False), pull.get("updatedAt", ""), pull["number"])) - selected = trusted[0] if trusted else None - Path(".opencode/selected-target.json").write_text( - json.dumps({"selected": selected}, ensure_ascii=False, indent=2) + "\n", - encoding="utf-8", - ) - print(json.dumps({"selected": selected}, ensure_ascii=False)) - PY - - pr_number="$(jq -r '.selected.number // empty' .opencode/selected-target.json)" - if [[ -n "$pr_number" ]]; then - head_branch="$(jq -r '.selected.headRefName' .opencode/selected-target.json)" - head_sha="$(jq -r '.selected.headRefOid' .opencode/selected-target.json)" - gh pr view "$pr_number" --repo "$GITHUB_REPOSITORY" \ - --json number,title,body,isDraft,mergeStateStatus,reviewDecision,reviews,comments,statusCheckRollup,files \ - > .opencode/pull-request-context.json - gh pr checkout "$pr_number" --repo "$GITHUB_REPOSITORY" --branch "$head_branch" - test "$(git rev-parse HEAD)" = "$head_sha" - printf 'mode=pull_request\n' >> "$GITHUB_OUTPUT" - printf 'pr_number=%s\n' "$pr_number" >> "$GITHUB_OUTPUT" - printf 'head_branch=%s\n' "$head_branch" >> "$GITHUB_OUTPUT" - else - branch_name="opencode/commercial-readiness-${GITHUB_RUN_ID}" - git checkout -b "$branch_name" "origin/${default_branch}" - gh issue list --repo "$GITHUB_REPOSITORY" --state open --limit 100 \ - --json number,title,body,labels,createdAt,updatedAt \ - > .opencode/open-issues.json - printf 'mode=product_gap\n' >> "$GITHUB_OUTPUT" - printf 'pr_number=\n' >> "$GITHUB_OUTPUT" - printf 'head_branch=%s\n' "$branch_name" >> "$GITHUB_OUTPUT" - fi - printf 'start_sha=%s\n' "$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + mkdir -p .opencode-context + gh issue list \ + --repo "$GITHUB_REPOSITORY" \ + --state open \ + --limit 100 \ + --json number,title,body,labels,createdAt,updatedAt \ + >.opencode-context/open-issues.json + gh pr list \ + --repo "$GITHUB_REPOSITORY" \ + --state merged \ + --limit 30 \ + --json number,title,body,mergedAt,files \ + >.opencode-context/recent-merged-prs.json + { + echo /opencode.json + echo /.opencode-context/ + } >>.git/info/exclude - - name: Build the bounded commercial-readiness assignment + - name: Install the pinned OpenCode CLI + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash - env: - TARGET_MODE: ${{ steps.target.outputs.mode }} - TARGET_PR: ${{ steps.target.outputs.pr_number }} run: | set -euo pipefail - cat > .opencode/assignment.md <<'EOF' - You are the implementation agent for ContextualWisdomLab/scopeweave. Work autonomously on exactly the checked-out target and stop before 45 minutes. - - Operating order: - 1. Read AGENTS.md, the selected PR or issue context under .opencode/, current source, tests, CHANGELOG.md, and documentation. - 2. For an existing PR, inspect every review comment and failing or pending check represented in the captured context. Reproduce each actionable failure before changing production code. Resolve comments in code rather than explaining them away. - 3. For an empty PR queue, select one bounded buyer-visible gap from the captured open issues. Do not invent a broad platform rewrite. Start with a failing realistic test, then implement the smallest complete vertical slice. - 4. Follow strict red-green-refactor TDD. Never weaken, skip, delete, or mark a meaningful test expected-to-fail merely to obtain green output. - 5. Preserve standalone ScopeWeave operation and framework-independent module seams suitable for ContextualWisdomLab/.github, naruon, or a future MSA adapter. - 6. Every new function, exported constant, security invariant, and non-obvious branch requires beginner-readable JSDoc. New or materially changed production modules require 100% statement, branch, function, and line coverage. - 7. Use multi-word snake_case for every new database table, column, index, trigger, constraint, and migration object. - 8. Add realistic API, concurrency, tenant-boundary, failure, privacy, and recovery tests appropriate to the feature. LLM-dependent tests must use NVIDIA_NIM_API_KEY through the repository's established contextual-orchestrator boundary; do not hard-code credentials or call GitHub Copilot. - 9. Ground design choices in current authoritative standards or peer-reviewed research, add APA 7th references to the relevant documentation, and update CHANGELOG.md. Do not fabricate citations. - 10. Do not edit, replace, copy, or weaken the existing CodeRabbit, Noema, OpenCode-review, Strix, security-review, or organization-central workflow/key system. Do not modify branch protection or use administrator bypass. - 11. Run npm ci, focused tests, complete unit and API suites, coverage, docstring evidence, cloud E2E where the changed behavior is user-visible, security checks available locally, and git diff --check. Fix every failure. - 12. Commit coherent changes locally with conventional commit messages. Do not push, merge, mark a PR ready, or create a release; the trusted publication step owns those operations. - - Never print, persist, summarize, or place credentials in logs, commits, prompts, test fixtures, URLs, issue comments, audit data, or generated artifacts. - EOF - printf '\nTarget mode: %s\nTarget PR: %s\n' "$TARGET_MODE" "${TARGET_PR:-none}" >> .opencode/assignment.md - - - name: Install the configured OpenCode release + archive="${RUNNER_TEMP}/opencode-linux-x64.tar.gz" + install_dir="${HOME}/.opencode/bin" + mkdir -p "$install_dir" + curl -fsSL \ + -o "$archive" \ + "https://github.com/anomalyco/opencode/releases/download/v${OPENCODE_VERSION}/opencode-linux-x64.tar.gz" + printf '%s %s\n' "$OPENCODE_SHA256" "$archive" | sha256sum -c - + tar -xzf "$archive" -C "$RUNNER_TEMP" + install -m 0755 "${RUNNER_TEMP}/opencode" "${install_dir}/opencode" + "${install_dir}/opencode" --version + echo "$install_dir" >>"$GITHUB_PATH" + + - name: Configure OpenCode for NVIDIA NIM + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash run: | set -euo pipefail - if [[ "$OPENCODE_VERSION" != "latest" && ! "$OPENCODE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then - echo 'OPENCODE_VERSION must be latest or an explicit semantic version.' >&2 - exit 1 - fi - npm install --global --ignore-scripts "opencode-ai@${OPENCODE_VERSION}" - resolved_version="$(opencode --version)" - test -n "$resolved_version" - printf 'OpenCode version: `%s`\n' "$resolved_version" >> "$GITHUB_STEP_SUMMARY" + cat >"$GITHUB_WORKSPACE/opencode.json" <<'CONFIG' + { + "$schema": "https://opencode.ai/config.json", + "enabled_providers": ["nvidia-nim"], + "model": "nvidia-nim/nvidia/llama-3.3-nemotron-super-49b-v1.5", + "small_model": "nvidia-nim/meta/llama-3.3-70b-instruct", + "provider": { + "nvidia-nim": { + "npm": "@ai-sdk/openai-compatible", + "name": "NVIDIA NIM", + "options": { + "baseURL": "https://integrate.api.nvidia.com/v1", + "apiKey": "{env:NVIDIA_API_KEY}" + }, + "models": { + "nvidia/llama-3.3-nemotron-super-49b-v1.5": { + "name": "NVIDIA Llama 3.3 Nemotron Super 49B v1.5", + "tool_call": true, + "limit": {"context": 131072, "output": 8192} + }, + "nvidia/nemotron-3-super-120b-a12b": { + "name": "NVIDIA Nemotron 3 Super 120B", + "tool_call": true, + "limit": {"context": 131072, "output": 8192} + }, + "deepseek-ai/deepseek-v4-pro": { + "name": "DeepSeek V4 Pro (NIM)", + "tool_call": true, + "limit": {"context": 131072, "output": 8192} + }, + "meta/llama-3.3-70b-instruct": { + "name": "Meta Llama 3.3 70B Instruct (NIM)", + "tool_call": true, + "limit": {"context": 131072, "output": 8192} + } + } + } + } + } + CONFIG - - name: Execute OpenCode with NVIDIA NIM + - name: Run the bounded NVIDIA NIM development agent + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash env: - NVIDIA_NIM_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }} - OPENCODE_CONFIG_CONTENT: >- - {"$schema":"https://opencode.ai/config.json","model":"nvidia_nim/${{ env.OPENCODE_NIM_MODEL }}","provider":{"nvidia_nim":{"npm":"@ai-sdk/openai-compatible","name":"NVIDIA NIM","options":{"baseURL":"https://integrate.api.nvidia.com/v1","apiKey":"{env:NVIDIA_NIM_API_KEY}"},"models":{"${{ env.OPENCODE_NIM_MODEL }}":{"name":"NVIDIA NIM commercial-readiness model"}}}},"permission":{"bash":"allow","edit":"allow","write":"allow","read":"allow","glob":"allow","grep":"allow"}} + NVIDIA_API_KEY: ${{ secrets.NVIDIA_NIM_API_KEY }} run: | set -euo pipefail - test -n "$NVIDIA_NIM_API_KEY" - opencode run \ - --model "nvidia_nim/${OPENCODE_NIM_MODEL}" \ - --format json \ - "$(cat .opencode/assignment.md)" \ - | tee "${RUNNER_TEMP}/opencode-commercial-readiness.jsonl" - - - name: Enforce repository and review-agent safety boundaries + test -n "$NVIDIA_API_KEY" + start_sha="$(git rev-parse HEAD)" + printf '%s\n' "$start_sha" >"$RUNNER_TEMP/start-sha" + prompt="$(cat "$RUNNER_TEMP/scopeweave-agent-prompt.md")" + status=1 + for model in $OPENCODE_MODEL_CANDIDATES; do + echo "::group::opencode $model" + if timeout --kill-after=30s "${OPENCODE_RUN_TIMEOUT_SECONDS}s" \ + env -u GH_TOKEN -u GITHUB_TOKEN -u REPOSITORY_TOKEN \ + -u ACTIONS_ID_TOKEN_REQUEST_TOKEN -u ACTIONS_ID_TOKEN_REQUEST_URL \ + opencode run "$prompt" --model "$model"; then + status=0 + echo "::endgroup::" + echo "Agent session completed with \`$model\`." >>"$GITHUB_STEP_SUMMARY" + break + fi + echo "::endgroup::" + echo "::warning::Model $model failed; discarding partial work and trying the next candidate." + git reset --hard "$start_sha" + git clean -fd + done + if [ "$status" -ne 0 ]; then + echo "::error::Every NVIDIA NIM model candidate failed; no work was proposed." + exit 1 + fi + if [ "$(git rev-parse HEAD)" != "$start_sha" ]; then + echo "::error::The agent created commits; trusted publication requires working-tree-only output." + exit 1 + fi + + - name: Enforce protected workflow and credential boundaries + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash - env: - START_SHA: ${{ steps.target.outputs.start_sha }} run: | set -euo pipefail - git diff --check "$START_SHA"...HEAD - changed_files="$(git diff --name-only "$START_SHA"...HEAD; git diff --name-only)" + start_sha="$(cat "$RUNNER_TEMP/start-sha")" + changed_files="$( + { + git diff --name-only "$start_sha"...HEAD + git diff --name-only + git ls-files --others --exclude-standard + } | sort -u + )" + if [ -z "$changed_files" ]; then + echo "No product change was produced." >>"$GITHUB_STEP_SUMMARY" + exit 0 + fi if printf '%s\n' "$changed_files" | grep -E '^\.github/workflows/.*(coderabbit|noema|opencode-review|review-agent|strix|security-review).*\.ya?ml$'; then - echo 'The commercial-readiness agent modified a protected review-agent workflow.' >&2 + echo "::error::The development agent modified a protected review-agent workflow." exit 1 fi - if git diff "$START_SHA"...HEAD | grep -E '(^|[^A-Za-z])(NVIDIA_NIM_API_KEY|ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,})[[:space:]]*[:=][[:space:]]*[^$<{[:space:]]'; then - echo 'A credential-like literal was introduced.' >&2 + if printf '%s\n' "$changed_files" | grep -E '(^|/)(\.trivyignore|\.semgrepignore|\.gitleaksignore)$'; then + echo "::error::The development agent introduced or changed a security-scan suppression file." exit 1 fi - git status --short + if git diff --no-ext-diff "$start_sha" -- . \ + | grep -E '(^|[^A-Za-z])(ghp_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|nvapi-[A-Za-z0-9_-]{20,})'; then + echo "::error::A credential-like literal was introduced." + exit 1 + fi + git diff --check - name: Run the complete product verification contract + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash env: - CI: 'true' + CI: "true" run: | set -euo pipefail npm ci @@ -189,48 +361,70 @@ jobs: fi git diff --check - - name: Publish the verified exact head without exposing credentials to the agent - id: publish + - name: Revalidate queue ownership and open exactly one pull request + if: steps.gate.outputs.dispatch == 'true' && env.DRY_RUN != 'true' shell: bash env: GH_TOKEN: ${{ github.token }} - HEAD_BRANCH: ${{ steps.target.outputs.head_branch }} - TARGET_MODE: ${{ steps.target.outputs.mode }} - TARGET_PR: ${{ steps.target.outputs.pr_number }} run: | set -euo pipefail - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add -A - if git diff --cached --quiet; then - echo 'No verified source change was produced.' - else - git commit -m 'fix: advance verified commercial readiness' + cd "$GITHUB_WORKSPACE" + rm -f opencode.json + rm -rf .opencode-context + + if [ -z "$(git status --porcelain)" ]; then + echo "The agent made no verified source change; nothing to propose this hour." \ + >>"$GITHUB_STEP_SUMMARY" + exit 0 fi - git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" - git push origin "HEAD:${HEAD_BRANCH}" - git remote set-url origin "https://github.com/${GITHUB_REPOSITORY}.git" - - if [[ "$TARGET_MODE" == 'product_gap' ]]; then - pr_url="$(gh pr create --repo "$GITHUB_REPOSITORY" --base "$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.default_branch')" --head "$HEAD_BRANCH" --draft \ - --title 'feat: advance the next commercial-readiness slice' \ - --body 'Automated OpenCode/NVIDIA NIM development slice. Remains Draft until all exact-head required checks, independent reviews, coverage, documentation, and release gates pass.')" - TARGET_PR="${pr_url##*/}" + + if [ "$( + gh pr list \ + --repo "$GITHUB_REPOSITORY" \ + --state open \ + --limit 1 \ + --json number \ + --jq 'length' + )" -ne 0 ]; then + echo "A pull request appeared while the agent was running; refusing duplicate development." \ + >>"$GITHUB_STEP_SUMMARY" + exit 0 fi - printf 'pr_number=%s\n' "$TARGET_PR" >> "$GITHUB_OUTPUT" - - name: Request current-head review and arm protected auto-merge only for Ready work - shell: bash - env: - GH_TOKEN: ${{ github.token }} - PR_NUMBER: ${{ steps.publish.outputs.pr_number }} - run: | - set -euo pipefail - test -n "$PR_NUMBER" - head_sha="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json headRefOid --jq '.headRefOid')" - gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" \ - --body "@coderabbitai review\n\nOpenCode/NVIDIA NIM completed the bounded implementation and local verification contract on exact head \`${head_sha}\`. Repository and organization-required checks and independent review remain authoritative." - is_draft="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json isDraft --jq '.isDraft')" - if [[ "$is_draft" == 'false' ]]; then - gh pr merge "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --squash --auto || true + title="ScopeWeave autonomous commercial-readiness increment" + body_file="$RUNNER_TEMP/pr-body.md" + if [ -f PR_MESSAGE.md ]; then + candidate_title="$(head -n 1 PR_MESSAGE.md | sed 's/^#\+ *//')" + [ -n "$candidate_title" ] && title="$candidate_title" + tail -n +2 PR_MESSAGE.md >"$body_file" + rm -f PR_MESSAGE.md + else + cat >"$body_file" <<'BODY' + Bounded OpenCode/NVIDIA NIM product increment. See the focused diff, + executable verification, CHANGELOG.md, and doctoring record. Central PR + governance remains responsible for independent review, repair, exact-head + checks, approval, and merge. + BODY fi + + branch="nim-agent/product-dev-${GITHUB_RUN_ID}" + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git checkout -b "$branch" + git add -A + git commit -m "$title" + git push \ + "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \ + "HEAD:refs/heads/${branch}" + pr_url="$( + gh pr create \ + --repo "$GITHUB_REPOSITORY" \ + --base "$DEFAULT_BRANCH" \ + --head "$branch" \ + --title "$title" \ + --body-file "$body_file" + )" + { + echo "Opened bounded pull request: $pr_url" + echo "Central PR governance owns review, repair, revalidation, and merge." + } >>"$GITHUB_STEP_SUMMARY" From 27f645acd9212d204689f767bb69eaf888fec9fd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:15:30 +0900 Subject: [PATCH 03/11] test(ci): enforce hourly OpenCode NVIDIA NIM contract --- ...rly-opencode-commercial-readiness.test.mjs | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/config/hourly-opencode-commercial-readiness.test.mjs diff --git a/tests/config/hourly-opencode-commercial-readiness.test.mjs b/tests/config/hourly-opencode-commercial-readiness.test.mjs new file mode 100644 index 00000000..574dd14a --- /dev/null +++ b/tests/config/hourly-opencode-commercial-readiness.test.mjs @@ -0,0 +1,116 @@ +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; + +const workflowPath = new URL( + '../../.github/workflows/hourly-opencode-commercial-readiness.yml', + import.meta.url, +); +const workflow = readFileSync(workflowPath, 'utf8'); + +assert.match( + workflow, + /cron:\s*["']41 \* \* \* \*["']/, + 'the autonomous product loop runs once per hour', +); +assert.match( + workflow, + /group:\s*scopeweave-hourly-opencode-commercial-readiness/, + 'one repository-wide concurrency group prevents overlapping agents', +); +assert.match( + workflow, + /cancel-in-progress:\s*false/, + 'a later hourly tick never interrupts a running product-development session', +); +assert.match( + workflow, + /permissions:\n\s+contents:\s+read/, + 'the workflow-level token defaults to read-only repository contents', +); +assert.match( + workflow, + /NVIDIA_API_KEY:\s*\$\{\{ secrets\.NVIDIA_NIM_API_KEY \}\}/, + 'the coding agent uses the organization NVIDIA NIM secret', +); +assert.doesNotMatch( + workflow, + /COPILOT_GITHUB_TOKEN|\/agents\/repos\/|create_pull_request/, + 'the scheduler never uses Copilot Agent Tasks or a user-scoped Copilot token', +); +assert.match( + workflow, + /OPENCODE_VERSION:\s*["']1\.17\.13["']/, + 'OpenCode is pinned to a reviewed release rather than latest', +); +assert.match( + workflow, + /OPENCODE_SHA256:\s+[0-9a-f]{64}/, + 'the OpenCode archive has a pinned SHA-256 digest', +); +assert.match( + workflow, + /sha256sum -c -/, + 'the downloaded OpenCode archive is verified before execution', +); +assert.match( + workflow, + /https:\/\/integrate\.api\.nvidia\.com\/v1/, + 'OpenCode targets the NVIDIA hosted NIM OpenAI-compatible endpoint', +); +assert.match( + workflow, + /"apiKey":\s*"\{env:NVIDIA_API_KEY\}"/, + 'the provider reads its key from the environment instead of the repository', +); +assert.match( + workflow, + /@ai-sdk\/openai-compatible/, + 'the OpenCode provider uses the documented OpenAI-compatible adapter', +); +assert.match( + workflow, + /env -u GH_TOKEN -u GITHUB_TOKEN -u REPOSITORY_TOKEN/, + 'the OpenCode process cannot inherit GitHub mutation credentials', +); +assert.match( + workflow, + /pull-request-first single-flight gate[\s\S]*gh pr list[\s\S]*state open/, + 'an existing pull request prevents another autonomous development slice', +); +assert.match( + workflow, + /Revalidate queue ownership[\s\S]*gh pr list[\s\S]*refusing duplicate development/, + 'the trusted publisher rechecks queue ownership immediately before publication', +); +assert.match( + workflow, + /protected review-agent workflow/, + 'agent changes to reviewer-owned workflows fail closed', +); +assert.match( + workflow, + /\.trivyignore\|\\\.semgrepignore\|\\\.gitleaksignore/, + 'security-scan suppression files are explicitly prohibited', +); +assert.match( + workflow, + /npm ci[\s\S]*npm run test:unit[\s\S]*npm run test:api[\s\S]*npm run coverage[\s\S]*static_coverage_evidence\.mjs docstrings[\s\S]*git diff --check/, + 'the complete deterministic verification contract precedes publication', +); +assert.match( + workflow, + /--base "\$DEFAULT_BRANCH"/, + 'the trusted publisher opens exactly one PR against develop', +); +assert.match( + workflow, + /Do not merge, publish, release, push, or commit/, + 'the coding agent cannot own publication or merge decisions', +); +assert.match( + workflow, + /Central PR governance owns review, repair, revalidation, and merge/, + 'the existing organization review system remains authoritative', +); + +console.log('✓ hourly OpenCode commercial-readiness workflow contract passed'); From d73f0b8591d7133ed60a25151594b4e72f414aed Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:16:17 +0900 Subject: [PATCH 04/11] docs(doctoring): record hourly OpenCode NVIDIA NIM design --- .../hourly-opencode-commercial-readiness.md | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 docs/doctoring/hourly-opencode-commercial-readiness.md diff --git a/docs/doctoring/hourly-opencode-commercial-readiness.md b/docs/doctoring/hourly-opencode-commercial-readiness.md new file mode 100644 index 00000000..bab06123 --- /dev/null +++ b/docs/doctoring/hourly-opencode-commercial-readiness.md @@ -0,0 +1,161 @@ +# Hourly OpenCode commercial-readiness loop: evidence and design record + +## Decision + +ScopeWeave separates two autonomous responsibilities: + +1. organization-owned workflows review, repair, revalidate, and merge existing + pull requests under the repository rules; and +2. one repository-owned scheduled workflow may create a new product-development + pull request only when the open pull-request queue is empty. + +The product-development workflow runs OpenCode directly inside GitHub Actions and +uses the organization secret named `NVIDIA_NIM_API_KEY`. It does not create a +GitHub Copilot Agent Task, require a Copilot subscription, or use a fine-grained +user token. The OpenCode process receives the NVIDIA key but no GitHub mutation +credential. A later trusted shell step performs the commit, branch push, and pull +request creation only after deterministic verification and a second queue check. + +This boundary preserves the existing CodeRabbit, Noema, OpenCode-review, Strix, +and central merge-scheduler identities. The new workflow neither copies those +reviewers nor changes their keys, permissions, or approval semantics. + +## Authoritative platform and provider constraints + +OpenCode documents custom OpenAI-compatible providers through an explicit +provider identifier, the `@ai-sdk/openai-compatible` package, a `baseURL`, an +explicit model map, and an environment-derived API key. ScopeWeave follows that +contract for the NVIDIA hosted endpoint rather than embedding a credential or +adding a repository-specific provider client. + +NVIDIA documents NIM for large language models as an OpenAI-compatible inference +API. NVIDIA's hosted endpoint uses `https://integrate.api.nvidia.com/v1`, and the +API key is conventionally provided through `NVIDIA_API_KEY`. The workflow maps +the GitHub secret `NVIDIA_NIM_API_KEY` to that process-only environment variable. + +GitHub scheduled workflows execute from the latest commit on the default branch. +The hourly loop therefore remains inert until this workflow is reviewed and +merged into `develop`. GitHub also permits scheduled runs to be delayed or +omitted under load, so the design treats the schedule as a best-effort heartbeat, +not as a durable clock or service-level guarantee. + +GitHub recommends explicit least-privilege token permissions. The workflow-level +token is read-only. The job receives repository-content and pull-request write +permissions only because the trusted publication step must create one branch and +one pull request. The OpenCode command explicitly removes `GH_TOKEN`, +`GITHUB_TOKEN`, repository-token variables, and OIDC request variables from its +environment. The NVIDIA secret is scoped only to the gate and OpenCode steps and +is absent during dependency installation and test execution. + +## Supply-chain and execution controls + +OpenCode is installed from one explicit release archive. The workflow pins both +the release version and a SHA-256 digest and verifies the downloaded archive +before installation. It does not install `latest`, execute an unverified install +script, or allow a pull request to select the agent binary. + +The coding-agent process may edit the checked-out repository but may not commit, +push, open a pull request, merge, publish, or release. A post-agent boundary +rejects: + +- changes to review-agent and security-review workflows; +- changes to `.trivyignore`, `.semgrepignore`, or `.gitleaksignore`; +- credential-like GitHub or NVIDIA token literals; +- commits created by the agent; and +- whitespace or conflict-marker errors detected by `git diff --check`. + +The workflow then runs `npm ci`, all unit and API tests, coverage, the configured +docstring evidence gate, cloud browser E2E when available, and a final diff +check. Publication occurs only after these commands succeed. Current-head GitHub +Checks and independent reviews remain separate protected-branch evidence; a +successful local workflow run does not approve or merge its own pull request. + +## Single-flight and race handling + +The first gate fails closed when pull-request inventory is unavailable, when an +open pull request exists, or when the NVIDIA secret is absent. One repository-wide +non-cancelling concurrency group prevents two scheduled agents from running at +the same time. + +The workflow checks the open pull-request queue again immediately before branch +publication. If another actor created a pull request while the model was working, +the trusted publisher discards publication for that hour. GitHub does not expose +a repository-wide compare-and-create transaction for pull requests, so this does +not claim global atomicity against unrelated clients. Repository operators must +keep this workflow as the sole scheduled product-development producer. + +## Product-quality contract + +The assignment limits each run to one buyer-visible vertical slice. It requires: + +- red-green-refactor test-first development; +- realistic multi-tenant, concurrency, failure, migration, recovery, scale, and + accessibility cases appropriate to the selected feature; +- 100% statement, branch, function, and line coverage for new or materially + changed production modules; +- complete beginner-readable JSDoc or docstrings; +- descriptive two-word-or-longer `snake_case` database objects; +- standalone operation and replaceable MSA adapters; +- `contextual-orchestrator` for any product LLM path; +- deterministic validation of model output before persistence; +- APA 7th standards or peer-reviewed evidence in `docs/doctoring/`; +- Figma or Product Design only for genuine buyer-facing interaction work; and +- CHANGELOG, operations, security, migration, rollback, and release evidence + updates when relevant. + +The prompt explicitly prohibits security suppression, branch-protection changes, +self-merge, self-release, and unrelated refactoring. The model must leave a +working-tree change and a `PR_MESSAGE.md`; a trusted step packages that output as +one pull request against `develop`. + +## Verification contract + +The repository contract test must prove that the workflow: + +- runs hourly with non-cancelling single-flight concurrency; +- fails closed when a pull request exists or the NVIDIA secret is unavailable; +- contains no Copilot Agent Tasks endpoint or `COPILOT_GITHUB_TOKEN`; +- pins and verifies the OpenCode binary; +- uses the OpenAI-compatible NVIDIA endpoint and an environment key; +- strips GitHub mutation credentials from OpenCode; +- blocks reviewer-workflow and scanner-suppression changes; +- performs the complete deterministic verification sequence before publication; +- rechecks the pull-request queue before publishing; and +- leaves independent review, exact-head Checks, and merge authority with central + governance. + +The first live scheduled run additionally provides operational evidence that the +configured OpenCode release, NVIDIA model pool, and repository secret work in the +actual GitHub-hosted environment. Until that run succeeds, the workflow is +implemented and statically verified but not yet operationally proven. + +## Limitations + +The NVIDIA hosted model catalog can change independently of the repository. A +candidate-model failure causes the workflow to discard partial work and try the +next pinned model identifier. Failure of every candidate produces no pull +request. The model pool and OpenCode release should be updated only through a +reviewed pull request with current documentation and checksum evidence. + +The hourly schedule is not a durable job queue. Missed ticks, GitHub Actions +capacity, NVIDIA service availability, repository billing policy, or secret +rotation can postpone a run. The workflow deliberately fails closed instead of +creating overlapping or unverifiable work. + +## References + +Anomaly. (2026). *Providers*. OpenCode documentation. +https://opencode.ai/docs/providers + +GitHub. (2026a). *Events that trigger workflows*. GitHub Docs. +https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows + +GitHub. (2026b). *Security hardening for GitHub Actions*. GitHub Docs. +https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions + +GitHub. (2026c). *Workflow syntax for GitHub Actions*. GitHub Docs. +https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax + +NVIDIA Corporation. (2026). *API reference: NVIDIA NIM for large language +models*. NVIDIA Documentation. +https://docs.nvidia.com/nim/large-language-models/2.0.1/reference/api-reference.html From 0d8cb2d71137aadba5013b123ada01ea2921b9d5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:16:55 +0900 Subject: [PATCH 05/11] docs(operations): operate the hourly OpenCode development loop --- .../hourly-opencode-commercial-readiness.md | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 docs/operations/hourly-opencode-commercial-readiness.md diff --git a/docs/operations/hourly-opencode-commercial-readiness.md b/docs/operations/hourly-opencode-commercial-readiness.md new file mode 100644 index 00000000..dbac92fc --- /dev/null +++ b/docs/operations/hourly-opencode-commercial-readiness.md @@ -0,0 +1,174 @@ +# Hourly OpenCode commercial-readiness operations + +## Ownership + +The repository workflow `.github/workflows/hourly-opencode-commercial-readiness.yml` +creates product-development pull requests. It does not review or merge them. +Organization-central workflows remain responsible for review dispatch, review +feedback repair, exact-head Checks, branch updates, independent approval, and +policy-compliant merge. + +Only one scheduled product-development producer should exist for ScopeWeave. +Do not add a Copilot Agent Tasks scheduler or another repository-local PR merge +scheduler alongside this workflow. + +## Required configuration + +Configure the organization or repository Actions secret: + +- `NVIDIA_NIM_API_KEY`: NVIDIA hosted NIM API credential. + +The workflow maps this value to `NVIDIA_API_KEY` only for the OpenCode gate and +agent process. It does not use `COPILOT_GITHUB_TOKEN`, a Copilot subscription, a +fine-grained user token, or any review-agent credential. + +No additional GitHub token is required. The trusted publication step uses the +job-scoped `GITHUB_TOKEN` with `contents: write` and `pull-requests: write`. The +OpenCode process explicitly removes GitHub mutation and OIDC variables from its +environment. + +## Schedule and activation + +The workflow runs at minute 41 of each UTC hour and also supports a manual dry +run. Scheduled workflows are active only after the workflow exists on the +default branch. Until its pull request merges into `develop`, no hourly agent is +scheduled. + +A scheduled tick performs no coding when: + +- an open pull request exists; +- pull-request inventory cannot be read; +- `NVIDIA_NIM_API_KEY` is absent; +- another hourly run is active; +- every configured NVIDIA model fails; +- the agent creates a commit instead of a working-tree change; +- protected review workflow or scanner-suppression files change; +- deterministic verification fails; +- another pull request appears before publication; or +- the agent produces no source change. + +These outcomes are intentional fail-closed states, not reasons to bypass the +queue or required Checks. + +## Manual dry run + +From the Actions page, select **Hourly ScopeWeave OpenCode Commercial Readiness**, +choose **Run workflow**, and set `dry_run` to `true`. The run evaluates the +single-flight gate and prints the bounded assignment to the step summary without +checking out source, invoking NVIDIA NIM, creating a branch, or opening a pull +request. + +A dry run still requires an empty pull-request queue and a configured NVIDIA +secret because it verifies the same activation preconditions as a live run. + +## OpenCode and model updates + +The workflow pins: + +- the OpenCode release number; +- the SHA-256 digest of the Linux x64 archive; and +- an ordered NVIDIA NIM model-candidate pool. + +To update OpenCode: + +1. inspect the official release and security notes; +2. download the exact `opencode-linux-x64.tar.gz` asset independently; +3. calculate its SHA-256 digest; +4. update both `OPENCODE_VERSION` and `OPENCODE_SHA256` in one reviewed pull + request; +5. update the workflow contract test if the installation contract changes; +6. run a manual dry run and then one live empty-queue run; and +7. retain the previous version and digest in the pull-request evidence for + rollback. + +Never replace the pin with `latest`, an unverified installation script, or a +pull-request-controlled download URL. + +To update models, verify the model identifier against the current NVIDIA hosted +catalog and confirm OpenCode tool-call behavior. Keep at least two independent +candidates so a single model outage does not silently create partial work. A +failed candidate is followed by `git reset --hard` and `git clean -fd`; partial +changes never flow into the next candidate. + +## Verification and publication + +After OpenCode exits successfully, trusted workflow steps: + +1. prove the agent did not create commits; +2. enumerate tracked and untracked changes; +3. reject protected reviewer workflows and scanner-suppression files; +4. reject credential-like literals; +5. run `git diff --check`; +6. run `npm ci`; +7. run the full unit and API suites; +8. run coverage and configured docstring evidence; +9. run cloud browser E2E when available; +10. recheck that the open pull-request queue is still empty; +11. remove temporary OpenCode configuration and context snapshots; +12. create one conventional commit on `nim-agent/product-dev-`; and +13. open one pull request against `develop`. + +The newly opened pull request is not approved by this workflow. Required GitHub +Checks, CodeRabbit, Noema, OpenCode-review, Strix, unresolved-thread rules, and +independent approval remain authoritative. + +## Failure diagnosis + +### `pull_request_inventory_unavailable` + +Confirm that GitHub API access and repository Actions are healthy. Do not convert +this state into an empty queue. Rerun after the API is available. + +### `open_pull_request` + +No action is required. The central PR loop owns review, repair, revalidation, and +merge. The next empty-queue hourly tick may start product development. + +### `nim_api_key_unavailable` + +Verify that `NVIDIA_NIM_API_KEY` is available to this repository through the +organization or repository secret policy. Do not print or copy the secret into a +workflow variable, issue, log, or pull request. + +### Archive checksum failure + +Treat the release artifact as untrusted. Compare the configured version, asset +URL, and independently calculated digest. Update the pin only through a reviewed +pull request. Never disable `sha256sum -c`. + +### All model candidates fail + +Inspect provider availability and fixed OpenCode logs for the operation. Do not +reuse partial working-tree output. Confirm the NVIDIA endpoint, model catalog, +key validity, and rate or quota status before changing the pool. + +### Protected-file boundary failure + +Review the agent diff manually. Do not whitelist changes to CodeRabbit, Noema, +OpenCode-review, Strix, security-review, `.trivyignore`, `.semgrepignore`, or +`.gitleaksignore` in this workflow. Such changes require a separately scoped, +human-authored governance pull request. + +### Deterministic test failure + +The workflow must not publish. Reproduce the failure on a normal development +branch, fix the product or test contract, and rerun the full suite. Do not skip, +ignore, suppress, or lower coverage thresholds. + +### Queue changed before publication + +Another pull request appeared while OpenCode was working. The trusted publisher +leaves the agent output unpublished. The active pull request owns the queue and +must complete through central governance first. + +## Rollback + +Disable the loop without deleting evidence by disabling the workflow in GitHub +Actions. A source rollback reverts the workflow, its contract test, operations +record, doctoring record, and CHANGELOG entry together. Disabling or reverting +the product-development loop does not change the organization-central review +workflows or their credentials. + +If a newly opened agent pull request is unsafe or duplicate, close that pull +request and delete only its `nim-agent/product-dev-*` branch. Do not weaken +branch protection to merge it. From 2e1a4f74dc6f2af3811ff9fa3b3b0197c1af7a12 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:17:24 +0900 Subject: [PATCH 06/11] test(ci): run hourly OpenCode workflow contract --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7790e678..a350a827 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "coverage": "c8 --all --include=app.js --include=cloud-sync.js --include=scripts/ci/static_coverage_evidence.mjs --include=server/app.mjs --include=server/auth.mjs --reporter=json --reporter=json-summary npm run test:coverage", "server": "node server/server.mjs", "test:api": "node tests/api/auth-secret.test.mjs && node tests/api/smoke.mjs && node tests/api/ratelimit.test.mjs", - "test:unit": "node tests/unit/analytics.test.mjs && node tests/unit/cpm.test.mjs && node tests/unit/baseline-compare.test.mjs && node tests/unit/workload.test.mjs && node tests/unit/cost-evm.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/dep-types.test.mjs && node tests/unit/weekly-report.test.mjs && node tests/unit/clearfolio.test.mjs && node tests/unit/sprint-stats.test.mjs && node tests/unit/burndown.test.mjs && node tests/unit/pm-analysis.test.mjs && node tests/unit/cloud-sync-security.test.mjs", + "test:unit": "node tests/unit/analytics.test.mjs && node tests/unit/cpm.test.mjs && node tests/unit/baseline-compare.test.mjs && node tests/unit/workload.test.mjs && node tests/unit/cost-evm.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/dep-types.test.mjs && node tests/unit/weekly-report.test.mjs && node tests/unit/clearfolio.test.mjs && node tests/unit/sprint-stats.test.mjs && node tests/unit/burndown.test.mjs && node tests/unit/pm-analysis.test.mjs && node tests/unit/cloud-sync-security.test.mjs && node tests/config/hourly-opencode-commercial-readiness.test.mjs", "test:coverage": "node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && npm run test:api", "test:e2e": "playwright test", "test:e2e:headed": "playwright test --headed", From f5a2f3b565400c3d9ac626731d17f47190fe606b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:17:57 +0900 Subject: [PATCH 07/11] docs(changelog): record hourly OpenCode commercial-readiness loop --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e84f41f8..0540ca5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added a fail-closed hourly commercial-readiness loop that runs a pinned, + checksum-verified OpenCode agent against NVIDIA hosted NIM models only when + the pull-request queue is empty. The agent receives `NVIDIA_NIM_API_KEY` but + no GitHub mutation credential; a later trusted step performs deterministic + unit, API, coverage, docstring, cloud E2E, and diff verification before + opening exactly one pull request for central review and merge governance. - Added deterministic PM analysis for requirements/RFI/RFP readiness, WBS estimation coverage, dependency risk, and procurement package section checks. - Preserved PM-analysis research papers, NASA WBS handbook, BCP 14, and JSON @@ -32,6 +38,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added regression coverage that prevents array-valued passwords from being coerced into valid credentials. - Updated Hono runtime dependencies to patched supported releases. +- Prevented the product-development agent from modifying reviewer-owned + workflows or scanner-suppression files, inheriting GitHub mutation and OIDC + credentials, committing or publishing directly, or installing an unverified + OpenCode binary. ### Changed @@ -61,4 +71,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.1] - 2026-06-25 ### 성능 개선 (Performance) -- 드래그 앤 드롭 동작 중 `dragover` 이벤트에서 발생하는 O(N) 작업 리스트 검색 성능 병목 문제를, O(1) 해시맵(Map) 기반의 캐싱 조회 로직으로 개선하여 큰 크기의 WBS 리스트에서의 버벅임 현상을 해결했습니다. \ No newline at end of file +- 드래그 앤 드롭 동작 중 `dragover` 이벤트에서 발생하는 O(N) 작업 리스트 검색 성능 병목 문제를, O(1) 해시맵(Map) 기반의 캐싱 조회 로직으로 개선하여 큰 크기의 WBS 리스트에서의 버벅임 현상을 해결했습니다. From 09fb99a51478999b12a62e6ac5eee0377d14eda8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:22:09 +0900 Subject: [PATCH 08/11] test(ci): allow wrapped no-publication prompt text --- tests/config/hourly-opencode-commercial-readiness.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/config/hourly-opencode-commercial-readiness.test.mjs b/tests/config/hourly-opencode-commercial-readiness.test.mjs index 574dd14a..8cc42309 100644 --- a/tests/config/hourly-opencode-commercial-readiness.test.mjs +++ b/tests/config/hourly-opencode-commercial-readiness.test.mjs @@ -104,7 +104,7 @@ assert.match( ); assert.match( workflow, - /Do not merge, publish, release, push, or commit/, + /Do not merge, publish, release,\s+push, or commit/, 'the coding agent cannot own publication or merge decisions', ); assert.match( From 61738d266f8d0d863c4ff152af943520f1254cf1 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:27:32 +0900 Subject: [PATCH 09/11] test(ci): anchor the NVIDIA endpoint contract --- tests/config/hourly-opencode-commercial-readiness.test.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/config/hourly-opencode-commercial-readiness.test.mjs b/tests/config/hourly-opencode-commercial-readiness.test.mjs index 8cc42309..19fa0d26 100644 --- a/tests/config/hourly-opencode-commercial-readiness.test.mjs +++ b/tests/config/hourly-opencode-commercial-readiness.test.mjs @@ -54,8 +54,8 @@ assert.match( ); assert.match( workflow, - /https:\/\/integrate\.api\.nvidia\.com\/v1/, - 'OpenCode targets the NVIDIA hosted NIM OpenAI-compatible endpoint', + /^\s*"baseURL":\s*"https:\/\/integrate\.api\.nvidia\.com\/v1",?$/m, + 'OpenCode targets only the NVIDIA hosted NIM OpenAI-compatible endpoint', ); assert.match( workflow, From 54a0f5a940da58af0ff6d02e53083739b559d2fc Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:30:59 +0900 Subject: [PATCH 10/11] chore: align hourly agent tests with attachment security base --- package.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a350a827..6fac2dc5 100644 --- a/package.json +++ b/package.json @@ -10,20 +10,21 @@ }, "scripts": { "check:python-docstrings": "node scripts/ci/static_coverage_evidence.mjs docstrings", - "coverage": "c8 --all --include=app.js --include=cloud-sync.js --include=scripts/ci/static_coverage_evidence.mjs --include=server/app.mjs --include=server/auth.mjs --reporter=json --reporter=json-summary npm run test:coverage", + "coverage": "npm run test:coverage", "server": "node server/server.mjs", - "test:api": "node tests/api/auth-secret.test.mjs && node tests/api/smoke.mjs && node tests/api/ratelimit.test.mjs", - "test:unit": "node tests/unit/analytics.test.mjs && node tests/unit/cpm.test.mjs && node tests/unit/baseline-compare.test.mjs && node tests/unit/workload.test.mjs && node tests/unit/cost-evm.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/dep-types.test.mjs && node tests/unit/weekly-report.test.mjs && node tests/unit/clearfolio.test.mjs && node tests/unit/sprint-stats.test.mjs && node tests/unit/burndown.test.mjs && node tests/unit/pm-analysis.test.mjs && node tests/unit/cloud-sync-security.test.mjs && node tests/config/hourly-opencode-commercial-readiness.test.mjs", - "test:coverage": "node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && npm run test:api", + "test:api": "node tests/api/auth-secret.test.mjs && node tests/api/smoke.mjs && node tests/api/ratelimit.test.mjs && node tests/api/attachment-status.test.mjs", + "test:unit": "node tests/unit/analytics.test.mjs && node tests/unit/cpm.test.mjs && node tests/unit/baseline-compare.test.mjs && node tests/unit/workload.test.mjs && node tests/unit/cost-evm.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && node tests/unit/dep-types.test.mjs && node tests/unit/weekly-report.test.mjs && node tests/unit/clearfolio.test.mjs && node tests/unit/clearfolio-adapter-mock-hmac.test.mjs && node tests/unit/sprint-stats.test.mjs && node tests/unit/burndown.test.mjs && node tests/unit/pm-analysis.test.mjs && node tests/unit/cloud-sync-security.test.mjs && node tests/unit/attachment-status.test.mjs && node tests/unit/clearfolio-status-signal.test.mjs && node tests/unit/coverage-script-contract.test.mjs && node tests/config/hourly-opencode-commercial-readiness.test.mjs", + "test:coverage": "c8 --all --include=app.js --include=cloud-sync.js --include=scripts/ci/static_coverage_evidence.mjs --include=server/attachment_status.mjs --include=server/app.mjs --include=server/auth.mjs --include=server/clearfolio.mjs --reporter=json --reporter=json-summary npm run test:coverage:cases", + "test:coverage:cases": "node tests/unit/coverage-script-contract.test.mjs && node tests/unit/attachment-status.test.mjs && node tests/unit/clearfolio-status-signal.test.mjs && node tests/unit/clearfolio-adapter-mock-hmac.test.mjs && node tests/unit/msproject.test.mjs && node tests/unit/auth-password.test.mjs && node tests/unit/editor-unsaved.test.mjs && node tests/unit/static-coverage-evidence.test.mjs && npm run test:api", "test:e2e": "playwright test", "test:e2e:headed": "playwright test --headed", - "test:e2e:cloud": "playwright test tests/e2e/cloud.spec.js", + "test:e2e:cloud": "playwright install chromium && playwright test tests/e2e/cloud.spec.js", "test:fuzz": "playwright install chromium && playwright test tests/e2e/csv_formula_fuzz.spec.js", "fuzz": "node --test tests/fuzz/*.mjs" }, "dependencies": { "@hono/node-server": "^2.0.12", - "hono": "^4.12.32" + "hono": "^4.13.0" }, "devDependencies": { "@playwright/test": "1.61.1", From 95bd9057e7ebff205f5f6350552216b08c5c68b2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 5 Aug 2026 07:31:44 +0900 Subject: [PATCH 11/11] chore: align hourly agent changelog with attachment security base --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0540ca5b..831351d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added regression coverage that prevents array-valued passwords from being coerced into valid credentials. - Updated Hono runtime dependencies to patched supported releases. +- Sanitized Clearfolio submission, status, and artifact-link transport failures + so network details and downstream response text cannot reach browser or + diagnostic payloads; rejected unknown or whitespace-padded conversion states + and malformed, unsupported-scheme, or HTTPS-downgrade artifact links. - Prevented the product-development agent from modifying reviewer-owned workflows or scanner-suppression files, inheriting GitHub mutation and OIDC credentials, committing or publishing directly, or installing an unverified @@ -45,6 +49,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Attachment-list status refresh now removes the per-row database lookup, + uses a configurable bounded worker pool with per-item abortable timeouts and + a request-wide latency budget, preserves stale status after downstream, + timeout, malformed-response, and persistence failures, excludes internal + conversion identifiers from responses, reports attempted, changed, failed, + skipped-data, and deferred-budget counters separately, and exposes fixed + low-cardinality timeout, lookup, validation, and persistence failure counters. - 프로젝트 이름 입력 필드에 입력 예시(placeholder)를 추가하여 사용자 편의성을 개선했습니다. - 데이터 테이블의 반복되는 액션 버튼에 컨텍스트 정보(작업명)를 포함한 명시적인 ARIA 레이블을 추가하고, 유효성 검사 에러를 폼 필드에 연결하여 접근성을 개선했습니다. - `createGanttBarElement`, `renderGantt`, `buildWeekdayTimeline`에서 반복적으로 호출되던 `compareDateStrings`를 직접적인 문자열 비교 연산(`>=`, `<=`)으로 교체하여 O(N*D) 복잡도의 캐시 스레싱과 정규식 검사를 방지했습니다.