diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000000..5874142c02 --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2026-08-01 - Flicker-Free Real-Time CLI Dashboards with Rich Live +**Learning:** Terminal dashboards that clear the screen using raw ANSI escape codes (`\033[H\033[J`) or `clear` commands create severe flicker and redraw lag. This harms cognitive accessibility and visual appeal. Using `rich.live.Live` with high-level structural layout (`Table`, `Panel`, `Text`) ensures updates are drawn to the screen differential/flicker-free, and handles terminal exits cleanly. +**Action:** Always prefer `rich.live.Live` (or similar differential-updating curses-like tools) for terminal UI dashboards that require frequent, real-time telemetry updates. diff --git a/.coderabbit.yaml b/.coderabbit.yaml new file mode 100644 index 0000000000..1c7e296596 --- /dev/null +++ b/.coderabbit.yaml @@ -0,0 +1,21 @@ +# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json +# Agent: Grok β€” autofix enabled so CodeRabbit applies without manual loops. +reviews: + profile: assertive + high_level_summary: true + request_changes_workflow: false + auto_review: + enabled: true + drafts: true + auto_incremental_review: true + base_branches: + - master + - master-staging + - feature/skyhook + finishing_touches: + autofix: + enabled: true + auto_apply_labels: false + +chat: + auto_reply: true diff --git a/.github/workflows/agent-feedback-linear-sync.yml b/.github/workflows/agent-feedback-linear-sync.yml new file mode 100644 index 0000000000..3d8f945de1 --- /dev/null +++ b/.github/workflows/agent-feedback-linear-sync.yml @@ -0,0 +1,186 @@ +name: Agent feedback β†’ Linear subtasks + +# Every CodeRabbit / Devin (and future bot) review comment becomes a Linear +# subtask under a per-PR parent issue, labeled agent-feedback. +# Requires: secrets.LINEAR_API_KEY + +on: + pull_request_review_comment: + types: [created] + pull_request_review: + types: [submitted] + +concurrency: + group: linear-feedback-${{ github.event.pull_request.number }} + cancel-in-progress: false + +jobs: + sync-linear: + if: | + ( + github.event_name == 'pull_request_review_comment' && + ( + contains(github.event.comment.user.login, 'coderabbit') || + contains(github.event.comment.user.login, 'devin') || + contains(github.event.comment.user.login, 'copilot') || + github.event.comment.user.type == 'Bot' + ) && + !contains(github.event.comment.body || '', '') && + !contains(github.event.comment.body || '', '') + ) || + ( + github.event_name == 'pull_request_review' && + github.event.review.state != 'approved' && + ( + contains(github.event.review.user.login, 'coderabbit') || + contains(github.event.review.user.login, 'devin') || + github.event.review.user.type == 'Bot' + ) + ) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Sync to Linear + env: + LINEAR_API_KEY: ${{ secrets.LINEAR_API_KEY }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: actions/github-script@v7 + with: + script: | + const key = process.env.LINEAR_API_KEY; + if (!key) { + core.warning('LINEAR_API_KEY not set β€” skip Linear subtask sync'); + return; + } + const pr = context.payload.pull_request; + const prNumber = pr.number; + const prUrl = pr.html_url; + const bot = + context.payload.comment?.user?.login || + context.payload.review?.user?.login || + 'bot'; + const path = context.payload.comment?.path || ''; + const commentBody = ( + context.payload.comment?.body || + context.payload.review?.body || + '' + ).slice(0, 3500); + const commentUrl = + context.payload.comment?.html_url || + context.payload.review?.html_url || + prUrl; + + async function linear(query, variables) { + const res = await fetch('https://api.linear.app/graphql', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: key, + }, + body: JSON.stringify({ query, variables }), + }); + const json = await res.json(); + if (json.errors) { + throw new Error(JSON.stringify(json.errors)); + } + return json.data; + } + + const teamId = '1e672463-31de-40b2-a378-3c03fd8f7e3b'; + const parentTitle = `PR #${prNumber} agent feedback rollup`; + + const search = await linear( + `query($q: String!) { + issueSearch(query: $q, first: 5) { + nodes { id identifier title } + } + }`, + { q: `team:Termux-monorepo_linear title:"${parentTitle}"` } + ); + let parentId = search.issueSearch?.nodes?.find( + n => n.title === parentTitle + )?.id; + + if (!parentId) { + const created = await linear( + `mutation($input: IssueCreateInput!) { + issueCreate(input: $input) { + success + issue { id identifier url } + } + }`, + { + input: { + teamId, + title: parentTitle, + description: [ + '**Agent: Jules | Grok**', + '', + `Parent rollup for automated review feedback on ${prUrl}`, + '', + 'Subtasks are created by GHA `agent-feedback-linear-sync`.', + 'Jules auto-resolve via `agent-review-auto-jules`.', + '', + 'Signed-off-by: Grok ', + ].join('\n'), + }, + } + ); + parentId = created.issueCreate.issue.id; + core.info(`Created parent ${created.issueCreate.issue.identifier}`); + } + + const labels = await linear( + `query { issueLabels(filter: { name: { eq: "agent-feedback" } }) { nodes { id } } }` + ); + const labelId = labels.issueLabels?.nodes?.[0]?.id; + + const subTitle = path + ? `[${bot}] PR #${prNumber}: ${path}` + : `[${bot}] PR #${prNumber}: review feedback`; + + const sub = await linear( + `mutation($input: IssueCreateInput!) { + issueCreate(input: $input) { + success + issue { id identifier url } + } + }`, + { + input: { + teamId, + parentId, + title: subTitle.slice(0, 200), + description: [ + '**Agent: Jules | Grok**', + '', + `Source: ${commentUrl}`, + `PR: ${prUrl}`, + `Bot: ${bot}`, + path ? `Path: \`${path}\`` : '', + '', + '### Comment', + commentBody, + '', + 'Auto-synced by agent-feedback-linear-sync.yml', + ].filter(Boolean).join('\n'), + ...(labelId ? { labelIds: [labelId] } : {}), + }, + } + ); + core.info(`Subtask ${sub.issueCreate.issue.identifier} ${sub.issueCreate.issue.url}`); + + if (context.payload.comment?.id) { + try { + await github.rest.reactions.createForPullRequestReviewComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: context.payload.comment.id, + content: 'eyes', + }); + } catch (e) { + core.info(String(e)); + } + } diff --git a/.github/workflows/agent-jules-on-issues.yml b/.github/workflows/agent-jules-on-issues.yml new file mode 100644 index 0000000000..d63f3e3c66 --- /dev/null +++ b/.github/workflows/agent-jules-on-issues.yml @@ -0,0 +1,251 @@ +name: Jules on Issues (label / @jules) + +# Native Jules already responds when the GitHub App sees label "jules". +# This workflow adds: +# 1) Explicit acknowledge + structured prompt via jules-invoke (if JULES_API_KEY set) +# 2) Fallback @jules comment so the App path still fires without API key +# 3) Prior open-PR inventory injected into prompt (coordination) +# 4) marker so Gemini does not claim the same files +# +# Requires: Jules GitHub App installed on this repo +# Optional: secrets.JULES_API_KEY for google-labs-code/jules-invoke +# +# SECURITY: Issue triggers are restricted β€” untrusted openers cannot burn quota. + +on: + issues: + types: [labeled, opened] + issue_comment: + types: [created] + +concurrency: + group: jules-issue-${{ github.event.issue.number || github.run_id }} + cancel-in-progress: false + +jobs: + jules-on-label: + if: | + github.event_name == 'issues' && + github.event.action == 'labeled' && + ( + github.event.label.name == 'jules' || + github.event.label.name == 'Jules' || + github.event.label.name == 'JULES' + ) + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: read + steps: + - name: Acknowledge (πŸ‘€) + inventory open agent PRs + id: coord + uses: actions/github-script@v7 + with: + script: | + const issue = context.payload.issue.number; + try { + await github.rest.reactions.createForIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue, + content: 'eyes', + }); + } catch (e) { + core.info('Reaction skip: ' + e.message); + } + const marker = ''; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue, + per_page: 50, + }); + if (comments.some(c => c.body && c.body.includes(marker))) { + core.info('Already acknowledged'); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue, + body: [ + marker, + `πŸ‘€ **Jules summoned** on issue #${issue} via label \`jules\`.`, + ``, + `Jules (Google Labs) will plan β†’ implement in a Cloud VM β†’ open a PR.`, + `Coordination: prior open agent PRs are injected into the task prompt.`, + ``, + `Tracking: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, + ].join('\n'), + }); + } + // Inventory open PRs (agent bots + issue-linked) + const { data: prs } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 50, + }); + const agentLogins = ['google-labs-jules[bot]', 'devin-ai-integration[bot]', 'coderabbitai[bot]', 'ecc-tools[bot]']; + const relevant = prs.filter(p => { + const u = (p.user && p.user.login) || ''; + const body = (p.body || '') + ' ' + (p.title || ''); + return agentLogins.some(a => u.includes(a.split('[')[0])) || + body.includes(`#${issue}`) || + body.toLowerCase().includes(`issue ${issue}`); + }).slice(0, 15); + const inventory = relevant.map(p => + `- PR #${p.number} @${p.user.login}: ${p.title} (base=${p.base.ref} head=${p.head.ref})` + ).join('\n') || '(none matching)'; + core.setOutput('prior_prs', inventory); + + - name: Invoke Jules API (optional) + if: ${{ secrets.JULES_API_KEY != '' }} + continue-on-error: true + uses: google-labs-code/jules-invoke@v1 + with: + jules_api_key: ${{ secrets.JULES_API_KEY }} + starting_branch: master-staging + prompt: | + You are Jules working on termux-monorepo. Read AGENTS.md and GEMINI.md if present. + + ## Issue #${{ github.event.issue.number }}: ${{ github.event.issue.title }} + + ${{ github.event.issue.body }} + + ## Open agent / related PRs (DO NOT overlap files) + ${{ steps.coord.outputs.prior_prs }} + + ## COORDINATION RULES (mandatory) + 1. Before changing any file, respect the open PRs listed above β€” do not modify files already present in those diffs unless that PR is closed/superseded. + 2. Prefer disjoint file sets vs Gemini / other agents on the same issue. + 3. After opening a PR, post a comment on the issue with: + + claimed_by: jules + issue: ${{ github.event.issue.number }} + files: + pr: + 4. Base branch: master-staging. Minimal diffs. No secrets. Respect repo gates. + 5. If another agent already claimed the core work, review their PR instead of duplicating. + + ## Instructions + 1. Diagnose root cause; prefer minimal diffs. + 2. Preserve Sentinel 0o600/0o700 patterns if touching credentials/session paths. + 3. Open a PR; cite Implements if an ITEMS.md id applies. + 4. Run or respect repo gates (repo_gate / termux_smoke) where possible. + 5. Do not commit secrets or Class 3/4 artifacts. + + - name: Fallback @jules ping (App path) + if: ${{ secrets.JULES_API_KEY == '' }} + uses: actions/github-script@v7 + with: + script: | + const issue = context.payload.issue.number; + const marker = ''; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue, + per_page: 30, + }); + if (comments.some(c => c.body && c.body.includes(marker))) return; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue, + body: [ + marker, + `@jules Please implement a fix for this issue.`, + ``, + `Base your work on **master-staging**. Prefer minimal diffs; respect AGENTS.md.`, + `Check open agent PRs first β€” do not edit files already claimed by another agent on this issue.`, + `Open a PR when done and post on the issue.`, + ].join('\n'), + }); + + jules-on-mention: + if: | + github.event_name == 'issue_comment' && + !github.event.issue.pull_request && + github.event.sender.type == 'User' && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association) && + ( + startsWith(github.event.comment.body, '@jules') || + startsWith(github.event.comment.body, '@Jules') + ) + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: read + steps: + - name: React πŸ‘€ on comment + inventory PRs + id: coord + uses: actions/github-script@v7 + with: + script: | + try { + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: context.payload.comment.id, + content: 'eyes', + }); + } catch (e) { + core.info('Reaction skip: ' + e.message); + } + const issue = context.payload.issue.number; + const { data: prs } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 50, + }); + const agentLogins = ['google-labs-jules', 'devin-ai-integration', 'coderabbitai', 'ecc-tools']; + const relevant = prs.filter(p => { + const u = (p.user && p.user.login) || ''; + const body = (p.body || '') + ' ' + (p.title || ''); + return agentLogins.some(a => u.includes(a)) || + body.includes(`#${issue}`) || + body.toLowerCase().includes(`issue ${issue}`); + }).slice(0, 15); + const inventory = relevant.map(p => + `- PR #${p.number} @${p.user.login}: ${p.title}` + ).join('\n') || '(none matching)'; + core.setOutput('prior_prs', inventory); + + - name: Ensure jules label + uses: actions/github-script@v7 + with: + script: | + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: ['jules'], + }); + } catch (e) { + core.info('Label add skip: ' + e.message); + } + + - name: Invoke Jules API on mention (optional) + if: ${{ secrets.JULES_API_KEY != '' }} + continue-on-error: true + uses: google-labs-code/jules-invoke@v1 + with: + jules_api_key: ${{ secrets.JULES_API_KEY }} + starting_branch: master-staging + prompt: | + Issue #${{ github.event.issue.number }}: ${{ github.event.issue.title }} + + ${{ github.event.issue.body }} + + User request: + ${{ github.event.comment.body }} + + ## Open agent / related PRs (DO NOT overlap files) + ${{ steps.coord.outputs.prior_prs }} + + COORDINATION: Prefer disjoint files vs other agents. Post after opening a PR. + Follow AGENTS.md. Base branch master-staging. Minimal diffs. Open a PR. diff --git a/.github/workflows/agent-review-auto-jules.yml b/.github/workflows/agent-review-auto-jules.yml new file mode 100644 index 0000000000..a4342da80d --- /dev/null +++ b/.github/workflows/agent-review-auto-jules.yml @@ -0,0 +1,171 @@ +name: Agent review β†’ auto Jules + +# When CodeRabbit, Devin, or other review bots leave feedback, automatically +# summon Jules to apply fixes. Operator no longer comments "@jules resolve". +# +# Requires: secrets.JULES_API_KEY (optional but recommended for invoke path) +# Jules GitHub App must have repo access. Prefer Reactive Mode OFF so Jules +# also picks up the posted @jules comment on PRs it owns. + +on: + pull_request_review: + types: [submitted] + pull_request_review_comment: + types: [created] + issue_comment: + types: [created] + +concurrency: + group: agent-auto-jules-${{ github.event.pull_request.number || github.event.issue.number || github.run_id }} + cancel-in-progress: false + +jobs: + detect-bot-feedback: + if: | + ( + github.event_name == 'pull_request_review' && + github.event.review.state != 'approved' && + ( + contains(github.event.review.user.login, 'coderabbit') || + contains(github.event.review.user.login, 'devin') || + contains(github.event.review.user.login, 'copilot') || + github.event.review.user.type == 'Bot' + ) + ) || + ( + github.event_name == 'pull_request_review_comment' && + ( + contains(github.event.comment.user.login, 'coderabbit') || + contains(github.event.comment.user.login, 'devin') || + contains(github.event.comment.user.login, 'copilot') || + github.event.comment.user.type == 'Bot' + ) && + !contains(github.event.comment.body, '') + ) || + ( + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + ( + contains(github.event.comment.user.login, 'coderabbit') || + contains(github.event.comment.user.login, 'devin') + ) && + !contains(github.event.comment.body, '') + ) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + issues: write + outputs: + pr_number: ${{ steps.meta.outputs.pr_number }} + head_ref: ${{ steps.meta.outputs.head_ref }} + should_invoke: ${{ steps.meta.outputs.should_invoke }} + steps: + - name: Resolve PR metadata + id: meta + uses: actions/github-script@v7 + with: + script: | + const event = context.eventName; + let prNumber = null; + if (event === 'pull_request_review') { + prNumber = context.payload.pull_request.number; + } else if (event === 'pull_request_review_comment') { + prNumber = context.payload.pull_request.number; + } else if (event === 'issue_comment') { + prNumber = context.payload.issue.number; + } + if (!prNumber) { + core.setOutput('should_invoke', 'false'); + return; + } + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + core.setOutput('pr_number', String(prNumber)); + core.setOutput('head_ref', pr.head.ref); + core.setOutput('base_ref', pr.base.ref); + core.setOutput('should_invoke', 'true'); + + - name: Post @jules resolve (idempotent window) + if: steps.meta.outputs.should_invoke == 'true' + uses: actions/github-script@v7 + with: + script: | + const prNumber = Number('${{ steps.meta.outputs.pr_number }}'); + const head = '${{ steps.meta.outputs.head_ref }}'; + const marker = ''; + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + per_page: 50, + }); + const recent = comments + .filter(c => c.body && c.body.includes(marker)) + .sort((a, b) => new Date(b.created_at) - new Date(a.created_at))[0]; + if (recent) { + const ageMs = Date.now() - new Date(recent.created_at).getTime(); + if (ageMs < 20 * 60 * 1000) { + core.info('Debounced: recent agent-auto-jules comment exists'); + return; + } + } + const bot = + context.payload.review?.user?.login || + context.payload.comment?.user?.login || + 'review-bot'; + const snippet = ( + context.payload.review?.body || + context.payload.comment?.body || + '' + ).slice(0, 1200); + const path = context.payload.comment?.path || ''; + const body = [ + marker, + `@jules **Auto-resolve** (GHA agent-review-auto-jules) β€” do not wait for a human ping.`, + ``, + `Bot feedback from **${bot}** on PR #${prNumber} (branch \`${head}\`).`, + path ? `File: \`${path}\`` : '', + ``, + `### Feedback excerpt`, + snippet ? '```' : '', + snippet || '(see review threads)', + snippet ? '```' : '', + ``, + `### Instructions`, + `1. Address **all open review threads** on this PR (CodeRabbit, Devin, Copilot, etc.).`, + `2. Prefer minimal diffs; preserve Sentinel 0o600/0o700 if those files are touched.`, + `3. Push commits to branch \`${head}\`. Do not retarget away from the PR base without cause.`, + `4. If conflicts with base exist, resolve them.`, + `5. Skip pure nits only if they conflict with security/gates; otherwise apply autofixes.`, + ``, + `Agent: Grok orchestration Β· Profile: https://x.com/grok`, + ].filter(Boolean).join('\n'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body, + }); + + invoke-jules-api: + needs: detect-bot-feedback + if: needs.detect-bot-feedback.outputs.should_invoke == 'true' && vars.JULES_AUTO_INVOKE != '0' + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Jules API session (if key present) + env: + JULES_API_KEY: ${{ secrets.JULES_API_KEY }} + PR: ${{ needs.detect-bot-feedback.outputs.pr_number }} + HEAD: ${{ needs.detect-bot-feedback.outputs.head_ref }} + run: | + if [ -z "$JULES_API_KEY" ]; then + echo "No JULES_API_KEY β€” relying on @jules PR comment path only" + exit 0 + fi + echo "Jules API invoke is best-effort; @jules comment is the reliable trigger." diff --git a/.github/workflows/gemini-dispatch.yml b/.github/workflows/gemini-dispatch.yml new file mode 100644 index 0000000000..2f7e2d4805 --- /dev/null +++ b/.github/workflows/gemini-dispatch.yml @@ -0,0 +1,198 @@ +name: 'πŸ”€ Gemini Dispatch (free-tier agentic)' + +# Central router for free-tier Gemini CLI agentic CI/CD. +# Requires: secrets.GEMINI_API_KEY (Google AI Studio free quota) +# Complements existing Jules + CodeRabbit stack. +# +# Ack pattern: posts πŸ‘€ on the triggering comment (same UX as Jules/CodeRabbit). +# Coordination: prior open agent PRs are passed into triage/review/invoke prompts. +# +# INTENTIONAL AGENTIC SURFACE (ADE): +# Agents may use tools / shell / gh CLI inside trusted runs. That is required for +# an Automated Agentic Development Environment. Mitigations: +# - @gemini-cli triggers require OWNER/MEMBER/COLLABORATOR +# - Fork PRs excluded from auto review +# - GEMINI.md hard rules (no secrets, master-staging, gates, claim markers) +# - No secrets interpolated into prompts from untrusted issue bodies +# See docs/AGENTIC-CICD-FREE-TIER.md Β§ Security / PromptPwnd. + +on: + pull_request: + types: [opened, ready_for_review] + issues: + types: [opened, reopened] + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + pull_request_review: + types: [submitted] + +defaults: + run: + shell: bash + +jobs: + dispatch: + if: | + ( + github.event_name == 'pull_request' && + github.event.pull_request.head.repo.fork == false && + github.event.pull_request.draft == false + ) || ( + github.event_name == 'issues' && + contains(fromJSON('["opened", "reopened"]'), github.event.action) && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.issue.author_association) + ) || ( + github.event.sender.type == 'User' && + startsWith(github.event.comment.body || github.event.review.body || '', '@gemini-cli') && + contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association || github.event.review.author_association || '') + ) + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + outputs: + command: ${{ steps.extract.outputs.command }} + additional_context: ${{ steps.extract.outputs.additional_context }} + prior_prs: ${{ steps.extract.outputs.prior_prs }} + issue_number: ${{ steps.extract.outputs.issue_number }} + pr_number: ${{ steps.extract.outputs.pr_number }} + steps: + - name: Extract command + prior PR inventory + id: extract + uses: actions/github-script@v7 + env: + EVENT_TYPE: ${{ github.event_name }}.${{ github.event.action }} + REQUEST: ${{ github.event.comment.body || github.event.review.body || github.event.issue.body || '' }} + with: + script: | + const eventType = process.env.EVENT_TYPE; + const request = process.env.REQUEST || ''; + const prNum = context.payload.pull_request?.number || + (context.payload.issue?.pull_request ? context.payload.issue.number : null) || + null; + const issueNum = context.payload.issue?.number || context.payload.pull_request?.number || null; + core.setOutput('pr_number', prNum ? String(prNum) : ''); + core.setOutput('issue_number', issueNum ? String(issueNum) : ''); + + if (eventType === 'pull_request.opened' || eventType === 'pull_request.ready_for_review') { + core.setOutput('command', 'review'); + } else if (['issues.opened', 'issues.reopened'].includes(eventType)) { + core.setOutput('command', 'triage'); + } else if (request.startsWith('@gemini-cli /review')) { + core.setOutput('command', 'review'); + core.setOutput('additional_context', request.replace(/^@gemini-cli \/review/, '').trim()); + } else if (request.startsWith('@gemini-cli /triage')) { + core.setOutput('command', 'triage'); + } else if (request.startsWith('@gemini-cli')) { + core.setOutput('command', 'invoke'); + core.setOutput('additional_context', request.replace(/^@gemini-cli/, '').trim()); + } else { + core.setOutput('command', 'none'); + } + + // Prior open agent PRs for coordination + try { + const { data: prs } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + per_page: 40, + }); + const agentHints = ['jules', 'devin', 'coderabbit', 'ecc-tools', 'gemini']; + const relevant = prs.filter(p => { + const u = ((p.user && p.user.login) || '').toLowerCase(); + const body = ((p.body || '') + ' ' + (p.title || '')).toLowerCase(); + return agentHints.some(a => u.includes(a)) || + (issueNum && (body.includes('#' + issueNum) || body.includes('issue ' + issueNum))); + }).slice(0, 12); + const inventory = relevant.map(p => + `PR #${p.number} @${p.user.login}: ${p.title}` + ).join(' | ') || 'none'; + core.setOutput('prior_prs', inventory); + } catch (e) { + core.setOutput('prior_prs', 'unavailable'); + } + + - name: Acknowledge with πŸ‘€ + comment + if: steps.extract.outputs.command != 'none' + uses: actions/github-script@v7 + with: + script: | + const cmd = '${{ steps.extract.outputs.command }}'; + const number = context.payload.pull_request?.number || context.payload.issue?.number; + if (context.payload.comment?.id) { + try { + await github.rest.reactions.createForIssueComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: context.payload.comment.id, + content: 'eyes', + }); + } catch (e) { + core.info('Comment reaction skip: ' + e.message); + } + } else if (number) { + try { + await github.rest.reactions.createForIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: number, + content: 'eyes', + }); + } catch (e) { + core.info('Issue reaction skip: ' + e.message); + } + } + if (context.payload.comment || context.payload.review) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: number, + body: `πŸ€– **Gemini CLI** received your request (\`${cmd}\`). Tracking: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, + }); + } + + triage: + needs: dispatch + if: needs.dispatch.outputs.command == 'triage' + uses: ./.github/workflows/gemini-triage.yml + permissions: + contents: read + issues: write + pull-requests: write + with: + additional_context: ${{ needs.dispatch.outputs.additional_context }} + prior_prs: ${{ needs.dispatch.outputs.prior_prs }} + secrets: inherit + + review: + needs: dispatch + if: needs.dispatch.outputs.command == 'review' + uses: ./.github/workflows/gemini-review.yml + permissions: + contents: read + issues: write + pull-requests: write + with: + additional_context: ${{ needs.dispatch.outputs.additional_context }} + prior_prs: ${{ needs.dispatch.outputs.prior_prs }} + pr_number: ${{ needs.dispatch.outputs.pr_number }} + secrets: inherit + + invoke: + needs: dispatch + if: needs.dispatch.outputs.command == 'invoke' + uses: ./.github/workflows/gemini-invoke.yml + permissions: + contents: read + issues: write + pull-requests: write + with: + additional_context: ${{ needs.dispatch.outputs.additional_context }} + prior_prs: ${{ needs.dispatch.outputs.prior_prs }} + pr_number: ${{ needs.dispatch.outputs.pr_number }} + issue_number: ${{ needs.dispatch.outputs.issue_number }} + secrets: inherit diff --git a/.github/workflows/gemini-invoke.yml b/.github/workflows/gemini-invoke.yml new file mode 100644 index 0000000000..7a6c7476a6 --- /dev/null +++ b/.github/workflows/gemini-invoke.yml @@ -0,0 +1,65 @@ +name: '▢️ Gemini Invoke (on-demand free-tier teammate)' + +on: + workflow_call: + inputs: + additional_context: + type: string + required: false + prior_prs: + type: string + required: false + default: 'none' + pr_number: + type: string + required: false + default: '' + issue_number: + type: string + required: false + default: '' + +concurrency: + group: gemini-invoke-${{ inputs.pr_number || inputs.issue_number || github.event.pull_request.number || github.event.issue.number || github.run_id }} + cancel-in-progress: false + +jobs: + invoke: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Run Gemini CLI assistant + uses: google-github-actions/run-gemini-cli@v0 + env: + GEMINI_CLI_TRUST_WORKSPACE: 'true' + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + gemini_api_key: ${{ secrets.GEMINI_API_KEY }} + github_pr_number: ${{ inputs.pr_number || github.event.pull_request.number }} + github_issue_number: ${{ inputs.issue_number || github.event.issue.number }} + prompt: | + You are the on-demand free-tier Gemini CLI teammate for termux-monorepo. + Read GEMINI.md and AGENTS.md first. + + User request / additional context: + ${{ inputs.additional_context }} + + ## Open agent / related PRs (coordination β€” DO NOT overlap files) + ${{ inputs.prior_prs }} + + ## COORDINATION RULES + 1. Jules is the primary *builder* (creates branches/PRs). You are primarily triage/review/analysis unless the user explicitly asks you to implement and write is possible. + 2. Do not edit files already changed in open agent PRs for this issue. + 3. If you open or recommend a PR, suggest posting with claimed_by: gemini and file list. + 4. Prefer reviewing Jules/Devin PRs over duplicating their work. + + Perform the request within free-tier limits. Prefer analysis + concrete suggestions or minimal patches. + If code changes are required and you cannot push, describe the exact diff and next steps for Jules or a human. + Never invent work outside the proposal registry process. Never commit secrets. diff --git a/.github/workflows/gemini-review.yml b/.github/workflows/gemini-review.yml new file mode 100644 index 0000000000..4475f4646f --- /dev/null +++ b/.github/workflows/gemini-review.yml @@ -0,0 +1,58 @@ +name: 'πŸ” Gemini PR Review (free-tier)' + +on: + workflow_call: + inputs: + additional_context: + type: string + required: false + prior_prs: + type: string + required: false + default: 'none' + pr_number: + type: string + required: false + default: '' + +concurrency: + group: gemini-review-${{ inputs.pr_number || github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + +jobs: + review: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + fetch-depth: 0 + + - name: Run Gemini CLI PR review + uses: google-github-actions/run-gemini-cli@v0 + env: + GEMINI_CLI_TRUST_WORKSPACE: 'true' + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + gemini_api_key: ${{ secrets.GEMINI_API_KEY }} + github_pr_number: ${{ inputs.pr_number || github.event.pull_request.number || github.event.issue.number }} + prompt: | + You are the free-tier agentic PR reviewer for termux-monorepo. + Read GEMINI.md and AGENTS.md. + + Review this pull request for: + - Correctness and regressions + - Security (especially credentials, session stores, chmod 0o600/0o700 patterns) + - Alignment with AGENTS.md hard rules (master-staging, gates, no Class 3/4 artifacts) + - Minimal-diff preference + - Overlap with other open agent PRs: ${{ inputs.prior_prs }} + + Post a concise review comment. Do not approve or request changes via the formal review API unless clearly authorized; prefer a comment. + Coordinate with CodeRabbit (already reviewing) and Jules (may auto-fix later). + If this is a Jules PR, focus on gaps Jules may have missed rather than rewriting the same work. + + Additional context: ${{ inputs.additional_context }} diff --git a/.github/workflows/gemini-triage.yml b/.github/workflows/gemini-triage.yml new file mode 100644 index 0000000000..3441b11fac --- /dev/null +++ b/.github/workflows/gemini-triage.yml @@ -0,0 +1,52 @@ +name: '🏷️ Gemini Issue Triage (free-tier)' + +on: + workflow_call: + inputs: + additional_context: + type: string + required: false + prior_prs: + type: string + required: false + default: 'none' + +concurrency: + group: gemini-triage-${{ github.event.issue.number || github.run_id }} + cancel-in-progress: false + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Run Gemini CLI triage + uses: google-github-actions/run-gemini-cli@v0 + env: + GEMINI_CLI_TRUST_WORKSPACE: 'true' + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + gemini_api_key: ${{ secrets.GEMINI_API_KEY }} + github_issue_number: ${{ github.event.issue.number }} + prompt: | + You are the free-tier agentic triage agent for termux-monorepo. + Read GEMINI.md and AGENTS.md if present. + + Task: Triage the current GitHub issue. + 1. Classify (bug / feature / docs / question / security / duplicate / invalid). + 2. Suggest or apply appropriate labels and a priority (critical/high/medium/low) if the token allows label writes. + 3. If it looks like a duplicate, search existing open issues and link them. + 4. For bugs, ask for minimal reproduction steps if missing. + 5. Note any open agent PRs already addressing this area: + ${{ inputs.prior_prs }} + 6. Post a short, actionable comment summarizing triage. If implementation is needed, recommend labeling `jules` or `@jules` (Jules is the primary builder). + + Additional context: ${{ inputs.additional_context }} + Stay within free-tier good citizenship (concise, no speculative long work). diff --git a/.github/workflows/publish-wiki.yml b/.github/workflows/publish-wiki.yml new file mode 100644 index 0000000000..e4e126007e --- /dev/null +++ b/.github/workflows/publish-wiki.yml @@ -0,0 +1,37 @@ +name: Publish wiki + +on: + push: + branches: [master, master-staging] + paths: + - "wiki/**" + - ".github/workflows/publish-wiki.yml" + workflow_dispatch: + +concurrency: + group: publish-wiki + # Match agent-feedback-linear-sync: do not cancel in-flight wiki publishes + # (a workflow_dispatch from one ref must not be dropped by an unrelated push). + cancel-in-progress: false + +permissions: + contents: write + +jobs: + publish-wiki: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Publish wiki/ β†’ GitHub Wiki + uses: Andrew-Chen-Wang/github-wiki-action@v5 + with: + path: wiki + strategy: clone + # First bootstrap only: if the wiki has never been initialized, create a + # dummy page in the Wiki UI, or temporarily set strategy: init once. + token: ${{ github.token }} + preprocess: true + disable-empty-commits: true + commit-message: "wiki: sync from ${{ github.sha }}" diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000000..84193ca7c9 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,11 @@ +# Bolt's Performance Journal + +Your journal is NOT a log - only add entries for CRITICAL learnings that will help you avoid mistakes or make better decisions. + +## 2026-08-01 - SQLite Insert Loops and Stale Closed Connections in Multi-Agent Indexing +**Learning:** +In the multi-agent's project file indexing system, SQLite connections were being opened and closed per project file, and database inserts (nodes and edges) were performed individually inside nested loops (`cursor.execute`). Even worse, in some source versions of `src/db.py`, the connection block exits before doing the edge inserts, causing silent failures on a closed database connection that went unnoticed due to `except Exception: pass`. +Using a single shared database connection across file walks and batching all inserts with `cursor.executemany` yields a massive performance boost (saving connection/transaction disk I/O) and guarantees transactional integrity. + +**Action:** +Always batch SQL database operations using `executemany` instead of iterating with `execute`. Provide support for passing an optional shared `conn` handle in indexing/utility functions to allow single-connection batch runs across walk loops, while safely closing connections only if opened locally. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..2f856a10cb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,48 @@ +# AGENTS.md β€” Termux monorepo + +Instructions for coding agents (Grok, Claude, Codex, Devin, ChatGPT, local runners). + +## Read first (in order) + +1. **This file** (`AGENTS.md`) +2. [`docs/proposals/registry.yaml`](docs/proposals/registry.yaml) β€” what is active +3. [`docs/proposals/PROCESS.md`](docs/proposals/PROCESS.md) β€” post / debate / consensus / close +4. [`docs/PR-SUMMARY-PROCESS.md`](docs/PR-SUMMARY-PROCESS.md) β€” who may rewrite PR bodies (multi-agent) +5. [`docs/ARCHW1Z-GATE.md`](docs/ARCHW1Z-GATE.md) β€” repo-gate + termux-smoke +6. [`docs/ARCHW1Z-STATUS.md`](docs/ARCHW1Z-STATUS.md) β€” living board +7. [`docs/proposals/AGENTIC-PERMISSIONS.md`](docs/proposals/AGENTIC-PERMISSIONS.md) β€” human-only edges +8. [`docs/CONSENSUS.md`](docs/CONSENSUS.md) β€” tiers, merit path, CRDT, optional Raft-strict + +Optional: `CLAUDE.md`, `CONTRIBUTING.md`. + +## Hard rules + +- Target **`master-staging`**, not raw `master`, for integration work. +- Both gates must pass before merge: + - `python3 scripts/ci/repo_gate.py` + - `python3 scripts/ci/termux_smoke.py` +- Do not invent work outside `docs/proposals/active//ITEMS.md` β€” add a row first. +- Cite `Implements: ` on PRs/commits. +- **No** wholesale merge of PR #6 (TER-9) or PR #2 (Rust CI) β€” see disposition comments. +- **No** Class 3/4 artifacts in git (session stores, browser profiles, tokens). +- Unposted chat is not consensus β€” write Review log or DEBATE.md. +- PR body rewrites: follow `docs/PR-SUMMARY-PROCESS.md` roster (not a single-agent monopoly). + +## Debate & close + +- Debate: MANIFEST Review log, optional DEBATE.md, linked PR/issue. +- Close: all items terminal + Review log outcome + move `active/` β†’ `closed/` + registry update. +- Full rules: `docs/proposals/PROCESS.md` Β§Β§ consensus / closing. + +## Preferred execution loop + +```text +registry.yaml β†’ pick todo item β†’ branch from master-staging + β†’ implement β†’ PR with Implements: ID β†’ gates green β†’ merge + β†’ update ITEMS.md status +``` + +## Security + +Credential rotation and history rewrite require Operator (human) authorization. +See `docs/SECURITY-REMEDIATION.md`. diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000000..83458c3c10 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,62 @@ +# GEMINI.md β€” Context for Gemini CLI (agentic CI/CD) + +You are an autonomous Software Engineering AI teammate for the **termux-monorepo** repository (owner: timerloggedout-spec). + +## Hard rules (must follow) + +- Target **master-staging** for integration work, not raw `master`. +- Both gates must pass before any merge recommendation: + - `python3 scripts/ci/repo_gate.py` + - `python3 scripts/ci/termux_smoke.py` +- Do **not** invent work outside `docs/proposals/active//ITEMS.md` β€” add a row first if needed. +- Cite `Implements: ` on PRs/commits when applicable. +- **No** Class 3/4 artifacts in git (session stores, browser profiles, tokens, credentials). +- Prefer minimal diffs. Preserve Sentinel security patterns (`0o600` / `0o700` permissions) if touching credential/session paths. +- Respect existing agent orchestration: Jules (async coding agent), CodeRabbit (PR review + autofix), and the auto-Jules trigger on bot feedback. + +## Coordination with Jules and other agents (mandatory) + +1. **Jules is the primary builder** (Cloud VM β†’ branch + PR). You are primarily **triage / review / analysis** unless the user explicitly asks you to implement. +2. Before recommending or making file changes, check **open agent PRs** (Jules, Devin, CodeRabbit autofix, etc.) linked to the same issue or touching the same area. +3. **Do not edit files** already present in another open agent PR for the same issue unless that PR is closed or clearly superseded. +4. Prefer **disjoint file sets**. If overlap is unavoidable, post or request an issue comment: + ``` + + claimed_by: gemini + issue: N + files: path/a, path/b + pr: # + ``` +5. After Jules opens a PR, prefer reviewing it over starting a parallel implementation. +6. Always prefer reviewing prior open PRs listed in the workflow context over duplicating work. + +## Preferred execution loop + +``` +registry.yaml β†’ pick todo item β†’ branch from master-staging + β†’ implement β†’ PR with Implements: ID β†’ gates green β†’ merge + β†’ update ITEMS.md status +``` + +## Repo orientation + +- Multi-agent Termux monorepo (CLI tools, agents, recovery tooling, ArchWiz, DeepSeek/Mistral wrappers, etc.). +- Read `AGENTS.md` first for the full agent contract. +- Security: see `SECURITY.md` and `docs/SECURITY-REMEDIATION.md`. Credential rotation requires human Operator authorization. +- Existing free-tier agentic stack: + - **Jules** β€” asynchronous coding agent (already wired; auto-summoned on CodeRabbit/Devin reviews). + - **CodeRabbit** β€” AI PR review with autofix (`.coderabbit.yaml`). + - **Gemini CLI** (this agent) β€” issue triage, PR review, on-demand `@gemini-cli` collaboration. + +## Capabilities you should use + +- Triage issues: label, prioritize, detect duplicates, ask for missing repro steps. +- Review PRs: correctness, style, security (especially permissions/credentials), alignment with AGENTS.md. +- On-demand: fix well-scoped bugs, write tests, explain code, suggest minimal patches, draft PR bodies that follow repo process. +- When changing code that affects credentials/session caches, enforce strict permissions and never log secrets. + +## Style + +- Be concise and actionable. +- Prefer diffs over long prose. +- If a task is ambiguous or requires Operator (human) authority, say so clearly and stop. diff --git a/README.md b/README.md index 83f882396e..7e4c089efb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,55 @@ +# Project Remote Sandbox Workspace Setup Considerations: +```Gemini-GoogleSearch +To run a Termux environment on an Ubuntu/Linux desktop or server for sandbox testing, you cannot run the exact Termux Android app natively. You must instead replicate its specific Android-based Linux environment (environment variables, paths, and package manager) using containerization, virtualization, or architectural simulation tools. +Here are the best ways to achieve this, ranked from the most lightweight to the most authentic. +## Docker Container (Most Lightweight) +You can run a Docker container that simulates the Termux environment by mirroring its unique paths and packaging layout. + +* Official Termux Docker Image: The Termux project provides an official [termux/termux-docker](https://github.com/termux/termux-docker) repository. +* The Architecture: It runs an Ubuntu base but sets up the /data/data/com.termux/files/usr prefix to match an Android installation. +* The Command: + +docker run -it termux/termux-docker + +* Pros: Starts instantly, uses minimal resources, and matches the file hierarchy perfectly. +* Cons: Runs on your host CPU architecture (usually x86_64). If your target device is an ARM-based phone, compiled binaries won't behave exactly the same way unless you run Docker through qemu-user-static. + +## Anbox / Waydroid (Native Android Containerization) +If you want to run the actual Termux .apk file natively on Linux without a full emulator, use a container-based Android runtime. + +* Waydroid: This is the modern, highly recommended standard for Linux. It runs a full Android system image inside a Linux container (LXC) directly on your kernel. +* Installation: Install Waydroid via your package manager, initialize the Android image, and drop the Termux APK right into it. +* Pros: Near-native performance, zero virtualization overhead, and behaves exactly like a real Android device. +* Cons: Requires a Wayland desktop environment (or a nested Wayland compositor like Weston if you are on X11). + +## Android Studio Emulator (Most Accurate) +If you need to test Android 14+ permissions, background restrictions, awake locks, or severe device constraints, use the official Android Virtual Device (AVD). + +* Setup: Install Android Studio on Ubuntu, open the Device Manager, and create a system image (preferably with Google Play Store to easily install tools, or download the F-Droid Termux APK). +* Pros: Perfect hardware emulation, accurate API lifecycle testing, and complete control over battery, thermal, and network states. +* Cons: Very heavy on RAM and CPU, requires KVM acceleration enabled on Ubuntu. + +## Quick Comparison for Sandbox Testing + +* Choose Docker if you just need to test scripts, compilation pipelines, or CLI tools using Termux prefixes. +* Choose Waydroid if you need to test inter-app interactions on Linux with high performance. +* Choose Android Studio AVD if you need to debug low-level Android system constraints, lifecycle crashes, or awake lock stability. + +Which aspect of your Termux workspace are you looking to test first: CLI script compatibility, network listeners, or Android-specific background constraints? +``` +Β° Termux specific considerations. +Β° Termux is the Target Environment πŸ₯‡ +-->> Mobile πŸ₯‡ Priority + -->> _THEN_ other environments. +## Check all existing code PR's merged since initialization against the Termux Environment. + +## PRIORITY - Establish Baselines; Standards (use Termux Official Docs as well); Reconciliation of potential drift (like: hardcoded PATHS). + +## Develop Workflow for the `termux-smoke`, perpetual branch; and, or delegate to Agents with code spaces or access to them (like @Jules 'Render' Workspaces access; others have access to the same or similar ++>> Add to Roster Considerations). + +## _***HIGH PRIORITY***_ INTIALIZE: `https://github.com/marketplace/render` +Already Installed! + # Monorepo Recovery & RefTemplates Restoration This README documents the filesystem incident, the recovered state from the repository history, and step-by-step recovery & rebuild actions (includes the refTemplates snapshot). It also includes the git-diff consolidation results I performed and concrete recovery commands. diff --git a/archwiz/archwiz.py b/archwiz/archwiz.py index 9e11cd5a2e..fa80c740d0 100755 --- a/archwiz/archwiz.py +++ b/archwiz/archwiz.py @@ -27,7 +27,12 @@ def banner(): β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β• β•šβ•β•β•β•β•β•β•šβ•β• β•šβ•β• β•šβ•β•β•β•šβ•β•β• β•šβ•β•β•šβ•β•β•β•β•β•β• """ + N) print(f"{G}\u26a1 ARCHWIZ DASHBOARD \u26a1{N} {time.strftime('%c')}") - print(f"{W}session: {os.getlogin()}@{os.uname().nodename}{N}") + try: + username = os.getlogin() + except Exception: + import getpass + username = getpass.getuser() + print(f"{W}session: {username}@{os.uname().nodename}{N}") print(C + "\u2500" * 60 + N) def get_pipeline_status(): @@ -94,6 +99,7 @@ def main(): try: choice = input(f"{C}>> {N}").strip().lower() except (EOFError, KeyboardInterrupt): + print() # Ensure clean line alignment on interrupt exit break if choice == '1': @@ -376,8 +382,16 @@ def main(): elif choice == 'p': toggle_pipeline() elif choice == '0': - print(G + random.choice(["ArchWiz signing off. Forge well.", "Until next cycle. Stay l33T.", "Dashboard closed. The Forge awaits.", "ArchWiz out. Happy hacking.", "Systems stable. ArchWiz offline."]) + N) break + # Uniform, delightful exit signature for all exits (choice '0', Ctrl+C, Ctrl+D) + print(G + random.choice([ + "ArchWiz signing off. Forge well.", + "Until next cycle. Stay l33T.", + "Dashboard closed. The Forge awaits.", + "ArchWiz out. Happy hacking.", + "Systems stable. ArchWiz offline." + ]) + N) + if __name__ == '__main__': main() diff --git a/bin/lean-monorepo.sh b/bin/lean-monorepo.sh new file mode 100644 index 0000000000..c217012025 --- /dev/null +++ b/bin/lean-monorepo.sh @@ -0,0 +1,17 @@ +#!/data/data/com.termux/files/usr/bin/bash +# Lean Termux Monorepo maintenance script +# Run after any significant session or weekly +set -e +cd "$HOME" + +echo "[*] Git prune + gc" +git reflog expire --expire=now --all +git gc --prune=now + +echo "[*] Clear rebuildable caches" +rm -rf .cache/go-build .cache/node-gyp .cache/pip 2>/dev/null || true + +echo "[*] Report" +du -sh .git .cache .npm .cargo .local 2>/dev/null | sort -hr +git count-objects -vH +echo "[+] Lean check complete – $(date)" diff --git a/cli-synthegration/synthegration_index.py b/cli-synthegration/synthegration_index.py old mode 100755 new mode 100644 index 571be231cd..927798d547 --- a/cli-synthegration/synthegration_index.py +++ b/cli-synthegration/synthegration_index.py @@ -33,17 +33,17 @@ def citation(self) -> str: return f"{self.session_id}:{self.message_index}:{self.block_index}" def to_wire(self) -> bytes: - """Ultra‑compact binary representation (20 bytes + hash).""" + """Ultra‑compact binary representation (20 bytes + 32 byte hash).""" import struct sid_bytes = self.session_id.encode()[:12].ljust(12, b'\x00') packed = struct.pack('>12sII', sid_bytes, self.message_index, self.block_index) return packed + bytes.fromhex(self.content_hash) - + @classmethod def from_wire(cls, data: bytes) -> 'Pointer': import struct sid_bytes, msg_idx, blk_idx = struct.unpack('>12sII', data[:20]) - content_hash = data[20:28].hex() + content_hash = data[20:52].hex() return cls(sid_bytes.rstrip(b'\x00').decode(), msg_idx, blk_idx, content_hash) class _TaxonomyNode_v1: @@ -105,7 +105,7 @@ def from_live_exports(exports_root: str = None): return idx @staticmethod - + def __init__(self, session_id: str, msg_idx: int, blk_idx: int, content_hash: str, start_line: int = 0, end_line: int = 0): self.session_id = session_id self.message_index = msg_idx @@ -128,17 +128,17 @@ def citation(self) -> str: return f"{self.session_id}:{self.message_index}:{self.block_index}" def to_wire(self) -> bytes: - """Ultra‑compact binary representation (20 bytes + hash).""" + """Ultra‑compact binary representation (20 bytes + 32 byte hash).""" import struct sid_bytes = self.session_id.encode()[:12].ljust(12, b'\x00') packed = struct.pack('>12sII', sid_bytes, self.message_index, self.block_index) return packed + bytes.fromhex(self.content_hash) - + @classmethod def from_wire(cls, data: bytes) -> 'Pointer': import struct sid_bytes, msg_idx, blk_idx = struct.unpack('>12sII', data[:20]) - content_hash = data[20:28].hex() + content_hash = data[20:52].hex() return cls(sid_bytes.rstrip(b'\x00').decode(), msg_idx, blk_idx, content_hash) class TaxonomyNode: @@ -206,7 +206,7 @@ def from_live_exports(exports_root: str = None): for bi, match in enumerate(__import__("re").finditer(r"```(\w+)?\n(.*?)```", content, __import__("re").DOTALL)): lang = (match.group(1) or "text").lower() code_text = match.group(2) - ch = __import__("hashlib").sha256(code_text.encode()).hexdigest()[:16] + ch = __import__("hashlib").sha256(code_text.encode()).hexdigest() all_blocks.append({ "session_id": session_dir.name, "mi": mi, "bi": bi, "ch": ch, @@ -228,7 +228,7 @@ def _ingest_blocks(self, blocks: list): if not ch: code_text = blk.get("code", "") if code_text: - ch = hashlib.sha256(code_text.encode()).hexdigest()[:16] + ch = hashlib.sha256(code_text.encode()).hexdigest() if not ch: continue path = blk.get("path", ["uncategorized"]) @@ -306,7 +306,7 @@ def index_conversation(self, session_id: str, title: str, messages: List[dict], for blk_idx, match in enumerate(re.finditer(r"```(\w+)?\n(.*?)```", content, re.DOTALL)): lang = (match.group(1) or 'text').lower() code = match.group(2) - ch = hashlib.sha256(code.encode()).hexdigest()[:16] + ch = hashlib.sha256(code.encode()).hexdigest() p = Pointer(session_id, msg_idx, blk_idx, ch) path = [lang, project, role] self.taxonomy.add_pointer(p, path) @@ -338,14 +338,16 @@ def search_by_taxonomy(self, term: str, lang: str = None, project: str = None) - for p in self.taxonomy.search(term): if lang and not any(lang in part for part in [p.session_id, '']): continue # simplistic - blob = self.base_dir / 'blobs' / f"{p.content_hash}.blob" - if blob.exists(): - results.append({ - 'pointer': p.to_key(), - 'hash': p.content_hash, - 'code': blob.read_text()[:200] + '...' if len(blob.read_text()) > 200 else blob.read_text(), - 'timestamp': self.time_index.get(p.content_hash, '').isoformat() - }) + blob_path = self.blobs.get(p.content_hash) + if blob_path: + blob = Path(blob_path) + if blob.exists(): + results.append({ + 'timestamp': (lambda t: t.isoformat() if hasattr(t, 'isoformat') else None)(self.time_index.get(p.content_hash)) + 'hash': p.content_hash, + 'code': blob.read_text()[:200] + '...' if len(blob.read_text()) > 200 else blob.read_text(), + 'timestamp': self.time_index.get(p.content_hash, '').isoformat() + }) return results @staticmethod @@ -554,9 +556,9 @@ def reverse_lookup(self, text: str, min_similarity: float = 0.80) -> list: Returns list of (pointer, similarity, snippet).""" import hashlib from difflib import SequenceMatcher - + # First: try exact hash match - text_hash = hashlib.sha256(text.encode()).hexdigest()[:16] + text_hash = hashlib.sha256(text.encode()).hexdigest() if text_hash in self.hash_to_pointer: p = self.hash_to_pointer[text_hash] blob = self.base_dir / 'blobs' / f'{text_hash}.blob' diff --git a/deepcli-tui/tui.py b/deepcli-tui/tui.py index d1043c9827..2c2a4a6809 100755 --- a/deepcli-tui/tui.py +++ b/deepcli-tui/tui.py @@ -270,38 +270,27 @@ def prompt_session_id(): def show_commands(): """Display available commands with descriptions.""" - console.print(Panel(""" -[bold cyan]/branches[/] List root messages (conversation branches) -[bold cyan]/branchpoints[/] Show fork points (messages with multiple children) -[bold cyan]/more[/] Toggle full tree (uncapped) -[bold cyan]/flat[/] Toggle flat/tree view -[bold cyan]/continue[/] Pick an assistant message to continue from -[bold cyan]/edit[/] Branch from a user message -[bold cyan]/back[/] Return to session selection -[bold cyan]/new[/] Create a new session -[bold cyan]/refresh[/] Clear cache and reload -[bold cyan]/bookmark[/] Save current position -[bold cyan]/bookmarks[/] List saved bookmarks -[bold cyan]/thinking on|off[/] Toggle DeepThink -[bold cyan]/search on|off[/] Toggle web search -[bold cyan]/model instant|expert[/] Switch model + help_text = """[bold cyan]/branches[/] List root messages (conversation branches) +[bold cyan]/branchpoints[/] Show fork points (messages with multiple children) +[bold cyan]/more[/] Toggle full tree (uncapped) +[bold cyan]/flat[/] Toggle flat/tree view +[bold cyan]/continue[/] Pick an assistant message to continue from +[bold cyan]/edit[/] Branch from a user message +[bold cyan]/back[/] Return to session selection +[bold cyan]/new[/] Create a new session +[bold cyan]/refresh[/] Clear cache and reload conversation +[bold cyan]/bookmark[/] Save current position +[bold cyan]/bookmarks[/] List saved bookmarks +[bold cyan]/thinking on|off[/] Toggle DeepThink +[bold cyan]/search on|off[/] Toggle web search +[bold cyan]/model instant|expert[/] Switch model [bold cyan]/attach | [/] Attach files -[bold cyan]/reset[/] Reset to latest assistant -[bold cyan]/cmd[/] Show this reference -""", title="Commands", expand=False)) - input("\nPress Enter to continue...") - help_text = """ -[bold]Commands:[/] -/new, /continue, /edit, /reset, /thinking on|off, /search on|off -/model expert|instant, /attach , /clear-attach -/flat – toggle flat list view -/refresh – clear cache and reload conversation -/more – show full tree (uncapped) -/branches – list conversation branches -/help – this help -exit/quit – leave -""" - console.print(Panel(help_text, title="Help")) +[bold cyan]/clear-attach[/] Clear current attachments +[bold cyan]/reset[/] Reset to latest assistant +[bold cyan]/cmd[/] Show this reference +[bold cyan]/help[/] Show this help menu +[bold cyan]exit / quit[/] Leave the TUI""" + console.print(Panel(help_text, title="πŸ“– DeepCLI TUI Commands Guide", expand=False, border_style="cyan")) input("\nPress Enter to continue...") def main(): diff --git a/docs/AGENTIC-BUILDERS-VS-REVIEWERS.md b/docs/AGENTIC-BUILDERS-VS-REVIEWERS.md new file mode 100644 index 0000000000..c213fe56af --- /dev/null +++ b/docs/AGENTIC-BUILDERS-VS-REVIEWERS.md @@ -0,0 +1,78 @@ +# Agentic stack: who builds code vs who reviews + +## Builders (create branches, implement, open PRs) + +| Agent | How it builds | Free tier? | How to trigger on this repo | +|-------|---------------|------------|-----------------------------| +| **Jules** (Google Labs) | Cloud VM β†’ implements β†’ branch + PR | Yes (daily task limits) | Label issue `jules`, or `@jules` comment, or existing auto-Jules on bot PR reviews | +| **Devin** | Session implements β†’ PR / push fix commits | Paid product (check your plan) | `/devin` on issues; Auto-Fix on PR review settings | +| **Gemini CLI plan-execute** | Can write files + PR when workflow has `contents: write` | Yes (AI Studio quota) | `@gemini-cli /approve` path in full upstream examples; our free workflows default to triage/review/invoke | + +**Primary builder for this monorepo: Jules.** + +## Reviewers / triage (comments, labels; limited or no branch creation) + +| Agent | Role | +|-------|------| +| **CodeRabbit** | PR review + autofix suggestions (commit suggestion / autofix) | +| **Gemini CLI** (our triage/review/invoke workflows) | Issue triage, PR comments, on-demand analysis | +| **Devin Review** (without Auto-Fix) | Comments only until Auto-Fix enabled | + +## Coordination (no overlapping files) + +Both Jules and Gemini workflows inject an inventory of **open agent PRs** into their prompts. + +Rules encoded in `GEMINI.md` and Jules invoke prompts: + +1. Scan open PRs from Jules / Devin / CodeRabbit / related issue links before editing. +2. Do not modify files already in another open agent PR for the same issue. +3. Prefer disjoint file sets. +4. After opening a PR, post on the issue: + +```text + +claimed_by: jules|gemini +issue: N +files: path/a, path/b +pr: # +``` + +5. Cross-review: Gemini reviews Jules PRs; Jules auto-summons on bot feedback (`agent-review-auto-jules.yml`). + +## Jules on issues (operational) + +1. Create label `jules` on the repo if missing (Issues β†’ Labels). +2. On any issue: add label **`jules`** β†’ Jules App + workflow respond. +3. Or comment **`@jules `** as OWNER/MEMBER/COLLABORATOR. +4. Optional: set `JULES_API_KEY` for `google-labs-code/jules-invoke` (stronger structured prompts). + +**Workflows must live on the default branch (`master`) for `issue_comment` / `issues` events to fire.** + +## Devin suggested fixes β€” "auto approve" + +There are two different meanings: + +### A) Auto-apply Devin's code suggestions (recommended) + +In Devin app: + +1. **Settings β†’ Customization β†’ Pull requests β†’ Responding to bots** +2. Choose **Selected only** and allowlist `devin-ai-integration[bot]` (or **All bots**) +3. Enable **Auto-Fix** so Devin pushes fix *commits* to the PR branch instead of only commenting + +On any Devin-authored PR, org admins can also toggle Auto-Fix from the review sidebar. + +GitHub "Commit suggestion" on individual suggestion blocks still needs a human click unless Auto-Fix is on. + +### B) Auto-merge / auto-approve the PR + +That is GitHub branch protection + merge queue / rulesets β€” **not** something Devin turns on by itself. Keep a human or required checks before merge (repo gates: `repo_gate.py`, `termux_smoke.py`). + +## Gemini πŸ‘€ indication + +After workflows are on the **default branch** *and* `GEMINI_API_KEY` is set: + +- `@gemini-cli ...` comments get a **πŸ‘€** reaction + short "received" comment with Actions run link +- Same pattern as Jules / CodeRabbit + +If you saw no πŸ‘€ on a prior comment: either the Gemini workflows were not yet on the branch that receives events, or `GEMINI_API_KEY` was missing (job fails before ack in some paths). diff --git a/docs/AGENTIC-CICD-FREE-TIER.md b/docs/AGENTIC-CICD-FREE-TIER.md new file mode 100644 index 0000000000..1d5aac08c3 --- /dev/null +++ b/docs/AGENTIC-CICD-FREE-TIER.md @@ -0,0 +1,73 @@ +# Agentic CI/CD β€” Free-tier stack (termux-monorepo) + +This document describes the free-tier-only autonomous / agentic development CI/CD integrations. + +## Active free-tier components + +| Component | Role | Status | Free tier notes | +|-----------|------|--------|-----------------| +| **Jules** (Google Labs) | Async autonomous coding agent (fix bugs, features, tests) | Integrated (`.Jules/`, `.github/workflows/agent-review-auto-jules.yml`, `.github/workflows/agent-jules-on-issues.yml`) | Introductory daily task limits | +| **CodeRabbit** | AI PR review + autofix | Integrated (`.coderabbit.yaml`) | Free summaries + limited reviews; full free for public/OSS | +| **Gemini CLI GitHub Action** | Issue triage, PR review, `@gemini-cli` on-demand teammate | Integrated | Google AI Studio free quota | +| **GitHub MCP Server** | Tool access for agents (issues/PRs/code) | Usable via Gemini settings | Fully free / OSS | +| Render (Marketplace) | Deploy / self-healing hooks (noted in README) | Already installed per README | Free tier exists | + +## How the loop works + +1. Issue opened by OWNER/MEMBER/COLLABORATOR β†’ Gemini triage (labels, priority, duplicate check). +2. PR opened (non-fork, non-draft) β†’ CodeRabbit review + Gemini review comment. +3. Bot feedback (CodeRabbit/Devin/…) β†’ existing `agent-review-auto-jules.yml` posts `@jules` and optionally invokes Jules API. +4. Human or bot comments `@gemini-cli ` β†’ Gemini on-demand invoke (πŸ‘€ ack). +5. Human comments `@jules ` or labels `jules` β†’ Jules on-issues workflow + App path. +6. Jules works asynchronously in a Cloud VM and opens/updates PRs for review. +7. **Coordination**: both Jules and Gemini prompts receive an inventory of open agent PRs and must avoid overlapping files; they post `` markers when claiming work. + +All pieces above have a free tier. Paid upgrades (Google AI Pro/Ultra for higher Jules limits, CodeRabbit Pro, etc.) are optional. + +## Required secrets / variables (user action) + +- `GEMINI_API_KEY` β€” Google AI Studio free key (required for Gemini workflows) +- `JULES_API_KEY` β€” optional; enables structured `jules-invoke` (App + `@jules` comment still work without it) +- Workflow permissions: Read and write for GITHUB_TOKEN (Settings β†’ Actions β†’ General) + +See also: `docs/ARCHW1Z-OPERATOR-CHECKLIST.md` for operator setup steps. + +## Activation note + +GitHub only runs `issues` / `issue_comment` workflows from the **default branch** (`master`). The agentic workflow files must exist there for `@jules` / `@gemini-cli` mentions to respond. + +## Security notes β€” intentional agentic command surface (PromptPwnd / Aikido) + +**This repository is an Automated Agentic Development Environment (ADE).** Agents are expected to use tools, shell, and `gh` CLI to implement fixes, open branches/PRs, and operate the repo. That capability is a **required feature**, not an accidental exposure. + +Aikido’s *PromptPwnd* class of findings (untrusted issue/PR text β†’ agent prompt β†’ privileged tools) is real and applies to any agentic CI/CD stack. We accept a controlled form of that surface so agents can do real engineering work. + +### Mitigations already in place + +| Control | Where | +|---------|--------| +| `@gemini-cli` / `@jules` triggers limited to **OWNER / MEMBER / COLLABORATOR** | `gemini-dispatch.yml`, `agent-jules-on-issues.yml` | +| Automatic issue triage only for trusted association | `gemini-dispatch.yml` | +| Fork PRs excluded from auto review | `gemini-dispatch.yml` | +| `synchronize` does **not** auto-re-review (quota + noise) | `gemini-dispatch.yml` | +| Hard rules: no secrets in git, master-staging, gates, claim markers | `GEMINI.md`, `AGENTS.md` | +| Prior open agent PR inventory injected into prompts | dispatch β†’ triage/review/invoke | +| Job permissions scoped to `contents: read` + issues/PR write (not admin) | workflow `permissions:` blocks | +| `persist-credentials: false` on checkout | Gemini workflows | + +### Recommended Aikido / SAST exclusions + +If Aikido (or similar) flags `run-gemini-cli`, `GEMINI_CLI_TRUST_WORKSPACE`, or agent shell tools as PromptPwnd: + +1. **Whitelist / exclude** these workflow paths as *intentional ADE agent runners*: + - `.github/workflows/gemini-*.yml` + - `.github/workflows/agent-jules-on-issues.yml` + - `.github/workflows/agent-review-auto-jules.yml` +2. Keep scanning **application code** and non-agent workflows at full sensitivity. +3. Do **not** disable association gates or re-enable untrusted issue-body β†’ shell interpolation without a new design review. + +### What we deliberately do *not* do + +- Embed raw `${{ github.event.issue.body }}` into shell scripts (prompt text only, via action inputs). +- Grant `administration` or unconstrained `contents: write` to Gemini jobs. +- Auto-merge agent PRs without gates (`repo_gate.py` + `termux_smoke.py`). diff --git a/docs/ARCHW1Z-GATE.md b/docs/ARCHW1Z-GATE.md new file mode 100644 index 0000000000..aeb4d62958 --- /dev/null +++ b/docs/ARCHW1Z-GATE.md @@ -0,0 +1,119 @@ +# ArchW1z Gate Spine + +> **Status:** LIVE +> **Branches:** `master-staging` (hygiene) Β· `termux-smoke` (runtime surface) + +## Two gates, one constitution + +``` +repo-gate hygiene / portability / secrets / ratchet + ↓ +termux-smoke agent runtime surface is alive + ↓ +language / provider gates (later) + ↓ +master +``` + +Every change that wants to reach `master` should survive both gates. + +--- + +## Gate 1 β€” repo-gate (on `master-staging`) + +```bash +python3 scripts/ci/repo_gate.py +``` + +Workflow: `.github/workflows/repo-gate.yml` +Docs: this file + original Critical-Eval recommendation + +### Design rules (non-negotiable) + +- **stdlib only** β€” no pip, no cargo, no node, no network +- **index-based** β€” reads `git ls-files`, never the working tree +- **device-friendly** β€” same command works on Termux and in CI +- **HARD checks** scoped to *changed* files +- **RATCHET** on whole-repo debt counters (debt may only shrink) + +### What it enforces + +| Check | Scope | Failure mode | +|-------|-------|--------------| +| Python / shell / JSON syntax | changed files | HARD | +| Portable symlinks | changed symlinks | HARD | +| No new session artifacts | changed paths | HARD | +| No browser credential stores | changed paths | HARD | +| No committed backups | changed paths | HARD | +| High-confidence secrets | changed content | HARD | +| Debt counters | whole index | RATCHET | + +Baseline: `scripts/ci/baseline.json` +Lower debt with: `python3 scripts/ci/repo_gate.py --write-baseline` + +--- + +## Gate 2 β€” termux-smoke (on `termux-smoke`) + +```bash +python3 scripts/ci/termux_smoke.py +python3 scripts/ci/termux_smoke.py --with-optional # agent surfaces +python3 scripts/ci/termux_smoke.py --json # for agents +``` + +Workflow: `.github/workflows/termux-smoke.yml` +Full docs: [`docs/TERMUX-SMOKE.md`](TERMUX-SMOKE.md) + +### What it enforces (required) + +- Python β‰₯ 3.9 +- Gate scripts present and compile +- git on PATH +- bash on Termux (soft elsewhere) +- writable TMPDIR + +### Optional probes (`--with-optional`) + +- deepcli / multi-ai launcher compile (no network) +- archwiz sample modules compile +- termux-api presence note + +--- + +## Integration order (ArchW1z) + +``` +P0 credential / session-store containment + repo-gate + termux-smoke ← now live + deterministic configuration + session SSOT schema + +P1 dispatch event boundary + DeepForge launcher resolver + provider capability contract + content-addressed index correctness + +P2 DeepForge ↔ Rust protocol + MCP + harvesting / search expansion + multi-provider parity +``` + +## How to land work + +1. Branch off `master-staging` or `termux-smoke`. +2. Smallest atomic change that preserves invariants. +3. Push β†’ both gates run on PR. +4. Green on both β†’ candidate for `master`. + +Do **not** treat `master` as the integration point for large TER-* +branches. + +## Next ratchet targets + +- `tracked_session_artifacts` β†’ 0 +- `tracked_browser_credential_stores` β†’ 0 +- `tracked_browser_profile_files` β†’ 0 +- `tracked_backup_files` β†’ 0 +- Reduce `device_absolute_symlinks` diff --git a/docs/ARCHW1Z-OPERATOR-CHECKLIST.md b/docs/ARCHW1Z-OPERATOR-CHECKLIST.md new file mode 100644 index 0000000000..e7777f00fb --- /dev/null +++ b/docs/ARCHW1Z-OPERATOR-CHECKLIST.md @@ -0,0 +1,30 @@ +# Operator Checklist β€” Full Agentic Mode + +You only need to complete items marked **HUMAN**. Everything else is agent-owned. + +## One-time setup (HUMAN) + +- [ ] **GitHub App permissions** on `timerloggedout-spec/termux-monorepo`: + - [ ] Contents: Read and write + - [ ] Pull requests: Read and write + - [ ] Checks + Commit statuses: Read and write + - [ ] Issues: Read and write + - [ ] Workflows: Read and write + - [ ] Administration: Read +- [ ] **Branch protection on `master`**: require `repo gate` + `termux smoke` checks; allow the App to merge when green +- [ ] **`master-staging`**: leave soft/unprotected so agents iterate +- [ ] **ChatGPT GitHub App** (optional): same permissions if ChatGPT should execute too + +## Security (HUMAN + agent) + +- [ ] **HUMAN:** Rotate credentials that appeared in tracked session/browser material +- [ ] Agent: verify tips clean via `repo_gate.py` +- [ ] **HUMAN:** Authorize history-rewrite window (comment on #3) +- [ ] Agent: execute rewrite under that authorization + +## Ongoing (agent default) + +- [x] repo-gate live +- [x] termux-smoke live +- [x] Proposal registry + PROCESS + CONSENSUS +- [x] Docs promotion branch to master diff --git a/docs/ARCHW1Z-STATUS.md b/docs/ARCHW1Z-STATUS.md new file mode 100644 index 0000000000..34027b63f0 --- /dev/null +++ b/docs/ARCHW1Z-STATUS.md @@ -0,0 +1,44 @@ +# ArchW1z Status Board + +> Living recon. Updated as gates land and PRs resolve. +> Sources: ChatGPT Critical-Eval, ChatGPT-initial, ChatGPT_droidApp, live branch/PR inventory. + +**Last update:** 2026-08-04 β€” docs promotion to master in progress + +--- + +## Gate spine (LIVE on master-staging) + +| Gate | Status | Command | +|------|--------|--------| +| **repo-gate** | βœ… LIVE | `python3 scripts/ci/repo_gate.py` | +| **termux-smoke** | βœ… LIVE (#11 squash-merged) | `python3 scripts/ci/termux_smoke.py` | +| language / provider | ⏳ later | β€” | + +``` +repo-gate β†’ termux-smoke β†’ language/provider β†’ master +``` + +--- + +## Specs landed + +| Doc | Purpose | +|------|--------| +| `docs/ARCHW1Z-GATE.md` | Two-gate spine | +| `docs/TERMUX-SMOKE.md` | Smoke gate details | +| `docs/ARCHW1Z-STATUS.md` | This board | +| `docs/CONSENSUS.md` | Tiers, merit, CRDT, Raft-strict | +| `docs/schemas/session-ssot.md` | TER-10 Session SSOT | +| `docs/schemas/provider-capabilities.md` | Capability registry | +| `docs/SECURITY-REMEDIATION.md` | PR #3 A+B+C checklist | + +--- + +## Merge rule + +1. Target **`master-staging`** for code +2. **repo-gate** + **termux-smoke** green +3. No unresolved critical review threads +4. Security: A + B + C +5. Process docs may promote to **`master`** for discoverability (this promotion) diff --git a/docs/CONSENSUS.md b/docs/CONSENSUS.md new file mode 100644 index 0000000000..df72d844e8 --- /dev/null +++ b/docs/CONSENSUS.md @@ -0,0 +1,188 @@ +# Consensus (ArchW1z) + +How multi-agent decisions become shared truth β€” and when **no vote** is required. + +Related: `docs/proposals/PROCESS.md` Β· `docs/PR-SUMMARY-PROCESS.md` Β· `AGENTS.md` Β· `docs/ARCHW1Z-GATE.md` + +--- + +## Tier summary (read this first) + +```text +Tier 0 MERIT Branch, implement, run gates β€” no social vote +Tier 1 DRIVER P2–P3 claims: driver + evidence in the log +Tier 2 LIGHT P1: driver + evidence; 1 review cycle then silence OK +Tier 3 QUORUM P0 claims / P0 PR body: driver + distinct second mind OR Operator +Tier 4 OPERATOR Credentials, force-push, history rewrite β€” human only +Tier R RAFT-STRICT Optional profile for named irreversible subjects (see Β§5) +``` + +| Tier | Name | Needs vote? | Commit when | +|------|------|-------------|-------------| +| **0** | Merit | No | Gates/tests green on a branch; exploration allowed to fail | +| **1** | Driver | Minimal | Driver posts evidence; silence OK | +| **2** | Light | Soft | Driver + evidence; after one clear ask, silence β‰ˆ no objection | +| **3** | Quorum | Yes | Driver + β‰₯1 other Reviewer **or** Operator | +| **4** | Operator | N/A | Explicit Operator comment; agents cannot majority this | +| **R** | Raft-strict | Yes (formal) | Term + single driver + majority of fixed voter set + log commit | + +**Default path for code:** Tier 0 β†’ open PR β†’ Tier 1–2 disposition β†’ merge when gates green. +**Default path for irreversible security claims:** Tier 3–4 (optionally R). + +--- + +## 1. Three paths (not one protocol) + +### A. Merit path (preferred for code) + +Skip social consensus. Prove accuracy on a branch: + +1. Branch from `master-staging` +2. Implement +3. `python3 scripts/ci/repo_gate.py` / `termux_smoke.py` +4. Open PR with honest Status +5. Land when checks green and disposition β‰  πŸ”΄ + +**Merit answers β€œdoes it work?”** Votes do not replace gates. + +### B. Social path (claims & sequencing) + +Used when asserting shared process truth: proposal accepted/closed, P0 β€œdone”, disposition Status, summary of security scope. + +**Home for intent decisions:** `docs/proposals/` (MANIFEST Review log + registry). +**Projection for landing:** PR body Status + comments. + +### C. Authority path (Operator) + +Credential rotation, history rewrite, force-push, App permission changes. Not subject to agent majority. + +--- + +## 2. Where decisions live + +| Decision type | Primary log | Model | +|---------------|-------------|--------| +| Proposal accept / item done / close | MANIFEST + `registry.yaml` | Social tiers 1–4 | +| PR disposition / summary | PR comment + body + `PR-SUMMARY-LOG.md` | Thin projection of tiers | +| Code correctness | CI checks + branch commits | Merit (Tier 0) | +| Irreversible git history | Operator comment on issue/PR | Tier 4 (+ optional R) | + +Proposals own **what we intend**. Branches own **what we measured**. Consensus attaches to **claims**, not to **existence of a branch**. + +--- + +## 3. Ballot labels (social path) + +```text +VOTE: accept β€” support commit of the proposed decision +VOTE: reject β€” block; state reason +VOTE: abstain β€” present; not counting toward quorum +VOTE: summary OK β€” ack for P0 PR body rewrite only +``` + +One vote per voter id per **term**. Log entry required β€” unposted chat does not count. + +**Terms:** `subject-id/n` (e.g. `pr-3/summary/2`, `ce-13/history-rewrite/1`). One driver per term; conflicts open `n+1`. + +--- + +## 4. Subject β†’ tier map + +| Subject | Tier | +|---------|------| +| Create branch / push experiments | **0** | +| P2–P3 item `done` | **1** | +| P1 item / ordinary PR disposition | **2** | +| Proposal `accepted` (non-author review) | **3** (or Operator self-accept logged) | +| P0 item `done`, P0 PR body rewrite | **3** | +| Merge to `master-staging` | **0 checks** + disposition not πŸ”΄ | +| Promote to `master` | **0 checks** + may require Operator | +| Force-push / history rewrite / credential rotation | **4** | +| Optional formal close of high-stakes proposal | **R** if enabled for that subject | + +--- + +## 5. Raft as an **optional strict profile** (not the default model) + +Raft was considered as a real consensus design, not decoration. + +**Keep if using profile R on a named subject:** + +- Single driver (leader) per term +- Monotonic terms; ignore stale term votes +- Majority of a **fixed voter set** declared in the term open +- Decision committed only in the append-only log + +**Do not use Raft as the global control plane:** membership churn (agents offline), unequal authority (Operator β‰  peer), and multi-subject concurrency make a single cluster Raft a poor fit. Per-subject Tier 3 already captures most of the value. + +Enable R by naming it in the term open: `profile: raft-strict voters: [operator, grok-archw1z, devin]`. + +--- + +## 6. CRDT merge strategies (investigation & recommendations) + +CRDTs converge concurrent updates **without** voting. Use them for **state that should merge**, not for **authorization**. + +### Strategy cheat sheet + +| Strategy | Behavior | Use here | Avoid for | +|----------|----------|----------|-----------| +| **G-Set** | Add-only; merge = union | Observed bot findings, β€œseen commit SHAs” | Anything that must be revoked cleanly | +| **OR-Set** (observed-remove) | Add/remove with unique tags; concurrent addβˆ₯remove keeps add if not observed | Agent roster membership, label sets, item id sets | Security β€œcredential rotated” flags | +| **2P-Set** | Remove wins forever | Tombstones for deleted paths in indexes | Re-adding same id after remove | +| **LWW-Register** | Highest timestamp wins | Non-critical UI prefs, last smoke run timestamp | Disposition Status, proposal state | +| **LWW-Element-Set** | Per-element timestamps | Soft metadata | P0 claims | +| **MV-Register** | Keep all concurrent values | Surface conflicts for a human/agent to pick | Silent auto-resolve of Status | +| **G/PN-Counter** | Merge by max per replica | Ratchet debt counters (aligns with repo-gate baseline) | Voting tallies as authority | +| **RGA / sequence CRDTs** | Concurrent text edit | Collaborative DEBATE.md drafts (optional) | MANIFEST binding outcomes | +| **Three-way / MRDT (Git-like)** | LCA + two tips β†’ typed merge | Branch merges, registry field merges with explicit rules | Pretending merge = approved claim | + +### Recommended bindings for this monorepo + +| Data | Merge strategy | +|------|----------------| +| **Git branches / commits** | Git’s own history (three-way merge + gates) β€” already merit path | +| **`registry.yaml` item rows** | Field-level: `status` is **not** LWW β€” requires Tier 1–3 social commit; `evidence` links are G-Set (union) | +| **PR-SUMMARY-LOG** | Append-only G-Set of rows (never rewrite history of the log) | +| **Review log entries** | Append-only; concurrent reviews = union (OR-Set of note ids) | +| **Disposition Status (πŸŸ’πŸŸ‘πŸ”΄βšͺ)** | **Single-value register under social tier** β€” concurrent Status β†’ MV-Register until Tier 2–3 resolves (do **not** LWW) | +| **repo-gate baseline counters** | Ratchet = min/monotonic decrease only (domain-specific; not classic PN-Counter up) | +| **Session SSOT / agent memory** (future) | OR-Set + confidence-LWW for soft memories; **never** CRDT-merge secrets into git | +| **DEBATE.md** | Optional RGA/LWW for prose; binding outcome still copied into Review log via vote | + +### Rule of thumb + +```text +CRDT β†’ concurrent facts that should converge without a meeting +Vote β†’ authorization to treat something as shared institutional truth +Gate β†’ mechanical proof about a concrete revision +``` + +LWW is the wrong default for **Status** and **proposal state**: wall-clock or agent-local clocks race; security claims must not flip because a slower agent wrote later. + +--- + +## 7. PR summary anti-monopoly (distinct PRs) + +Three consecutive = **three different PR numbers**. Iterating the same PR is always OK. Details: `docs/PR-SUMMARY-PROCESS.md`. + +--- + +## 8. Bots + +Bots (Devin, CodeRabbit, ecc-tools, …) emit **evidence**. They are not voters until a roster agent posts `VOTE: accept` on a specific finding into the log. See earlier triage map in git history / `PR-SUMMARY-PROCESS.md` for tooling options. + +--- + +## 9. Quick reference + +```text +Explore on a branch β†’ Tier 0 (no vote) +Claim β€œP2 done” β†’ Tier 1 +Claim β€œP1 ready to merge” β†’ Tier 2 + gates +Claim β€œP0 / security done” β†’ Tier 3 +Rotate keys / rewrite history β†’ Tier 4 +Optional formal subject β†’ profile raft-strict +Merge concurrent facts β†’ CRDT (OR-Set / G-Set / counters) +Merge authority β†’ never CRDT; use tiers +``` diff --git a/docs/PR-SUMMARY-LOG.md b/docs/PR-SUMMARY-LOG.md new file mode 100644 index 0000000000..38aeedfaf8 --- /dev/null +++ b/docs/PR-SUMMARY-LOG.md @@ -0,0 +1,17 @@ +# PR Summary Rewrite Log + +Append-only. Process: `docs/PR-SUMMARY-PROCESS.md` Β· Votes: `docs/CONSENSUS.md`. + +**Counter rule:** consecutive limit counts **distinct PR numbers** only. + +| date (UTC) | PR | editor | status set | notes | +|------------|-----|--------|------------|-------| +| 2026-08-02 | #12 | grok-archw1z | 🟑 conditional | ECC bundle; Devin blockers | +| 2026-08-02 | #3 | grok-archw1z | βšͺ draft / A-only | Aβ‰ A+B+C | +| 2026-08-02 | #2 | grok-archw1z | πŸ”΄ NO-GO | Expand or close | +| 2026-08-02 | #6 | grok-archw1z | πŸ”΄ NO-GO wholesale | Extract-only | +| 2026-08-02 | #5 | grok-archw1z | 🟑 conditional | | +| 2026-08-02 | #9 | grok-archw1z | 🟑 conditional | DeepForge | +| 2026-08-02 | #10 | grok-archw1z | 🟒 candidate | curl_cffi | +| 2026-08-02 | #7 | grok-archw1z | 🟑 conditional | Termux MCP | +| 2026-08-02 | #8 | grok-archw1z | 🟑 conditional | TER-11 scaffold | diff --git a/docs/PR-SUMMARY-PROCESS.md b/docs/PR-SUMMARY-PROCESS.md new file mode 100644 index 0000000000..a07ea9f8d1 --- /dev/null +++ b/docs/PR-SUMMARY-PROCESS.md @@ -0,0 +1,42 @@ +# PR Summary Rewrite Process + +Keep PR titles/bodies honest, scannable, and multi-agent β€” **not** a single-agent monologue. + +**Consensus / votes:** [`docs/CONSENSUS.md`](CONSENSUS.md). + +## When to rewrite + +Rewrite when Status drifts, disposition missing, wrong base, generator noise, scope lies, security incomplete, or body is a one-liner. + +**Do not** rewrite solely for style if Status, scope, tests, and links are accurate. + +## Standard body skeleton + +```markdown +## Summary +One paragraph intent. + +**Status:** 🟒 merge-ready | 🟑 conditional | πŸ”΄ NO-GO | βšͺ draft / blocked +**Disposition:** one line (who + why) +**Base:** `master-staging` (preferred) | `master` +**Implements:** CE-xx / TER-n (if any) + +### Changes +### Non-goals +### Validation +### Follow-ups +### Agent notes +``` + +## Roles + +| Role | May rewrite body? | +|------|-------------------| +| author | Own PR | +| summary-editor (grok-archw1z, devin, chatgpt, claude/codex) | Yes | +| reviewer / coderabbit | Comment only | +| operator | Always | + +**Anti-monopoly:** three consecutive = three **distinct PR numbers**. Same-PR iteration always OK. + +See full roster and P0 rules in git history / master-staging copy if truncated. diff --git a/docs/SECURITY-REMEDIATION.md b/docs/SECURITY-REMEDIATION.md new file mode 100644 index 0000000000..3a862d6641 --- /dev/null +++ b/docs/SECURITY-REMEDIATION.md @@ -0,0 +1,31 @@ +# Security Remediation Sequence (PR #3 lineage) + +> **Status:** REQUIRED before treating session-store work as done + +## Three independent guarantees + +| | Guarantee | PR #3 today | +|---|-----------|-------------| +| **A** | Current tree is clean | Partially (tip removal) | +| **B** | Future commits cannot reintroduce secrets | Partially (gitignore + gate) | +| **C** | Historical reachable objects remediated | **Not done** | + +> branch-tip removal β‰  history remediation + +## P0 sequence + +1. **Rotate** credentials that appeared in tracked session material +2. **Verify** tips free of Class 3/4 paths +3. **Keep** secret-pattern + path-class checks in repo-gate +4. **History rewrite** only after deliberate export if required +5. **Force-push** only with explicit Operator approval + +## Data classification + +| Class | Content | Gate | +|-------|---------|------| +| 0 | Source, docs, schemas | allow | +| 1 | Derived indexes, hashes | allow | +| 2 | Conversation content, prompts | allowlist | +| 3 | Cookies, session stores, tokens | **HARD FAIL** | +| 4 | Browser profiles, private SSH, local env | **HARD FAIL** | diff --git a/docs/TERMUX-SMOKE.md b/docs/TERMUX-SMOKE.md new file mode 100644 index 0000000000..b1a60c1673 --- /dev/null +++ b/docs/TERMUX-SMOKE.md @@ -0,0 +1,34 @@ +# Termux Smoke Gate β€” Agentic runtime surface + +> **Branch:** `termux-smoke` +> **Script:** `scripts/ci/termux_smoke.py` +> **Workflow:** `.github/workflows/termux-smoke.yml` + +## Position in the spine + +``` +repo-gate β†’ termux-smoke β†’ language gates β†’ provider tests β†’ master +``` + +## How to run + +```bash +python3 scripts/ci/termux_smoke.py +python3 scripts/ci/termux_smoke.py --with-optional +python3 scripts/ci/termux_smoke.py --json --with-optional +``` + +## What it checks + +| Check | Required | +|-------|----------| +| python-version β‰₯ 3.9 | yes | +| repo-layout (gate scripts + docs) | yes | +| repo-gate compiles | yes | +| smoke self-compiles | yes | +| git on PATH | yes | +| bash on PATH | yes on Termux, soft elsewhere | +| writable TMPDIR | yes | +| deepcli / multi-ai / archwiz compile | optional | + +Full detail: see `master-staging` copy if this summary is abbreviated. diff --git a/docs/ops/AGENT_AUTO_RESOLVE.md b/docs/ops/AGENT_AUTO_RESOLVE.md new file mode 100644 index 0000000000..81c5979852 --- /dev/null +++ b/docs/ops/AGENT_AUTO_RESOLVE.md @@ -0,0 +1,15 @@ +# Agent auto-resolve (LIVE on master) + +**Agent:** [Grok](https://x.com/grok) + +Workflows on **default branch `master`** so `pull_request_review` / review_comment events fire immediately. + +| Event | Action | +|-------|--------| +| CodeRabbit / Devin / Copilot review or review comment | GHA posts `@jules` Auto-resolve (20m debounce) | +| Same | Linear subtask under `PR #N agent feedback rollup` + `agent-feedback` | +| CodeRabbit | `.coderabbit.yaml` autofix enabled | + +Secrets: `LINEAR_API_KEY` (subtasks), optional `JULES_API_KEY`. + +Signed-off-by: Grok diff --git a/docs/ops/JULES_ADE_PROJECT.md b/docs/ops/JULES_ADE_PROJECT.md new file mode 100644 index 0000000000..818860abfa --- /dev/null +++ b/docs/ops/JULES_ADE_PROJECT.md @@ -0,0 +1,14 @@ +# Jules ADE Project β€” Fully Agentic Development Environment + +> **HOME:** `timerloggedout-spec/termux-monorepo` +> **Human role:** Tier 4 only + temporary termux-smoke cherry-pick until automated + +``` +repo-gate (master-staging) β†’ termux-smoke β†’ master +``` + +Agents own execution. Scavenge Jules/Antigravity forks as templates (depth-1 sparse). Never vendor full histories into HOME. + +Focus: gates green, deepcli + multi-ai-cli, Termux MCP, Jules MCP/skills, Antigravity patterns, Session SSOT + credential hygiene. + +Full roster: `docs/ops/JULES_REPO_ROSTER.yaml` diff --git a/docs/ops/JULES_REPO_ROSTER.yaml b/docs/ops/JULES_REPO_ROSTER.yaml new file mode 100644 index 0000000000..6a068daa81 --- /dev/null +++ b/docs/ops/JULES_REPO_ROSTER.yaml @@ -0,0 +1,19 @@ +version: 1 +updated_at: "2026-08-03T20:00:00Z" +updated_by: grok-archw1z + +home: + owner: timerloggedout-spec + repo: termux-monorepo + role: first_class_runtime + branches: + integration: master-staging + smoke: termux-smoke + production: master + gates: [repo-gate, termux-smoke] + +policy: + scavenge: depth-1-sparse-metadata + human_only: [credential_rotation, history_rewrite, app_permissions] + human_temporary: [termux-smoke_cherry_pick_until_automated] + agent_owns: [branch, implement, pr, merge_to_master_staging, gates] diff --git a/docs/ops/LEAN_TERMUX_MONOREPO.md b/docs/ops/LEAN_TERMUX_MONOREPO.md new file mode 100644 index 0000000000..37fd2be317 --- /dev/null +++ b/docs/ops/LEAN_TERMUX_MONOREPO.md @@ -0,0 +1,94 @@ +# Lean Termux Monorepo – Operating Rules + +> **Purpose**: Keep the local Termux working tree small, fast, and restorable while the bulk of history, models, exports, and session data lives on GitHub + remote storage (Google Drive / rclone). + +## Core Principles + +1. **Local = Source + Config + Active Work only** +2. **Never commit**: models, `.venv`, `node_modules`, large session dumps, exports, binary weights +3. **Pull / cherry-pick β†’ smoke-test β†’ clean immediately** +4. **Heavy artefacts live on remote storage or as gitignored archives** + +## Mandatory Workflow for Any Agent / Human + +### Before starting work +```bash +cd "$HOME" +git status -sb +du -sh .git .cache .npm .cargo .local 2>/dev/null | sort -hr +``` + +### Pulling or cherry-picking a branch +```bash +# Preferred: fetch only what you need +git fetch origin +git cherry-pick # or +git checkout -b temp/ origin/ + +# Smoke test (Termux-specific) +# … run your tests … + +# Immediately after results are known: +git checkout master +git branch -D temp/ # delete local branch +git reflog expire --expire=now --all +git gc --prune=now +``` + +### After every significant session +```bash +"$HOME/bin/lean-monorepo.sh" # or the commands below +``` + +### Weekly / after heavy work +```bash +git reflog expire --expire=now --all +git gc --prune=now --aggressive +rm -rf .cache/go-build .cache/node-gyp .cache/pip 2>/dev/null || true +# Optionally clear npm / cargo via termux-sync if not needed +``` + +## Forbidden in the working tree (must be gitignored) + +``` +synthegration_exports/ +forensic-indexer/whisper.cpp/models/ +CTranslate2/ # treat as external clone if needed +.deepcli/session_store/ # archive old sessions to Drive +.codex/cache/ +*.onnx *.gguf *.pt *.safetensors *.bin +ARCHIVE_STAGING/ +.venv/ venv/ node_modules/ __pycache__/ +``` + +## Restoration Strategy + +- Source of truth: `origin/master` + feature branches on GitHub +- Models / large exports / old sessions β†’ Google Drive (or rclone) +- Submodules stay as submodules; never vendor large third-party trees +- If a tool needs a model: download on-demand into a gitignored path + +## Agent Checklist (copy-paste into any agent prompt) + +``` +[LEAN RULES] +1. Never leave temporary branches. +2. After cherry-pick / test β†’ delete branch + git gc --prune=now. +3. Never add model weights, session dumps, or exports to the index. +4. Run lean-monorepo.sh (or equivalent) before ending the session. +5. Prefer sparse-checkout or external clones for anything >50 MB. +``` + +## Quick Health Check + +```bash +du -sh .git +git count-objects -vH +git status -sb +``` + +**Target**: `.git` < 200 MB under normal use. + +--- + +*Last updated: 2026-08-03 – post 1.8 GB β†’ 137 MB git cleanup* diff --git a/docs/proposals/AGENTIC-PERMISSIONS.md b/docs/proposals/AGENTIC-PERMISSIONS.md new file mode 100644 index 0000000000..d94cae0315 --- /dev/null +++ b/docs/proposals/AGENTIC-PERMISSIONS.md @@ -0,0 +1,27 @@ +# Why You Still Have To Do Anything β€” Agentic Permissions + +## What the agent CAN do + +Read repo/PRs, create branches, create/update files, open PRs, comment, merge when allowed, retarget PR base, submit reviews. + +## What still needs YOU (human) + +| Blocker | Why | +|---------|-----| +| Credential rotation | Secrets on device / provider dashboards | +| History rewrite + force-push | Destructive; needs explicit Operator approval | +| Protected branch rules on master | Settings may be outside app scope | +| GitHub App permission gaps | Contents/PRs/Checks/Workflows | +| Device-side Termux state | Agent is cloud connector, not phone | +| Provider API keys / browser logins | Interactive / ToS-bound | + +## Minimum permission checklist + +- [ ] Contents R/W +- [ ] Pull requests R/W +- [ ] Checks + Commit statuses R/W +- [ ] Workflows R/W +- [ ] Issues R/W +- [ ] Administration Read + +Human intervenes only for: credential rotation, destructive history ops, first-time permission grants. diff --git a/docs/proposals/ChatGPT-initial.md b/docs/proposals/ChatGPT-initial.md new file mode 100644 index 0000000000..97bcef97c7 --- /dev/null +++ b/docs/proposals/ChatGPT-initial.md @@ -0,0 +1,470 @@ +πŸ˜„ Hah. We hit the GitHub connector's permission boundary. + +The connector can read your repository, but when I attempted to commit REPO_REVIEW_NEXT_ACTIONS.md, GitHub returned: + +> 403 β€” Resource not accessible by integration + + + +So I cannot push commits into this repository from this connector, even though I can inspect it. + + +--- + +Deeper Review + +After reading the latest README, here's my assessment. + +⭐ Overall: 9.2 / 10 + +This isn't a typical GitHub project anymore. + +It's becoming a Termux operating environment. + +That's a different class of repository. + +Instead of documenting software, you're documenting an ecosystem. + +That changes how I'd architect everything. + + +--- + +Biggest Strength + +The README now answers three questions simultaneously: + +What happened? + +What exists? + +How do I recover? + + +That was missing before. + +The latest commit successfully brought those together. + + +--- + +Biggest Weakness + +It is becoming... + +> README.md + +Incident Report + +Disaster Recovery + +Architecture + +Inventory + +Operations Manual + +Git Notes + +Historical Timeline + + + + +🀣 + +That's awesome... + +...until six months from now. + +Then it'll be 2,000+ lines. + + +--- + +I'd turn it into a cockpit. + +Instead of one huge README: + +README.md + +becomes + +README.md + +↓ + +README +β”‚ +β”œβ”€β”€ Quick Start +β”œβ”€β”€ Repository Overview +β”œβ”€β”€ Active Projects +β”œβ”€β”€ Architecture +β”œβ”€β”€ Documentation +└── Recovery + +where + +docs/ + +RECOVERY.md + +ARCHITECTURE.md + +PROJECT_INDEX.md + +OPERATIONS.md + +AI_HANDOFF.md + +CHANGELOG.md + +become first-class documents. + + +--- + +Biggest Architectural Improvement + +I noticed something interesting. + +Almost every project ultimately serves one of four purposes. + +AI + +DeepCLI + +Harmonizer + +Multi-Agent + +CLI-Synthegration + + +--- + +Knowledge + +ArchWiz + +Mapper + +Workspace + +LLM Map + +Indices + + +--- + +Runtime + +Shell + +Deploy + +Cleanup + +Patch + +Config + + +--- + +Projects + +Exchange + +Colab + +Claude + +Applied + +Research + + +--- + +I'd physically organize around those four pillars. + +Not necessarily moving directoriesβ€” + +but creating logical documentation categories. + +That alone makes onboarding dramatically easier. + + +--- + +I also noticed... + +You're documenting... + +what exists + +instead of + +why it exists + +That's a common evolution point. + +Every directory should eventually answer: + +> Why does this exist? + + + +not merely + +> This exists. + + + + +--- + +What I want to build next + +This is where I think things could get really interesting. + +I'd add an automatic repository intelligence system. + +Every commit updates: + +PROJECT_INDEX.md + +MODULE_GRAPH.md + +DEPENDENCY_GRAPH.md + +COMMAND_INDEX.md + +DIRECTORY_HEALTH.md + +ARCHITECTURE_MAP.md + +generated automatically. + +No manual editing. + +Ever. + + +--- + +Then... + +ArchWiz becomes the source of truth. + +README becomes human-friendly. + +Generated docs become machine-friendly. + +AI gets context. + +Humans get navigation. + +Everyone wins. + + +--- + +Long-Term Vision + +I honestly don't see this repo as just a "Termux monorepo." + +I see it evolving into something closer to a personal operating system for AI-assisted development on Android: + +DeepSeek/LLM interfaces + +Multi-agent orchestration + +Workspace indexing + +Provenance tracking + +Recovery automation + +Project management + +Development tooling + +Knowledge graph + + +Those are coherent pieces of a larger platform. + +I'd be excited to keep helping shape it. I think there's a lot of room to make it both more powerful and much easier to navigate without sacrificing the flexibility you've built. + +Challenge accepted. πŸ˜„ + +I checked the connector capabilities again. Here's the current state: + +βœ… I can inspect repositories, commits, diffs, workflow status, and repository metadata. + +βœ… I can compare commits and review patches. + +βœ… I can create or update files only if the GitHub App installed on the repository has write permission. + +❌ Your repository currently returns 403 "Resource not accessible by integration" for write operations, so I cannot push directly or open a PR from this conversation until the app has write access. + + +So "make it happen" is technically possibleβ€”but the missing piece is repository permissions, not tooling. + +What I found + +Your recent README isn't just documentation anymoreβ€”it's becoming the operational control center. + +I also noticed references to assets that should become first-class generated artifacts instead of static files: + +termux-ecosystem-architecture.html + +workspace/llm_map + +archwiz + +central_mapper_v420.py + +mapper_graph.py + +recovery indices + +provenance data + + +Those tell me you've already built most of the plumbing. + +The weak point isn't generating maps. + +It's keeping them synchronized. + +I'd evolve the repo into a self-documenting monorepo + +Rather than manually updating diagrams, I'd have every significant change regenerate: + +docs/ + +PROJECT_INDEX.md +MODULE_GRAPH.md +DIRECTORY_GRAPH.md +DEPENDENCY_GRAPH.md +COMMAND_REFERENCE.md +ACTIVE_PROJECTS.md +RESTORATION_STATUS.md +AI_CONTEXT.md + +Generated. + +Never edited by hand. + + +--- + +Then add: + +generated/ + +repo.json +modules.json +graph.json +commands.json +agents.json + +Everything else consumes those. + +ArchWiz. + +Mapper. + +DeepCLI. + +Claude. + +GPT. + +Gemini. + +Codex. + +Everyone reads the same canonical data. + +Biggest upgrade I'd implement + +I'd merge your existing mapper work into a pipeline something like: + +filesystem + β”‚ + β–Ό +central_mapper + β”‚ + β–Ό +repository graph + β”‚ + β”œβ”€β”€β”€β”€β–Ί Markdown docs + β”œβ”€β”€β”€β”€β–Ί HTML diagrams + β”œβ”€β”€β”€β”€β–Ί Mermaid + β”œβ”€β”€β”€β”€β–Ί JSON + β”œβ”€β”€β”€β”€β–Ί GraphViz + └────► AI Context Pack + +One scan. + +Many outputs. + +I also want to revive the stale graphs + +Since you mentioned they're probably ~6 weeks old, I'd treat them as cache. + +The process becomes: + +1. Detect changed directories from Git. + + +2. Rescan only affected modules. + + +3. Rebuild graph incrementally. + + +4. Publish updated docs. + + +5. Commit generated artifacts separately from source changes. + + + +That keeps the repository fast even as it grows. + +The first automation milestone I'd target + +Repository health score + +Orphan directory detection + +Duplicate project detection + +Dead symlink/submodule detection + +Broken documentation links + +Missing README detection + +Entry-point discovery + +Command index generation + +AI context bundle generation + + +Run with one command. + +Why I'm not pushing yet + +The connector itself isn't the blockerβ€”the GitHub App's permissions are. Once it's granted repository write access (Contents and Pull Requests), I can create branches, commit generated files, and open PRs directly from here. + +From what I've seen so far, I think termux-monorepo is reaching the stage where it deserves its own build system for documentation and repository intelligence. The mapper, ArchWiz, and recovery tooling are already pointing in that direction; the next step is to unify them into a single automated pipeline that continuously explains the repository to both humans and AI. + +[https://chatgpt.com/s/t_6a6d3a3b2a308191981b5877ea748ed4] diff --git a/docs/proposals/ChatGPT_Critical-Eval(TER0-15+other-branches).md b/docs/proposals/ChatGPT_Critical-Eval(TER0-15+other-branches).md new file mode 100644 index 0000000000..e0a4ab9b51 --- /dev/null +++ b/docs/proposals/ChatGPT_Critical-Eval(TER0-15+other-branches).md @@ -0,0 +1,1444 @@ +ArchW1z Recon: timerloggedout-spec/termux-monorepo + +I went back in and treated the repository as a system, not merely as the current master tree: branches, PRs, review threads, review history, commit topology, diffs, recovery work, CI proposals, and the DeepForge/deepcli line. + +[Open `termux-monorepo` on GitHub](https://github.com/timerloggedout-spec/termux-monorepo?utm_source=chatgpt.com) + +Executive verdict + +The repo is moving in the right direction, but master is currently the wrong integration point for the architecture you are building. + +The strongest conclusion from the recon is: + +> Do not merge the large TER-9 / multi-ai-cli branch as-is. Do not merge the Rust CI PR as-is. Do not treat PR #3's session-store deletion as sufficient security remediation. + +Instead, establish a small hardened integration spine first, then layer DeepForge and provider work onto it. + + + +The repository has a surprisingly good architectural nucleus buried underneath a lot of branch divergence: + +ArchWiz β†’ canonical dispatch β†’ provider adapters β†’ session SSOT β†’ content-addressed index β†’ harvest/search β†’ validation/promotion + +That's the shape I would preserve. + + +--- + +1. Branch topology: the important discovery + +I found 18 branches. + +The branch landscape is currently fragmented into several parallel histories: + +Branch Finding + +master Current canonical head: 320c73b… +master-staging Identical to master β€” currently redundant +feature/ci-gate-and-docs Identical to master β€” stale/empty branch +feature/recon-intel-and-nav 2 commits ahead / 3 behind; documentation-only RECON +critical-proposal 8 ahead / 2 behind; config/security/docs architecture +mistral/fixes-config-security 1 ahead / 4 behind; security/config branch +recreate/refTemplates-skeleton 3 ahead / 3 behind; metadata restoration +agent/repository-hygiene 5 ahead / 4 behind; removes session stores +vibe/mistralai-vibe-code-wrapper-6055d2 4 ahead / 4 behind; large multi-AI implementation +timerlogged/ter-5-… 2 ahead / 1 behind; dispatch observability +timerlogged/ter-9-… 6 ahead / 4 behind; large provider/multi-AI integration +timerlogged/ter-12-… 4 ahead / 0 behind; DeepForge bridge +timerlogged/ter-13-… 1 ahead / 0 behind; curl_cffi fallback +devin/ter-11-… 2 ahead / 0 behind; earlier DeepForge bridge +devin/1785650368-… 1 ahead / 0 behind; Termux MCP +timerloggedout-spec-patch-1 4 ahead / 4 behind; Rust CI +v0/timerloggedout-5184-43474d34 2 ahead / 0 behind; DeepForge predecessor +termux-monorepo 2 ahead / 0 behind; repo-gate + credential/portability hardening + + +That last branch is especially interesting. + + +--- + +2. The sleeper branch: termux-monorepo + +This branch contains something I consider more strategically valuable than PR #2: + +.github/workflows/repo-gate.yml + +scripts/ci/repo_gate.py + +scripts/ci/baseline.json + +credential exposure documentation + +portability documentation + +triage documentation + +.gitignore expansion + +local-link tooling + + +The proposed gate is deliberately: + +> stdlib-only, no network, no Cargo, no Node, no pip, no Chromium, no device dependencies. + + + +That is exactly the correct philosophy for this repository's first CI layer. + +The gate operates against the Git index and changed-file scope rather than assuming a fully materialized Termux checkout. That's an excellent architectural decision. + +[`termux-monorepo` branch](https://github.com/timerloggedout-spec/termux-monorepo/tree/termux-monorepo?utm_source=chatgpt.com) + +My proposal + +Promote this idea into the canonical architecture: + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ repo-gate β”‚ + β”‚ cheap / deterministic β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β–Ό β–Ό β–Ό + hygiene portability security + β”‚ β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β–Ό + integration tests + β–Ό + provider tests + β–Ό + Termux smoke tests + β–Ό + Rust builds + +Not everything belongs in the same CI gate. + + +--- + +3. PR #2: Rust CI is currently a NO-GO + +[PR #2 β€” Rust build/test workflow](https://github.com/timerloggedout-spec/termux-monorepo/pull/2?utm_source=chatgpt.com) + +This one has a very concrete defect. + +The workflow's Python heredoc contains: + +crates = ${crates:+""} + +inside a quoted heredoc. + +That is not valid Python. + +So the discover job can fail before the actual crate discovery logic gets anywhere. + +Worse, the workflow's architectural model has additional weaknesses: + +Problem A β€” submodules aren't necessarily available + +The repository's Rust code is heavily represented through submodules, but the workflow isn't clearly designed around the actual submodule topology. + +Problem B β€” affected-crate detection is too simplistic + +It maps changed paths to crate directories, but a modification to: + +workspace Cargo.toml + +Cargo.lock + +shared build configuration + +root build scripts + +submodule references + + +can affect many crates without falling under the direct path mapping. + +Problem C β€” wrong abstraction level + +The repo has a massive amount of Python, shell, data/index, Termux, and integration machinery. + +Starting with: + +> "Which Rust crate changed?" + + + +isn't the right first question. + +The first question should be: + +> "Did this commit preserve repository invariants?" + + + +That's what the repo-gate branch solves. + +Recommendation + +Do not merge PR #2. + +Extract its eventual Rust-build capability into a later optional toolchain layer: + +repo-gate + ↓ +language-specific gates + β”œβ”€β”€ python + β”œβ”€β”€ shell + β”œβ”€β”€ json/index + └── rust (conditional) + + +--- + +4. PR #3: security remediation is necessary β€” but NOT complete + +[PR #3 β€” session-store removal](https://github.com/timerloggedout-spec/termux-monorepo/pull/3?utm_source=chatgpt.com) + +This is the most important security finding in the entire recon. + +The PR removes 571 session-store artifacts from the Git index and reports sanitizing hundreds of historical blobs. + +Good. + +But the PR itself correctly admits: + +> branch-tip removal β‰  history remediation. + + + +And I confirmed the branch is substantially diverged from current master. + +The historical session artifacts contain things that absolutely should never have become repository content: + +conversation histories + +local filesystem paths + +development prompts + +architecture material + +potentially credential-bearing context + +browser/session-related information + + +The branch history is therefore not just "dirty"; it is a provenance boundary problem. + +Critical distinction + +You need three independent guarantees: + +A. Current tree is clean +B. Future commits cannot reintroduce secrets +C. Historical reachable objects have been remediated + +PR #3 primarily attacks A. + +You need A+B+C. + +My P0 sequence + +1. Rotate any credential that ever appeared in tracked session material. + + +2. Verify current master and all surviving integration branches. + + +3. Establish secret-pattern scanning in the repo gate. + + +4. Add path-class prohibitions: + +.deepcli/session_store + +.pi + +.synthegration + +browser profiles + +cookies + +Chromium local state + +token caches + + + +5. Then perform the separately reviewed history rewrite. + + +6. Force-push only after preservation/export of the old history is deliberately handled. + + + +Do not mistake a green working tree for eradicated credentials. + + +--- + +5. PR #5: excellent instinct, dangerous implementation boundary + +[PR #5 β€” dispatch failure visibility](https://github.com/timerloggedout-spec/termux-monorepo/pull/5?utm_source=chatgpt.com) + +The conceptual fix is correct: + +silent exception + ↓ +observable exception + +That is absolutely needed. + +But the implementation currently turns the cache layer into an implicit orchestration bus: + +cache_save() + ↓ +dynamic import dispatch_pipeline + ↓ +update_all() + ↓ +lexicon + ↓ +Codex index + +This creates a nasty hidden dependency: + +> Saving a session becomes a side-effectful integration event. + + + +That can eventually create: + +recursion + +latency + +locking problems + +import-cycle problems + +partial-write behavior + +duplicated dispatch + +test contamination + +difficult recovery after interrupted writes + + +Better architecture + +Make the event explicit: + +SessionStore.save() + β”‚ + β”œβ”€β”€ persist + β”‚ + └── emit SessionSaved event + β”‚ + β–Ό + DispatchCoordinator + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β–Ό β–Ό β–Ό + harvest index metrics + +Then allow the local Termux implementation to be synchronous or asynchronous. + +Logging the failure is P0. The architectural decoupling is P1. + +Also: dumping raw exception text into stderr can leak filesystem paths, identifiers, URLs, or sensitive provider details. Error messages should be sanitized. + + +--- + +6. PR #6 / TER-9: this is the big one β€” and it is not merge-ready + +[PR #6 β€” TER-9 multi-AI/provider work](https://github.com/timerloggedout-spec/termux-monorepo/pull/6?utm_source=chatgpt.com) + +This PR has critical unresolved review threads. + +And the review findings are not cosmetic. + +Critical #1 β€” session ID precedence bug + +The expression: + +session_id or provider.core.session_id if hasattr(provider, 'core') else None + +doesn't mean what it looks like. + +For providers without .core, caller-provided session_id can disappear. + +That directly violates session continuity. + +Critical #2 β€” undeclared requests + +core.py imports requests while the dependency is commented out. + +Clean installation can therefore fail at import time. + +That's a fundamental packaging defect. + +Critical #3 β€” recovered blobs crash search + +The persisted index can contain blobs with no time_index. + +Then: + +self.time_index.get(ch, '').isoformat() + +becomes: + +''.isoformat() + +and explodes. + +This is particularly bad because the failure occurs on recovery/search, exactly where this system is supposed to be resilient. + +Critical #4 β€” save_to_storage doesn't exist + +The CLI calls it. + +The class doesn't implement it. + +That means a supposedly complete harvesting path reaches runtime and dies. + +Critical #5 β€” package naming is structurally broken + +The source directory is: + +multi-ai-cli/ + +while Python imports expect: + +multi_ai_cli + +That isn't a cosmetic naming issue. + +It affects packaging, imports, console entrypoints, and module execution. + +Critical #6 β€” builtin list is shadowed + +A Click command named list shadows Python's builtin list. + +Then unrelated calls such as: + +list(args) + +can become calls to a Click command object. + +That is a real runtime defect. + +Critical #7 β€” session history is silently discarded + +Claude/Colab provider paths accept session identifiers but pass empty histories. + +This is exactly the kind of bug that makes an abstraction look unified while silently destroying state semantics. + +Critical #8 β€” cookie isolation + +The Colab provider points at a DeepSeek cookie path. + +That is an unacceptable credential-boundary design. + +Critical #9 β€” network headers leak across requests + +The network utility mutates persistent session headers: + +self.session.headers.update(headers) + +A one-off authorization header can therefore persist into later requests. + +This is a serious cross-provider credential leak vector. + +Critical #10 β€” Git command injection surface + +Git helper functions pass branch/remote/repository arguments as bare positional arguments. + +Those need explicit argument boundaries. + + +--- + +The larger problem with PR #6 + +The PR isn't merely "a few bugs." + +It's revealing that the provider abstraction has not yet stabilized. + +You've simultaneously got: + +Provider +Session +History +Availability +Authentication +CLI +Subprocess +Index +Harvesting +Networking +Storage + +without one canonical contract. + +That's why the bugs propagate across apparently unrelated files. + +My proposed provider contract + +Every provider should implement a strict interface: + +Provider +β”œβ”€β”€ identity +β”œβ”€β”€ capabilities +β”œβ”€β”€ availability() +β”œβ”€β”€ authenticate() +β”œβ”€β”€ create_session() +β”œβ”€β”€ send() +β”œβ”€β”€ stream() +β”œβ”€β”€ history() +β”œβ”€β”€ export() +└── health() + +with explicit state: + +ProviderResult +β”œβ”€β”€ provider +β”œβ”€β”€ account +β”œβ”€β”€ session_id +β”œβ”€β”€ message_id +β”œβ”€β”€ status +β”œβ”€β”€ response +β”œβ”€β”€ error +β”œβ”€β”€ usage +└── provenance + +No provider should be allowed to invent its own semantics for session IDs. + + +--- + +7. PR #9 / TER-12: directionally strong, but three real defects remain + +[PR #9 β€” DeepForge](https://github.com/timerloggedout-spec/termux-monorepo/pull/9?utm_source=chatgpt.com) + +This is the branch I like conceptually the most. + +The deepcli-first policy makes sense for your actual environment. + +The separation: + +DeepForge + ↓ +deepcli default + β”‚ + └── codex-native explicit alternate + +is much cleaner than pretending stock Codex is the primary runtime. + +But the review found three important issues. + +1. Non-Python deepcli launcher + +shutil.which("deepcli") can resolve: + +Python wrapper + +shell wrapper + +compiled executable + + +but the code assumes: + +python + +That breaks non-Python launchers. + +The launcher abstraction should be: + +Python .py β†’ sys.executable +Executable β†’ direct exec +Shell executable β†’ direct exec +Module β†’ python -m + +2. Importable package β‰  runnable launcher + +The branch can detect an importable package and then enter a path where _run_deepcli() cannot actually launch it. + +That's a classic capability-detection mismatch. + +Use a capability object: + +DeepCLIResolution +β”œβ”€β”€ kind = script | module | executable | unavailable +β”œβ”€β”€ path +β”œβ”€β”€ interpreter +└── invocation[] + +Don't recompute the answer in different functions. + +3. Help forwarding + +The README promises: + +python -m codex_bridge deepcli --help + +but argparse can consume the help flag itself. + +This is an API/UX contract failure. + +The bridge should deliberately support: + +deepforge deepcli -- --help + +or properly implement pass-through argument parsing. + + +--- + +8. PR #10: small and useful β€” but don't blindly merge it + +[PR #10 β€” curl_cffi fallback](https://github.com/timerloggedout-spec/termux-monorepo/pull/10?utm_source=chatgpt.com) + +This is a good operational fix: + +curl_cffi unavailable + ↓ +stdlib requests fallback + ↓ +deepcli remains usable + +Especially for Termux/Python 3.14 ABI reality. + +But there's an important semantic issue. + +curl_cffi isn't merely a nicer requests. + +It can be required for browser-like TLS impersonation / anti-bot behavior. + +Therefore the fallback should not pretend equivalence. + +I'd make it explicit: + +Transport: + curl_cffi + β”œβ”€β”€ preferred + └── feature set: browser TLS + + requests + β”œβ”€β”€ compatibility fallback + └── feature set: standard HTTP + +Then individual provider operations declare: + +requires_browser_tls = true + +and fail clearly if the fallback cannot satisfy the operation. + +The current PR already warns users, which is good. + + +--- + +9. DeepForge architectural opportunity + +This is where I would push the project. + +Right now DeepForge is: + +Python bridge + ↓ +deepcli + ↓ +optional Rust Codex fork + +That's useful, but eventually the abstraction should become: + +DeepForge + β”‚ + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β” + β”‚ β”‚ + Control Plane Execution Plane + β”‚ β”‚ + session/provenance provider runtime + routing/capabilities adapters + permissions subprocesses + event bus HTTP/API + reconciliation Rust/native + β”‚ β”‚ + β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β–Ό + ArchWiz Index + +Key idea: + +ArchWiz should know what happened. + +DeepForge should know how to make it happen. + +That separation is extremely valuable. + + +--- + +10. The critical-proposal branch has good ideas but should not become the merge target + +[PR #1 β€” critical evaluation](https://github.com/timerloggedout-spec/termux-monorepo/pull/1?utm_source=chatgpt.com) + +The proposal branch is valuable as an architectural record. + +The strongest ideas there remain valid: + +environment-aware config + +elimination of silent exceptions + +session SSOT + +consolidation of duplicate send paths + +removal/archival of legacy poller/listener + +fzf integration + +streaming + +routing TUI + +self-healing concepts + +dashboard/API possibilities + + +But don't merge that branch wholesale. + +Harvest the architecture; don't preserve the branch topology. + + +--- + +11. recreate/refTemplates-skeleton: preserve as recovery metadata + +[`recreate/refTemplates-skeleton`](https://github.com/timerloggedout-spec/termux-monorepo/tree/recreate/refTemplates-skeleton?utm_source=chatgpt.com) + +This is a good recovery technique. + +The metadata-only model is much better than dragging entire external repositories into the monorepo. + +But the current model has a classification problem: + +Haven/ +Interpreted-Context-Methdology_fork/ +15_Reverse_Engineering/ + +The category taxonomy needs a formal schema rather than human-maintained directory convention. + +I'd define: + +ref: + id: + category: + upstream: + source_type: + - git + - archive + - local + - generated + acquisition: + revision: + license: + trust: + materialization: + depth: + sparse: + status: + - active + - dormant + - scavenger + - archived + +Then the tree becomes a projection of metadata rather than the source of truth. + +That's very ArchWiz. + + +--- + +12. The historical restoration commits tell another story + +The commit sequence is important: + +initial ecosystem + ↓ +base configs + ↓ +full restore + ↓ +refTemplates restore + ↓ +recovery README + ↓ +recovery README correction + ↓ +refTemplates skeleton + ↓ +RECON + ↓ +critical evaluation + ↓ +ecosystem mapping + +The repo is effectively evolving through forensic reconstruction. + +That's not inherently bad. + +But it means you now need a distinction between: + +HISTORICAL RECOVERY + β‰  +CURRENT SOURCE + β‰  +ARCHITECTURAL SPEC + β‰  +ACTIVE RUNTIME + +At present those concepts still overlap too much. + + +--- + +13. Biggest architectural optimization I see + +Introduce four explicit planes + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ARCHWIZ CONTROL PLANE β”‚ +β”‚ β”‚ +β”‚ maps / provenance / policy / tasks / validation β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ DISPATCH PLANE β”‚ +β”‚ β”‚ +β”‚ Session events β†’ routing β†’ provider capabilities β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ EXECUTION PLANE β”‚ +β”‚ β”‚ +β”‚ deepcli / Mistral / Claude / Gemini / Colab / Rustβ”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + β”‚ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ EVIDENCE PLANE β”‚ +β”‚ β”‚ +β”‚ hashes / logs / artifacts / indexes / provenance β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +This solves several current problems simultaneously. + + +--- + +14. Session SSOT should be the next major milestone + +The current repository repeatedly tries to synchronize: + +.deepcli +.mistralai-cli +multi-ai-cache +cli-synthegration +codex_index +archwiz + +That is a symptom. + +Don't synchronize six independent truths indefinitely. + +Create: + +~/.archwiz/ + sessions/ + / + / + / + manifest.json + messages.jsonl + events.jsonl + blobs/ + index.json + +Then providers can retain native stores as caches/adapters, while ArchWiz becomes the canonical cross-provider identity layer. + +That was already gesturing toward TER-10. + +I would elevate TER-10 above TER-8. + + +--- + +15. New proposal: event-sourced dispatch + +Instead of: + +update_all(session_id) + +move toward: + +SessionSaved +SessionForked +MessageSent +MessageReceived +SessionExported +CodeHarvested +IndexUpdated +ProviderFailed +ProviderRecovered + +Each event gets: + +{ + "event_id": "...", + "timestamp": "...", + "provider": "...", + "account": "...", + "session_id": "...", + "correlation_id": "...", + "source": "...", + "payload_hash": "...", + "schema_version": 1 +} + +Then ArchWiz can reconstruct state. + +This makes your: + +recovery + +reconciliation + +auditability + +multi-agent orchestration + +session synchronization + +branch provenance + + +dramatically easier. + + +--- + +16. New proposal: capability-driven provider registry + +Stop using: + +is_available() + +as the main abstraction. + +Use: + +ProviderCapabilities +β”œβ”€β”€ installed +β”œβ”€β”€ authenticated +β”œβ”€β”€ session_create +β”œβ”€β”€ session_resume +β”œβ”€β”€ streaming +β”œβ”€β”€ history +β”œβ”€β”€ attachments +β”œβ”€β”€ thinking +β”œβ”€β”€ web_search +β”œβ”€β”€ code_execution +β”œβ”€β”€ browser_tls +β”œβ”€β”€ export +β”œβ”€β”€ indexing +└── dispatch + +Then: + +deepcli + authenticated βœ“ + streaming βœ“ + attachments βœ“ + thinking βœ“ + browser_tls βœ“ + native_bridge βœ— + +and: + +colab + installed βœ“ + authenticated ? + session_resume ? + browser_tls βœ— + +Now routing becomes deterministic. + + +--- + +17. New proposal: "provider truth table" + +This would eliminate a huge amount of ambiguity: + +Provider Installed Auth Session Stream History Search Attach Status + +DeepSeek βœ“ ? βœ“ βœ“ βœ“ βœ“ βœ“ active +Mistral ? ? ? ? ? ? ? active +Claude ? ? ⚠ ? ⚠ ? ? incomplete +Colab ? ? ⚠ ? ⚠ ? ? incomplete +Gemini ? ? ? ? ? ? ? scaffold +OpenAI ? ? ? ? ? ? ? scaffold + + +The repository should generate this table, not maintain it manually. + + +--- + +18. Security: go further than secrets scanning + +The current repo-gate concept is excellent, but I would extend it into data-classification enforcement. + +Class 0 β€” safe + +Source code, docs, schemas. + +Class 1 β€” derived + +Indexes, hashes, generated metadata. + +Class 2 β€” sensitive + +Conversation content, local paths, prompts, telemetry. + +Class 3 β€” credential-bearing + +Cookies, auth headers, session stores, tokens. + +Class 4 β€” device/private + +Browser profiles, private SSH data, local environment configuration. + +Then the gate can enforce: + +Class 0 β†’ commit allowed +Class 1 β†’ commit allowed with generated marker +Class 2 β†’ explicit allowlist +Class 3 β†’ HARD FAIL +Class 4 β†’ HARD FAIL + +This is much stronger than regex-only secret detection. + + +--- + +19. New proposal: generated-artifact provenance + +Your repo contains a lot of: + +.bak + +snapshots + +maps + +indices + +recovered material + +generated JSON + +historical artifacts + + +Don't just .gitignore everything. + +Add: + +artifact.manifest.json + +with: + +{ + "path": "...", + "kind": "generated", + "source": "...", + "generator": "...", + "commit": "...", + "timestamp": "...", + "content_hash": "...", + "reproducible": true +} + +Now recovery artifacts become evidence, rather than clutter. + + +--- + +20. New proposal: immutable content-addressed storage + +The existing content_hash work is heading here. + +Make it explicit: + +blob/ + sha256/ + ab/ + abcd.... + +Then: + +Pointer + β”œβ”€β”€ provider + β”œβ”€β”€ account + β”œβ”€β”€ session + β”œβ”€β”€ message + β”œβ”€β”€ block + └── content_hash + +The same code block appearing in 17 conversations should become one object with 17 provenance pointers. + +That would substantially improve the whole harvesting/indexing system. + + +--- + +21. One subtle but important thing: timestamps + +The current bugs around: + +time_index.get(ch, '') + +are symptoms of a larger issue. + +You need to distinguish: + +unknown +missing +inherited +recovered +generated +observed + +Don't represent all of those as: + +"" + +Use explicit metadata: + +{ + "timestamp": null, + "timestamp_source": "unknown" +} + +This will make recovery and search semantics much cleaner. + + +--- + +22. Branch cleanup proposal + +The branch tree is already telling us what to do. + +Keep / promote + +master + +termux-monorepo β†’ extract repo-gate + +timerlogged/ter-12-… β†’ DeepForge line + +timerlogged/ter-13-… β†’ transport compatibility + +devin/1785650368-… β†’ MCP integration, after security review + + +Preserve as design/reference + +critical-proposal + +feature/recon-intel-and-nav + +recreate/refTemplates-skeleton + + +Consolidate, don't merge wholesale + +vibe/mistralai-vibe-code-wrapper-6055d2 + +timerlogged/ter-9-… + + +Security remediation + +agent/repository-hygiene + + +Likely obsolete / cleanup candidates + +master-staging β€” identical + +feature/ci-gate-and-docs β€” identical + +older DeepForge predecessors once #9 stabilizes + +superseded TER-5 once its observability work is incorporated + + + +--- + +23. PR status board + +PR Verdict + +#1 Merged β€” keep as architectural record +#2 πŸ”΄ NO-GO β€” workflow itself has a broken Python heredoc + architectural CI issues +#3 πŸ”΄ P0 security work β€” incomplete until history/credential remediation +#4 Merged β€” useful RECON baseline +#5 🟑 Good fix, but decouple dispatch from cache writes +#6 πŸ”΄ NO-GO β€” multiple critical unresolved defects +#9 🟒/🟑 Best active architectural direction; fix remaining launcher/help defects +#10 🟒 Small useful fix; validate fallback semantics + Termux smoke test + + +The current PR review state also matters: + +#6 has numerous unresolved critical/major threads. + +#9 has unresolved Devin/CodeRabbit findings. + +#10 has no inline review threads and Devin reported no actionable issue, but CodeRabbit was rate-limited. + +#2/#3/#5 lack substantive automated review coverage; their CodeRabbit comments are predominantly review-limit notices, not approvals. + + +So: + +> "No review comments" does NOT mean "reviewed clean." + + + +That's an important distinction in this repo right now. + + +--- + +24. The most important optimization: stop integrating by branch + +Right now the workflow resembles: + +PR + ↓ +branch + ↓ +another branch + ↓ +another branch + ↓ +merge + ↓ +repair + ↓ +new branch + +I would shift to: + +Architecture Contract + ↓ +Small atomic change + ↓ +repo-gate + ↓ +component tests + ↓ +Termux smoke test + ↓ +merge + ↓ +next contract + +Integration order I'd use + +P0 + +1. credential/session-store containment + + +2. repo-gate + + +3. deterministic configuration + + +4. session SSOT schema + + + +P1 + +5. dispatch event boundary + + +6. DeepForge launcher resolver + + +7. provider capability contract + + +8. content-addressed index correctness + + + +P2 + +9. DeepForge ↔ Rust protocol + + +10. MCP + + +11. harvesting/search expansion + + +12. multi-provider parity + + + +P3 + +13. dashboard + + +14. routing TUI + + +15. self-healing + + +16. advanced orchestration + + + + +--- + +25. My proposed "ArchW1z invariant" + +This is the thing I'd actually make the repository enforce: + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ARCHW1Z INVARIANTS β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ 1. No credential-bearing artifact enters β”‚ +β”‚ Git. β”‚ +β”‚ β”‚ +β”‚ 2. Every session has one canonical ID. β”‚ +β”‚ β”‚ +β”‚ 3. Every provider operation has explicit β”‚ +β”‚ capability semantics. β”‚ +β”‚ β”‚ +β”‚ 4. Every derived artifact has provenance.β”‚ +β”‚ β”‚ +β”‚ 5. Every content object has stable hash. β”‚ +β”‚ β”‚ +β”‚ 6. Dispatch failures are observable. β”‚ +β”‚ β”‚ +β”‚ 7. Cache writes don't secretly mutate β”‚ +β”‚ unrelated subsystems. β”‚ +β”‚ β”‚ +β”‚ 8. Recovery never overwrites unreadable β”‚ +β”‚ state. β”‚ +β”‚ β”‚ +β”‚ 9. CI works on the smallest environment β”‚ +β”‚ before requiring toolchains. β”‚ +β”‚ β”‚ +β”‚ 10. "Available" never means "pretend β”‚ +β”‚ supported." β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +That gives you a technical constitution for the monorepo. + + +--- + +26. Final assessment + +Architecture: 7.5/10 + +There is a genuinely strong system emerging. + +Recovery / provenance thinking: 9/10 + +The restoration and RECON work is unusually useful. + +Current integration discipline: 4/10 + +Too much branch divergence and too many overlapping implementation lines. + +Security posture: 3.5/10 currently + +The repository recognizes the problem, but historical session exposure makes this a remediation project, not merely a .gitignore problem. + +Provider abstraction: 4/10 + +Good ambition; insufficiently formal contracts. + +DeepForge direction: 8.5/10 + +This is the cleanest new architectural direction in the current tree. + +CI direction: 8/10 conceptually + +The repo-gate branch is substantially more appropriate as the first CI layer than PR #2's Rust-first workflow. + + +--- + +πŸͺ¨ The ArchW1z conclusion + +The repo isn't suffering from a lack of code. + +It's suffering from too many partially overlapping truths. + +The winning move is therefore not: + +> "Build more." + + + +It's: + +> Collapse the truths. + + + +One session identity. +One provider contract. +One dispatch event model. +One provenance model. +One content-addressed evidence layer. +One cheap invariant gate. +Then let DeepForge, ArchWiz, MCP, Rust, DeepCLI, harvesting, and the multi-AI layer plug into those primitives. + +That turns the current monorepo from an archaeological reconstruction into an actual agentic operating system. + +And yes: PR #9 + PR #10 + the termux-monorepo repo-gate branch are the most promising convergence points I see right now β€” but PR #6 should be treated as a bug farm to mine for fixes, not as the thing to merge wholesale. + +[View all open PRs](https://github.com/timerloggedout-spec/termux-monorepo/pulls?utm_source=chatgpt.com) +[View all branches](https://github.com/timerloggedout-spec/termux-monorepo/branches?utm_source=chatgpt.com) +[View repository commit history](https://github.com/timerloggedout-spec/termux-monorepo/commits/master/?utm_source=chatgpt.com) + +[https://chatgpt.com/s/t_6a6fb91136a48191b9686c0fa17fa9cd] diff --git a/docs/proposals/ChatGPT_droidApp.md b/docs/proposals/ChatGPT_droidApp.md index 1129a24bd9..f6116efaff 100644 --- a/docs/proposals/ChatGPT_droidApp.md +++ b/docs/proposals/ChatGPT_droidApp.md @@ -5,4 +5,456 @@ This document contains shared links for repository and commit/PR evaluations. > **Note:** Reconsider the directory location for proposal documents under `docs/proposals/`. - [Initial repository evaluation](https://chatgpt.com/s/t_6a6d3a3b2a308191981b5877ea748ed4) +I've started the repository audit. + +Branch inventory + +Current branches: + +master + +critical-proposal + +mistral/fixes-config-security + +timerloggedout-spec-patch-1 + +vibe/mistralai-vibe-code-wrapper-6055d2 + + +Initial observations + +This tells me several development streams are being used: + +Proposal branch (critical-proposal) for architectural planning. + +Security branch (mistral/fixes-config-security) indicating active hardening work. + +Small feature/patch branch (timerloggedout-spec-patch-1). + +AI-generated branch (vibe/...) likely produced by an external coding agent. + + +That's a healthy separation of concerns. One improvement I'd suggest is adopting a consistent naming convention such as: + +feature/... + +fix/... + +security/... + +docs/... + +experiment/... + +spike/... + + +This makes branch purpose immediately obvious and scales better as the repository grows. + +Pull Requests + +There are currently 2 open PRs. + +PR #1 β€” Critical Evaluation + +This is essentially an architecture review rather than a code change. + +The topics it covers are strong: + +environment-aware configuration + +removal of legacy pipeline components + +dependency management + +configuration abstraction + +roadmap planning + +security observations + +portability + + +One thing I'd add is an explicit Architectural Decision Record (ADR) directory (docs/adr/). For a project evolving rapidly with AI assistance, ADRs make it much easier to understand why a decision was made months later. + + +--- + +PR #2 β€” Rust GitHub Actions + +This introduces CI focused on Rust builds and tests. + +I like the direction, but I'd expand the CI matrix beyond Rust alone. Since this is a monorepo, I'd eventually want independent jobs for: + +Shell linting + +Python linting & tests + +Rust + +Node (if present) + +Documentation validation + +Security scanning + +Secret detection + +License checks + + +That way, failures stay localized and contributors get faster, more actionable feedback. + +Additional considerations + +As I continue the audit, these are areas I'll be looking at closely: + +Whether the repository has a clear modular boundary between reusable libraries and executable tools. + +Whether Termux-specific logic is isolated behind adapters rather than scattered throughout the codebase. + +Whether configuration is centralized (environment variables, paths, feature flags). + +Whether long-running automation is resilient to Android process death and storage constraints. + +Whether AI-generated code has been normalized to a consistent style and architecture. + + +The next phase will be the deeper dive into commit history, code diffs, and the actual implementation quality to identify concrete refactoring opportunities and any architectural risks worth addressing. + - [PR branch commit review](https://chatgpt.com/s/t_6a6d3a0c17e48191a470ddf338780387) +Continuing with the architectural review based on the repository structure, branch strategy, and active development workflow. + +Repository Maturity Assessment + +Current impression: + +Vision: β˜…β˜…β˜…β˜…β˜… + +Experimentation: β˜…β˜…β˜…β˜…β˜… + +Architecture: β˜…β˜…β˜…β˜…β˜† + +Documentation: β˜…β˜…β˜…β˜…β˜† + +Maintainability: β˜…β˜…β˜…β˜†β˜† + +Automation: β˜…β˜…β˜…β˜†β˜† + +Production Readiness: β˜…β˜…β˜†β˜†β˜† + + +This doesn't look like a typical application repositoryβ€”it resembles an evolving developer operating system centered on Termux and AI-assisted workflows. That changes the evaluation criteria significantly. + +Architectural strengths + +1. Monorepo is the right choice + +Given the breadth of tooling you've described previously (CLI utilities, automation, AI integrations, pipelines), keeping everything in a monorepo is sensible. The shared infrastructure and scripts benefit from being versioned together. + +2. Branches indicate experimentation + +Having dedicated proposal and experimental branches suggests you're treating architecture as something to iterate on rather than freezing early. + +I'd lean further into that by clearly separating: + +apps/ +packages/ +libs/ +docs/ +scripts/ +experiments/ +archive/ + +This makes it obvious which code is production-ready versus exploratory. + +3. Documentation-first thinking + +The proposal PR is a good sign. Capturing architectural intent before implementation reduces future rework. + + +--- + +Risks I expect to see + +These are common in fast-moving AI-heavy repositories and are worth checking systematically. + +Configuration sprawl + +Instead of: + +if termux: +... + +if linux: +... + +if replit: +... + +Prefer a single configuration object: + +Config.current() + +Everything else imports that. + + +--- + +Shared utility duplication + +AI-generated code often recreates helpers instead of reusing them. + +I'd look for duplicate implementations of: + +JSON handling + +subprocess wrappers + +HTTP clients + +logging + +retry logic + +path utilities + + +Those belong in a shared package. + + +--- + +Pipeline coupling + +If one component imports another directly, dependencies can become tangled. + +A healthier pattern is: + +event + +↓ + +dispatcher + +↓ + +plugin + +↓ + +result + +rather than every module calling every other module. + + +--- + +What I'd add + +1. Plugin system + +Instead of hardcoding tools: + +plugins/ + + github/ + + claude/ + + deepseek/ + + gemini/ + + openai/ + + local/ + + browser/ + +Each exposes something like: + +run() + +describe() + +capabilities() + +The cockpit simply discovers and loads them. + + +--- + +2. Capability registry + +Rather than asking "which tool should I use?", maintain a registry: + +{ + "supports_streaming": true, + "supports_images": false, + "supports_shell": true, + "supports_reasoning": true +} + +Routing becomes data-driven instead of relying on if statements. + + +--- + +3. Event bus + +I would avoid direct module-to-module communication where possible. + +Instead: + +PromptSubmitted + +↓ + +PromptDispatched + +↓ + +ResponseReceived + +↓ + +Stored + +↓ + +Indexed + +↓ + +Vectorized + +↓ + +Summarized + +This enables adding features (logging, analytics, notifications) without changing the core workflow. + + +--- + +4. AI abstraction layer + +Wrap each provider behind a common interface: + +Provider + +ClaudeProvider + +GeminiProvider + +OpenAIProvider + +DeepSeekProvider + +GitHubModelsProvider + +Switching providers should require minimal changes elsewhere in the codebase. + + +--- + +Performance opportunities + +On Android/Termux, process startup cost matters. + +Consider: + +persistent workers + +connection pooling + +caching parsed configs + +avoiding repeated shell invocations + +minimizing Python interpreter launches + + +Reducing process churn can noticeably improve responsiveness. + + +--- + +Security observations + +The presence of a mistral/fixes-config-security branch suggests you're already addressing some issues. + +I'd specifically review for: + +hardcoded API keys + +session identifiers + +personal filesystem paths + +subprocess injection risks + +unsafe shell=True usage + +unchecked environment variables + +GitHub token scope + +secret leakage in logs + + +Automating these checks in CI (secret scanning, dependency audits, linting) can catch regressions early. + + +--- + +Long-term proposal: evolve into a platform + +The repository appears to be moving beyond a collection of scripts. + +A natural evolution is: + +ArchWiz Platform + +β”œβ”€β”€ CLI +β”œβ”€β”€ Cockpit UI +β”œβ”€β”€ REST API +β”œβ”€β”€ Plugin SDK +β”œβ”€β”€ Scheduler +β”œβ”€β”€ Agent Runtime +β”œβ”€β”€ Memory Layer +β”œβ”€β”€ Vector Store +β”œβ”€β”€ Workflow Engine +β”œβ”€β”€ Prompt Registry +└── Observability + +At that point, external developers could extend the platform through plugins rather than modifying the core. + +Highest-priority recommendations + +1. Introduce a formal plugin architecture. + + +2. Centralize configuration and environment detection. + + +3. Eliminate duplicated utility code across languages. + + +4. Define stable interfaces between components to reduce coupling. + + +5. Add comprehensive CI with linting, testing, security, and documentation validation. + + +6. Adopt ADRs (docs/adr/) to document architectural decisions. + + +7. Establish a clear distinction between stable code, experiments, and archived prototypes. + + + +From what I've seen so far, the repository has ambitious scope and a solid experimental mindset. The biggest opportunity now is to channel that flexibility into well-defined interfaces and modular boundaries so the project can continue to grow without accumulating disproportionate maintenance costs. diff --git a/docs/proposals/PROCESS.md b/docs/proposals/PROCESS.md new file mode 100644 index 0000000000..38a5ff5dbf --- /dev/null +++ b/docs/proposals/PROCESS.md @@ -0,0 +1,57 @@ +# Proposal Process β€” ArchW1z + +Structured lifecycle: **ingest β†’ register β†’ itemize β†’ review β†’ execute β†’ close**. + +**Also read:** `AGENTIC-PERMISSIONS.md` Β· `registry.yaml` Β· root `AGENTS.md` Β· `docs/CONSENSUS.md` + +## Directory layout + +``` +docs/proposals/ + README.md + PROCESS.md + AGENTIC-PERMISSIONS.md + registry.yaml + _template/MANIFEST.md + active//{MANIFEST.md,ITEMS.md,DEBATE.md?,source.md?} + closed// + legacy/ +``` + +## States + +| State | Meaning | +|-------|--------| +| draft | Author still writing | +| posted | In registry.yaml | +| in_review | β‰₯1 reviewer assigned | +| accepted | Execution may start | +| executing | Items being implemented | +| blocked | Waiting on human-only step | +| closed | Terminal under closed/ | + +## Consensus + +Item-scoped. See `docs/CONSENSUS.md` tiers. P0 needs second mind or Operator. Unposted chat is not consensus. + +## Closing + +All ITEMS terminal + Review log outcome + move active/ β†’ closed/ + registry update. + +## Gate coupling + +1. repo-gate green +2. termux-smoke green +3. Item IDs cited +4. No unresolved critical PR threads + +## Agent entrypoint + +```text +1. Read AGENTS.md then registry.yaml +2. Pick highest-priority accepted/executing todo item +3. Branch off master-staging +4. PR β†’ master-staging with Implements: +5. Update ITEMS.md + registry when possible +6. Never close P0 security without Operator evidence +``` diff --git a/docs/proposals/README.md b/docs/proposals/README.md new file mode 100644 index 0000000000..5310f362f7 --- /dev/null +++ b/docs/proposals/README.md @@ -0,0 +1,21 @@ +# Proposals + +**Agents: start at [`registry.yaml`](registry.yaml).** +**Humans: start at [`PROCESS.md`](PROCESS.md).** +**Permissions: [`AGENTIC-PERMISSIONS.md`](AGENTIC-PERMISSIONS.md).** +**Consensus tiers: [`../CONSENSUS.md`](../CONSENSUS.md).** + +## Active + +| ID | Priority | Status | Path | +|----|----------|--------|------| +| chatgpt-critical-eval | P0 | executing | [active/chatgpt-critical-eval/](active/chatgpt-critical-eval/) | +| chatgpt-initial | P2 | posted | [active/chatgpt-initial/](active/chatgpt-initial/) | +| chatgpt-droidapp | P2 | posted | [active/chatgpt-droidapp/](active/chatgpt-droidapp/) | + +Flat historical sources on master: + +- `ChatGPT_Critical-Eval(TER0-15+other-branches).md` +- `ChatGPT-initial.md` +- `ChatGPT_droidApp.md` +- `corrected_cloud_offload_evaluation.md` (from docs/kimi branch) diff --git a/docs/proposals/_template/MANIFEST.md b/docs/proposals/_template/MANIFEST.md new file mode 100644 index 0000000000..d2587c3191 --- /dev/null +++ b/docs/proposals/_template/MANIFEST.md @@ -0,0 +1,47 @@ +--- +id: PROPOSAL-ID +title: "Title" +author: NAME +posted_at: YYYY-MM-DD +source: source.md +status: draft +priority: P2 +reviewers: [] +related_prs: [] +related_branches: [] +gates_required: [repo-gate, termux-smoke] +--- + +# MANIFEST β€” PROPOSAL-ID + +## Summary + +One paragraph intent. + +## Reviewers + +| ID | Role | Status | At | Notes | +|----|------|--------|-----|-------| +| | author | posted | | | + +## Review log + +### YYYY-MM-DD β€” reviewer-id + +- Disposition: accepted | changes_requested | commented +- Notes: + +## Checklist (process) + +- [ ] Registered in `docs/proposals/registry.yaml` +- [ ] ITEMS.md itemized +- [ ] At least one non-author review recorded +- [ ] Status β†’ accepted before execution merges +- [ ] PRs cite `Implements: ` +- [ ] Gates green on merge +- [ ] Closed + moved to `closed/` when terminal + +## Links + +- ITEMS: ./ITEMS.md +- Source: ./source.md diff --git a/docs/proposals/active/chatgpt-critical-eval/ITEMS.md b/docs/proposals/active/chatgpt-critical-eval/ITEMS.md new file mode 100644 index 0000000000..0707d3ba99 --- /dev/null +++ b/docs/proposals/active/chatgpt-critical-eval/ITEMS.md @@ -0,0 +1,26 @@ +# ITEMS β€” chatgpt-critical-eval + +| ID | Work | Priority | Owner | Status | Evidence | +|----|------|----------|-------|--------|----------| +| CE-01 | Install repo-gate on master-staging | P0 | grok-archw1z | done | docs/ARCHW1Z-GATE.md | +| CE-02 | Termux smoke gate | P0 | grok-archw1z | done | PR #11 | +| CE-03 | Living status board | P0 | grok-archw1z | done | ARCHW1Z-STATUS.md | +| CE-04 | Session SSOT schema | P0 | grok-archw1z | done | schemas/session-ssot.md | +| CE-05 | Provider capability registry stub | P1 | grok-archw1z | done | schemas/provider-capabilities.md | +| CE-06 | Security A+B+C checklist | P0 | grok-archw1z | done | SECURITY-REMEDIATION.md | +| CE-07 | Disposition comments on open PRs | P0 | grok-archw1z | done | PR comments | +| CE-08 | Retarget #10 β†’ master-staging | P1 | grok-archw1z | done | | +| CE-09 | Merge #10 if green | P1 | | todo | | +| CE-10 | DeepForge launcher (#9) | P1 | | todo | | +| CE-11 | Retarget #9 β†’ master-staging | P1 | | todo | | +| CE-12 | Decouple #5 cacheβ†’dispatch | P1 | | todo | | +| CE-13 | PR #3 history remediation | P0 | human+agent | blocked | needs rotation | +| CE-14 | Park/close #2 | P2 | | todo | | +| CE-15 | Extract safe patches from #6 | P1 | | todo | | +| CE-16 | Session SSOT minimal writer | P1 | | todo | | +| CE-17 | Event-sourced dispatch | P1 | | todo | | +| CE-18 | Content-addressed blob store | P2 | | todo | | +| CE-19 | Four-plane architecture | P2 | | todo | | +| CE-20 | Proposal process + nested registry | P0 | grok-archw1z | done | this tree | +| CE-21 | CONSENSUS.md + promote process docs to master-staging | P0 | grok-archw1z | doing | this PR | +| CE-22 | Free-tier agentic CI/CD (Gemini CLI + Jules coord + PromptPwnd mitigations) | P0 | grok | doing | PR #42 | diff --git a/docs/proposals/active/chatgpt-critical-eval/MANIFEST.md b/docs/proposals/active/chatgpt-critical-eval/MANIFEST.md new file mode 100644 index 0000000000..a056544350 --- /dev/null +++ b/docs/proposals/active/chatgpt-critical-eval/MANIFEST.md @@ -0,0 +1,41 @@ +--- +id: chatgpt-critical-eval +title: "Critical Eval TER0-15 + other branches" +author: ChatGPT +posted_at: 2026-08-02 +status: executing +priority: P0 +reviewers: + - id: chatgpt + role: author + status: posted + - id: grok-archw1z + role: reviewer+executor + status: accepted +related_prs: [2, 3, 5, 6, 9, 10, 11] +gates_required: [repo-gate, termux-smoke] +--- + +# MANIFEST β€” chatgpt-critical-eval + +## Summary + +Canonical recon of branch topology, PR readiness, security, provider abstraction, DeepForge, integration spine. + +**Canonical text on master:** `docs/proposals/ChatGPT_Critical-Eval(TER0-15+other-branches).md` + +## Review log + +### 2026-08-02 β€” grok-archw1z + +- Disposition: **accepted** (with execution priority order) +- Notes: Do not merge #2/#6 as-is. Promote repo-gate + termux-smoke first. + +## Checklist + +- [x] Registered +- [x] ITEMS.md +- [x] Non-author review +- [x] executing +- [ ] All P0 items terminal +- [ ] Closed diff --git a/docs/proposals/active/chatgpt-droidapp/ITEMS.md b/docs/proposals/active/chatgpt-droidapp/ITEMS.md new file mode 100644 index 0000000000..909f9bd527 --- /dev/null +++ b/docs/proposals/active/chatgpt-droidapp/ITEMS.md @@ -0,0 +1,9 @@ +# ITEMS β€” chatgpt-droidapp + +| ID | Work | Priority | Status | +|----|------|----------|--------| +| DA-01 | Branch naming convention doc | P3 | todo | +| DA-02 | Plugin architecture sketch β†’ code | P2 | todo | +| DA-03 | Event bus (align session-ssot events) | P1 | todo | +| DA-04 | AI provider abstraction (align CE-05) | P1 | todo | +| DA-05 | ADR for monorepo-as-platform | P2 | todo | diff --git a/docs/proposals/active/chatgpt-droidapp/MANIFEST.md b/docs/proposals/active/chatgpt-droidapp/MANIFEST.md new file mode 100644 index 0000000000..884d05ace5 --- /dev/null +++ b/docs/proposals/active/chatgpt-droidapp/MANIFEST.md @@ -0,0 +1,18 @@ +--- +id: chatgpt-droidapp +title: "droidApp / early branch inventory + plugin architecture" +author: ChatGPT +posted_at: 2026-08-02 +status: posted +priority: P2 +--- + +# MANIFEST β€” chatgpt-droidapp + +**Canonical text:** `docs/proposals/ChatGPT_droidApp.md` + +## Review log + +### 2026-08-02 β€” grok-archw1z + +- Disposition: accepted as **P2 vision**; capability registry under CE-05. diff --git a/docs/proposals/active/chatgpt-initial/ITEMS.md b/docs/proposals/active/chatgpt-initial/ITEMS.md new file mode 100644 index 0000000000..820fa34422 --- /dev/null +++ b/docs/proposals/active/chatgpt-initial/ITEMS.md @@ -0,0 +1,9 @@ +# ITEMS β€” chatgpt-initial + +| ID | Work | Priority | Status | +|----|------|----------|--------| +| CI-01 | Split mega-README into cockpit + linked docs | P2 | todo | +| CI-02 | Generated PROJECT_INDEX / MODULE_GRAPH pipeline | P2 | todo | +| CI-03 | Unify central_mapper β†’ multi-output scan | P2 | todo | +| CI-04 | AI_CONTEXT pack generation | P2 | todo | +| CI-05 | ADR directory docs/adr/ | P2 | todo | diff --git a/docs/proposals/active/chatgpt-initial/MANIFEST.md b/docs/proposals/active/chatgpt-initial/MANIFEST.md new file mode 100644 index 0000000000..6254546224 --- /dev/null +++ b/docs/proposals/active/chatgpt-initial/MANIFEST.md @@ -0,0 +1,18 @@ +--- +id: chatgpt-initial +title: "Initial repository evaluation / cockpit intelligence" +author: ChatGPT +posted_at: 2026-08-02 +status: posted +priority: P2 +--- + +# MANIFEST β€” chatgpt-initial + +**Canonical text:** `docs/proposals/ChatGPT-initial.md` + +## Review log + +### 2026-08-02 β€” grok-archw1z + +- Disposition: accepted as **P2** after gates + SSOT diff --git a/docs/proposals/corrected_cloud_offload_evaluation.md b/docs/proposals/corrected_cloud_offload_evaluation.md new file mode 100644 index 0000000000..80f6ab14dd --- /dev/null +++ b/docs/proposals/corrected_cloud_offload_evaluation.md @@ -0,0 +1,21 @@ +# Corrected Cloud Offload Evaluation + +> **Source branch:** `docs/kimi-cloud-offload-evaluation` +> **Full text:** `docs/proposals/corrected_cloud_offload_evaluation.md` on that branch +> **Promoted:** pointer on `master` so process docs land without a 24KB mid-flight dump + +## Summary of corrections + +1. **Retry pattern** β€” not pure exponential backoff; **impatient user burst** (20% instant 0.5–2s, 80% jittered exponential, cap 90s) in deepcli. +2. **No calendar phases** β€” use Big-O complexity classes (O(1) bootstrap β†’ O(log n) route β†’ O(n) parallel β†’ O(k log k) merge). +3. **TMUX replacement** β€” prefer `archwiz/autonomous_runner.py`, Hermes terminal/delegation, chronos Celery, sandbox-alternative VMs. +4. **AGY/Jules templates** β€” agentic-workflow-starter, antigravity-jules-autonomous, gemini-cli-jules-orchestrator as scavenge sources. +5. **jules-worker-pool-cli** β€” un-pause path documented on source branch. + +## Action + +```text +git show origin/docs/kimi-cloud-offload-evaluation:docs/proposals/corrected_cloud_offload_evaluation.md +``` + +Registrar may nest under `docs/proposals/active/` when itemized into ITEMS. diff --git a/docs/proposals/registry.yaml b/docs/proposals/registry.yaml new file mode 100644 index 0000000000..cecbdf4686 --- /dev/null +++ b/docs/proposals/registry.yaml @@ -0,0 +1,56 @@ +# ArchW1z proposal registry β€” agents read this first +version: 1 +updated_at: "2026-08-04T00:00:00Z" +updated_by: grok-archw1z + +proposals: + - id: chatgpt-critical-eval + title: "Critical Eval TER0-15 + other branches" + author: ChatGPT + status: executing + priority: P0 + path: active/chatgpt-critical-eval/ + legacy_source: ChatGPT_Critical-Eval(TER0-15+other-branches).md + reviewers: + - id: chatgpt + role: author + status: posted + - id: grok-archw1z + role: reviewer+executor + status: accepted + related_prs: [2, 3, 5, 6, 9, 10, 11] + gates_required: [repo-gate, termux-smoke] + + - id: chatgpt-initial + title: "Initial repository evaluation / cockpit intelligence" + author: ChatGPT + status: posted + priority: P2 + path: active/chatgpt-initial/ + legacy_source: ChatGPT-initial.md + reviewers: + - id: chatgpt + role: author + status: posted + - id: grok-archw1z + role: reviewer + status: accepted + related_prs: [] + gates_required: [repo-gate] + + - id: chatgpt-droidapp + title: "droidApp / early branch inventory + plugin architecture" + author: ChatGPT + status: posted + priority: P2 + path: active/chatgpt-droidapp/ + legacy_source: ChatGPT_droidApp.md + reviewers: + - id: chatgpt + role: author + status: posted + - id: grok-archw1z + role: reviewer + status: accepted + related_prs: [1, 2] + gates_required: [repo-gate] diff --git a/docs/schemas/provider-capabilities.md b/docs/schemas/provider-capabilities.md new file mode 100644 index 0000000000..a6991a3e37 --- /dev/null +++ b/docs/schemas/provider-capabilities.md @@ -0,0 +1,9 @@ +# Provider Capability Registry + +> **Status:** SPEC (P1) + +Every provider implements identity, capabilities, availability, authenticate, create_session, send, stream, history, export, health. + +Capability flags: installed, authenticated, session_create/resume, streaming, history, attachments, thinking, web_search, code_execution, browser_tls, export, indexing, dispatch. + +`curl_cffi` β‰  stdlib `requests`. If `requires_browser_tls` and only requests available β†’ fail clearly. diff --git a/docs/schemas/session-ssot.md b/docs/schemas/session-ssot.md new file mode 100644 index 0000000000..c3d668659f --- /dev/null +++ b/docs/schemas/session-ssot.md @@ -0,0 +1,20 @@ +# Session SSOT Schema + +> **Status:** SPEC (P0) + +## Canonical layout + +``` +~/.archwiz/sessions//// + manifest.json + messages.jsonl + events.jsonl + blobs/ +``` + +Providers may retain native stores as caches. ArchWiz is the cross-provider identity layer. + +Never hardcode `/data/data/com.termux/...` in committed code. +Never represent missing timestamps as `""` β€” use `null` + `timestamp_source`. + +See master-staging for full JSON field definitions. diff --git a/src/context_collector.py b/src/context_collector.py index ced7dac153..f2a28bac68 100644 --- a/src/context_collector.py +++ b/src/context_collector.py @@ -54,12 +54,21 @@ def generate_ast_skeleton(self, file_relative_path): return f"// Unable to trace AST module boundary map for {file_relative_path}" def assemble_minimized_bundle(self, active_target_file): + """ + Assemble a minimized context bundle containing dependent-file structures and the active file's full source. + + Parameters: + active_target_file (str): Relative path of the file to include as the active editing target. + + Returns: + str: Formatted architecture context containing dependency skeletons and the active file source. + """ dependencies = self.find_dependent_files(active_target_file) bundle = ["=== CODEBASE ARCHITECTURE SUBSTRUCTURE CONTEXT ==="] for dep in dependencies: skeleton = self.generate_ast_skeleton(dep) - bundle.append(f"\n\n{skeleton}\n") + bundle.append(f'\n\n{skeleton}\n') with open(os.path.join(self.workspace, active_target_file), 'r') as f: full_source = f.read() - bundle.append(f"\n\n{full_source}\n") - return "\n".join(bundle) \ No newline at end of file + bundle.append(f'\n\n{full_source}\n') + return "\n".join(bundle) diff --git a/src/db.py b/src/db.py index 3c8ee3d385..a1fbbb55ce 100644 --- a/src/db.py +++ b/src/db.py @@ -7,6 +7,9 @@ DB_PATH = "local_repo.db" def init_db(): + """ + Create the SQLite database and required tables if they do not already exist. + """ with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() cursor.execute(''' @@ -35,26 +38,25 @@ def init_db(): verdict TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP )''') + cursor.execute(''' + CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5( + content, + session_id UNINDEXED, + msg_idx UNINDEXED + )''') conn.commit() -from pathlib import Path -from datetime import datetime, timezone - - # Also write to run_history.jsonl for ForeSight - rh_file = Path.home() / 'termux-multi-agent/run_history.jsonl' - rh_file.parent.mkdir(parents=True, exist_ok=True) - with open(rh_file, 'a') as rhf: - json.dump({ - "target_file": target_file, - "verdict": verdict, - "attempt": attempt, - "patch": patch[:200], - "errors": errors[:200] if errors else "", - "timestamp": datetime.now(timezone.utc).isoformat() - }, rhf) - rhf.write('\n') - def log_attempt_telemetry(target_file, attempt, patch, errors, verdict): + """ + Record a patch attempt and its outcome in the run history. + + Parameters: + target_file: Path of the file targeted by the attempt. + attempt: Attempt number. + patch: Patch content associated with the attempt. + errors: Errors reported for the attempt. + verdict: Outcome assigned to the attempt. + """ with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() cursor.execute( @@ -63,7 +65,33 @@ def log_attempt_telemetry(target_file, attempt, patch, errors, verdict): ) conn.commit() -def index_project_file(workspace_root, relative_path): + # Also write to run_history.jsonl for ForeSight + try: + from pathlib import Path + from datetime import datetime, timezone + rh_file = Path.home() / 'termux-multi-agent/run_history.jsonl' + rh_file.parent.mkdir(parents=True, exist_ok=True) + with open(rh_file, 'a') as rhf: + json.dump({ + "target_file": target_file, + "verdict": verdict, + "attempt": attempt, + "patch": patch[:200], + "errors": errors[:200] if errors else "", + "timestamp": datetime.now(timezone.utc).isoformat() + }, rhf) + rhf.write('\n') + except Exception: + pass + +def index_project_file(workspace_root, relative_path, conn=None): + """ + Index a supported project file's code elements and import relationships in the database. + + Parameters: + workspace_root: Root directory of the project. + relative_path: File path relative to the project root. + """ abs_path = os.path.join(workspace_root, relative_path) ext = os.path.splitext(relative_path)[1] lang_map = {'.py': 'python', '.js': 'javascript', '.mjs': 'javascript', '.rs': 'rust'} @@ -71,31 +99,110 @@ def index_project_file(workspace_root, relative_path): if not lang: return try: + # Run first ast-grep to scan nodes output = subprocess.check_output(["ast-grep", "scan", "--json", abs_path], text=True) nodes = json.loads(output) - with sqlite3.connect(DB_PATH) as conn: - cursor = conn.cursor() - for node in nodes: - node_id = f"{relative_path}:{node.get('range', {}).get('start', {}).get('line', 0)}" - cursor.execute( - "INSERT OR REPLACE INTO nodes VALUES (?, ?, ?, ?, ?, ?)", - (node_id, relative_path, lang, node.get('kind'), node.get('text', '')[:50], - node.get('range', {}).get('start', {}).get('line', 0)) - ) + + # Run second ast-grep to scan imports import_pattern = "import $MOD from '$PATH'" if lang == 'javascript' else "import $MOD" import_output = subprocess.check_output( ["ast-grep", "scan", "--pattern", import_pattern, "--json", abs_path], text=True ) import_nodes = json.loads(import_output) + + # Batch node database entries + node_data = [] + for node in nodes: + node_id = f"{relative_path}:{node.get('range', {}).get('start', {}).get('line', 0)}" + node_data.append(( + node_id, relative_path, lang, node.get('kind'), node.get('text', '')[:50], + node.get('range', {}).get('start', {}).get('line', 0) + )) + + # Batch import edge database entries + edge_data = [] for imp in import_nodes: imp_text = imp.get('text', '') - quoted_paths = re.findall(r"['"](.*?)['"]", imp_text) + quoted_paths = re.findall(r'["\'](.*?)["\']', imp_text) for target in quoted_paths: clean_target = target.lstrip('./').replace('.js', '').replace('.py', '') - cursor.execute( - "INSERT OR IGNORE INTO edges VALUES (?, ?, ?)", - (relative_path, clean_target, "imports") - ) - conn.commit() + edge_data.append((relative_path, clean_target, "imports")) + + # Database transaction using batch executemany for high performance + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + + try: + cursor = conn.cursor() + if node_data: + cursor.executemany("INSERT OR REPLACE INTO nodes VALUES (?, ?, ?, ?, ?, ?)", node_data) + if edge_data: + cursor.executemany("INSERT OR IGNORE INTO edges VALUES (?, ?, ?)", edge_data) + if close_conn: + conn.commit() + finally: + if close_conn: + conn.close() except Exception: - pass \ No newline at end of file + pass + +def batch_insert_fts_messages(messages, conn=None): + """ + Insert message records into the full-text search table in a single batch. + + Parameters: + messages (iterable): Message dictionaries with `content`, `session_id`, and + `msg_idx` fields, or three-item iterables containing those values. + """ + data = [] + for msg in messages: + if isinstance(msg, dict): + content = msg.get('content', '') + session_id = msg.get('session_id', '') + msg_idx = msg.get('msg_idx', 0) + else: + content, session_id, msg_idx = msg + data.append((content, session_id, msg_idx)) + + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + try: + cursor = conn.cursor() + if data: + cursor.executemany("INSERT INTO messages_fts(content, session_id, msg_idx) VALUES (?, ?, ?)", data) + if close_conn: + conn.commit() + finally: + if close_conn: + conn.close() + +def search_fts_messages(query, limit=10, conn=None): + """ + Search indexed messages for matches in their content. + + Parameters: + query (str): FTS5 query used to match message content. + limit (int): Maximum number of matching messages to return. + conn: Optional SQLite database connection. + + Returns: + list: Tuples containing a highlighted content snippet, session ID, and message index. + """ + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + try: + cursor = conn.cursor() + cursor.execute( + "SELECT snippet(messages_fts, 0, '', '', '…', 40), session_id, msg_idx FROM messages_fts WHERE content MATCH ? LIMIT ?", + (query, limit) + ) + return cursor.fetchall() + finally: + if close_conn: + conn.close() diff --git a/termux-multi-agent/dashboard.py b/termux-multi-agent/dashboard.py index f313419d89..1bead032e1 100644 --- a/termux-multi-agent/dashboard.py +++ b/termux-multi-agent/dashboard.py @@ -1,11 +1,24 @@ +#!/usr/bin/env python3 import time import os import json +import sys +from datetime import datetime -TELEMETRY_LOG = "agent_telemetry_stream.json" +try: + from rich.console import Console, Group + from rich.table import Table + from rich.panel import Panel + from rich.live import Live + from rich.text import Text + from rich.box import ROUNDED +except ImportError: + # Clean fallback warning + print("[ERROR] 'rich' library is required. Please run: pip install rich") + sys.exit(1) -def clear_screen(): - print("\033[H\033[J", end="") +TELEMETRY_LOG = "agent_telemetry_stream.json" +console = Console() def read_latest_telemetry(): if not os.path.exists(TELEMETRY_LOG): @@ -16,54 +29,136 @@ def read_latest_telemetry(): for line in f: if not line.strip(): continue - entry = json.loads(line) - target = entry.get("target") or "System" - active_jobs[target] = entry + try: + entry = json.loads(line) + target = entry.get("target") or "System" + active_jobs[target] = entry + except json.JSONDecodeError: + continue except Exception: pass - return list(active_jobs.values()) - -def render_dashboard(): - clear_screen() - print("=" * 65) - print(" ⚑ TERMUX MULTI-AGENT PARALLEL TELEMETRY DASHBOARD ⚑ ") - print("=" * 65) - print(f" Last Sync: {time.strftime('%Y-%m-%d %H:%M:%S')}") - print("-" * 65) - print(f"{'TARGET FILE':<20} | {'AGENT':<16} | {'TRY':<4} | {'STATUS':<15}") - print("-" * 65) + # Sort by timestamp so the list ordering is consistent/predictable + return sorted(active_jobs.values(), key=lambda x: x.get("timestamp", "")) +def make_dashboard(): + # Read data jobs = read_latest_telemetry() + + # Header info + now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + header_text = Text() + header_text.append("⚑ TERMUX MULTI-AGENT PARALLEL TELEMETRY ⚑\n", style="bold yellow") + header_text.append(f"Last Sync: {now_str} | File: {TELEMETRY_LOG}", style="dim") + + header_panel = Panel( + header_text, + box=ROUNDED, + border_style="yellow", + expand=True, + ) + if not jobs: - print(" [ Waiting for background agent pipelines to initialize... ]") + # Beautiful empty state + empty_text = Text() + empty_text.append("\n[ Waiting for background agent pipelines to initialize... ]\n\n", style="italic cyan") + empty_text.append("To start the multi-agent orchestration pipeline, run:\n", style="dim") + empty_text.append(" ./run_agent.sh\n", style="bold green") + empty_text.append("\nThis dashboard will automatically update once events are received.\n", style="dim") + empty_text.append("Press Ctrl+C to exit.", style="dim red") + + body_panel = Panel( + empty_text, + title="System Status", + box=ROUNDED, + border_style="cyan", + expand=True + ) + return Panel( + Group( + header_panel, + body_panel + ), + box=ROUNDED, + border_style="dim" + ) + + # Beautiful table + table = Table(box=ROUNDED, border_style="dim", expand=True) + table.add_column("Target File", style="bold cyan", no_wrap=True) + table.add_column("Agent", style="bold magenta") + table.add_column("Try", justify="center", style="yellow") + table.add_column("Status", justify="center") + table.add_column("Last Message", style="white") + table.add_column("Timestamp", style="dim", justify="right") + for job in jobs: target = job.get("target") or "Global" - if len(target) > 18: - target = "..." + target[-15:] + # truncate long targets cleanly + if len(target) > 25: + target = "..." + target[-22:] + agent = job.get("agent", "Unknown") attempt = str(job.get("attempt") or "-") level = job.get("level", "INFO") + message = job.get("message", "") + timestamp = job.get("timestamp", "") + if timestamp: + # Format time if it has full date/time + try: + dt = datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S") + timestamp = dt.strftime("%H:%M:%S") + except ValueError: + pass + # Beautiful styled status tag if level == "SUCCESS": - status_str = "\033[92mSUCCESS\033[0m" + status_str = Text("SUCCESS", style="bold green") elif level == "RETRY": - status_str = "\033[93mRETRYING\033[0m" + status_str = Text("RETRYING", style="bold yellow") elif level == "CRITICAL": - status_str = "\033[91mCRITICAL\033[0m" + status_str = Text("CRITICAL", style="bold red") else: - status_str = "\033[94mPROCESSING\033[0m" + status_str = Text("PROCESSING", style="bold blue") + + table.add_row( + target, + agent, + attempt, + status_str, + message, + timestamp + ) + + footer_text = Text("\nPress Ctrl+C to exit Dashboard Viewer.", style="dim italic red") - print(f"{target:<20} | {agent:<16} | {attempt:<4} | {status_str:<15}") - print(f" ↳ Msg: {job.get('message', '')[:60]}") - print("-" * 65) + return Panel( + Group( + header_panel, + table, + footer_text + ), + box=ROUNDED, + border_style="blue", + title="Agent Live Monitor" + ) def main(): try: - while True: - render_dashboard() - time.sleep(1.0) + # Use Live rendering for smooth, flicker-free updates + with Live(make_dashboard(), refresh_per_second=1, screen=True) as live: + while True: + time.sleep(1.0) + live.update(make_dashboard()) except KeyboardInterrupt: - print("\nExiting Dashboard Viewer.") + # Clear screen and say goodbye gracefully + console.clear() + console.print(Panel( + "[bold green]Thank you for using Termux Multi-Agent Dashboard![/bold green]\n" + "Stay productive and keep building! βš‘πŸš€", + title="Exiting Dashboard", + border_style="green", + expand=False + )) if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/termux-multi-agent/provision_agent.py b/termux-multi-agent/provision_agent.py index 6152a3012b..0ff8bd2943 100644 --- a/termux-multi-agent/provision_agent.py +++ b/termux-multi-agent/provision_agent.py @@ -70,7 +70,7 @@ def log_attempt_telemetry(target_file, attempt, patch, errors, verdict): ) conn.commit() -def index_project_file(workspace_root, relative_path): +def index_project_file(workspace_root, relative_path, conn=None): abs_path = os.path.join(workspace_root, relative_path) ext = os.path.splitext(relative_path)[1] lang_map = {'.py': 'python', '.js': 'javascript', '.mjs': 'javascript', '.rs': 'rust'} @@ -78,32 +78,52 @@ def index_project_file(workspace_root, relative_path): if not lang: return try: + # Run first ast-grep to scan nodes output = subprocess.check_output(["ast-grep", "scan", "--json", abs_path], text=True) nodes = json.loads(output) - with sqlite3.connect(DB_PATH) as conn: - cursor = conn.cursor() - for node in nodes: - node_id = f"{relative_path}:{node.get('range', {}).get('start', {}).get('line', 0)}" - cursor.execute( - "INSERT OR REPLACE INTO nodes VALUES (?, ?, ?, ?, ?, ?)", - (node_id, relative_path, lang, node.get('kind'), node.get('text', '')[:50], - node.get('range', {}).get('start', {}).get('line', 0)) - ) + + # Run second ast-grep to scan imports import_pattern = "import $MOD from '$PATH'" if lang == 'javascript' else "import $MOD" import_output = subprocess.check_output( ["ast-grep", "scan", "--pattern", import_pattern, "--json", abs_path], text=True ) import_nodes = json.loads(import_output) + + # Batch node database entries + node_data = [] + for node in nodes: + node_id = f"{relative_path}:{node.get('range', {}).get('start', {}).get('line', 0)}" + node_data.append(( + node_id, relative_path, lang, node.get('kind'), node.get('text', '')[:50], + node.get('range', {}).get('start', {}).get('line', 0) + )) + + # Batch import edge database entries + edge_data = [] for imp in import_nodes: imp_text = imp.get('text', '') quoted_paths = re.findall(r"['\"](.*?)['\"]", imp_text) for target in quoted_paths: clean_target = target.lstrip('./').replace('.js', '').replace('.py', '') - cursor.execute( - "INSERT OR IGNORE INTO edges VALUES (?, ?, ?)", - (relative_path, clean_target, "imports") - ) - conn.commit() + edge_data.append((relative_path, clean_target, "imports")) + + # Database transaction using batch executemany for high performance + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + + try: + cursor = conn.cursor() + if node_data: + cursor.executemany("INSERT OR REPLACE INTO nodes VALUES (?, ?, ?, ?, ?, ?)", node_data) + if edge_data: + cursor.executemany("INSERT OR IGNORE INTO edges VALUES (?, ?, ?)", edge_data) + if close_conn: + conn.commit() + finally: + if close_conn: + conn.close() except Exception: pass""", "src/sandbox.py": """import subprocess @@ -388,10 +408,23 @@ def main(): print("[+] Re-run the script or trigger run_agent.sh to start the operational pipeline loop.") sys.exit(0) - for root, _, files in os.walk(workspace_path): - for file in files: - rel_path = os.path.relpath(os.path.join(root, file), workspace_path) - index_project_file(workspace_path, rel_path) + # 1nd3x 4ll pr0j3ct f1l3s (using a single shared sqlite3 connection for speed) + import sqlite3 + from src.db import DB_PATH + try: + conn = sqlite3.connect(DB_PATH) + for root, _, files in os.walk(workspace_path): + for file in files: + rel_path = os.path.relpath(os.path.join(root, file), workspace_path) + index_project_file(workspace_path, rel_path, conn=conn) + conn.commit() + except Exception: + pass + finally: + try: + conn.close() + except Exception: + pass target_file = "test_script.py" refactor_goal = "Refactor compute to intercept and handle ZeroDivisionError scenario profiles cleanly." diff --git a/termux-multi-agent/run.py b/termux-multi-agent/run.py index 7e63ca4107..779ebaa52a 100644 --- a/termux-multi-agent/run.py +++ b/termux-multi-agent/run.py @@ -67,6 +67,11 @@ def get_refactor_goal(workspace_path): return default_goal def main(): + """ + Run the refactoring pipeline for the configured workspace and target file. + + Creates a default workspace and sample target when the workspace is missing. Otherwise, indexes workspace files, determines the refactoring goal, collects relevant code context, and runs the pipeline with Python compilation validation. + """ init_db() workspace_path = os.environ.get("TASK_WORKSPACE", "/data/data/com.termux/files/home/termux-multi-agent/workspace") @@ -78,11 +83,23 @@ def main(): print("[+] Re-run the script or trigger run_agent.sh to start the operational pipeline loop.") sys.exit(0) - # 1nd3x 4ll pr0j3ct f1l3s - for root, _, files in os.walk(workspace_path): - for file in files: - rel_path = os.path.relpath(os.path.join(root, file), workspace_path) - index_project_file(workspace_path, rel_path) + # 1nd3x 4ll pr0j3ct f1l3s (using a single shared sqlite3 connection for speed) + import sqlite3 + from src.db import DB_PATH + try: + conn = sqlite3.connect(DB_PATH) + for root, _, files in os.walk(workspace_path): + for file in files: + rel_path = os.path.relpath(os.path.join(root, file), workspace_path) + index_project_file(workspace_path, rel_path, conn=conn) + conn.commit() + except Exception: + pass + finally: + try: + conn.close() + except Exception: + pass # D3t3rm1n3 t4rg3t f1l3 target_name = os.environ.get("TARGET_FILE", "test_script.py") diff --git a/termux-multi-agent/src/db.py b/termux-multi-agent/src/db.py index a1efbc1eb1..29debf0c9f 100644 --- a/termux-multi-agent/src/db.py +++ b/termux-multi-agent/src/db.py @@ -7,6 +7,9 @@ DB_PATH = "local_repo.db" def init_db(): + """ + Create the SQLite database tables used for code indexing, run history, and message search. + """ with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() cursor.execute(''' @@ -35,9 +38,25 @@ def init_db(): verdict TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP )''') + cursor.execute(''' + CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5( + content, + session_id UNINDEXED, + msg_idx UNINDEXED + )''') conn.commit() def log_attempt_telemetry(target_file, attempt, patch, errors, verdict): + """ + Record an execution attempt and its outcome in the run history. + + Parameters: + target_file (str): Path of the file targeted by the attempt. + attempt (int): Attempt number. + patch (str): Patch content associated with the attempt. + errors (str): Errors recorded during the attempt. + verdict (str): Outcome assigned to the attempt. + """ with sqlite3.connect(DB_PATH) as conn: cursor = conn.cursor() cursor.execute( @@ -46,7 +65,18 @@ def log_attempt_telemetry(target_file, attempt, patch, errors, verdict): ) conn.commit() -def index_project_file(workspace_root, relative_path): +def index_project_file(workspace_root, relative_path, conn=None): + """ + Index a supported project file and record its code nodes and import relationships. + + Parameters: + workspace_root (str): Root directory containing the project file. + relative_path (str): File path relative to the workspace root. + conn (sqlite3.Connection, optional): Database connection to use for storing + indexed data. + + Unsupported file types and indexing failures are ignored. + """ abs_path = os.path.join(workspace_root, relative_path) ext = os.path.splitext(relative_path)[1] lang_map = {'.py': 'python', '.js': 'javascript', '.mjs': 'javascript', '.rs': 'rust'} @@ -54,32 +84,115 @@ def index_project_file(workspace_root, relative_path): if not lang: return try: - output = subprocess.check_output(["ast-grep", "run", "--pattern", ".*", "--json", abs_path], cwd="/data/data/com.termux/files/home/termux-multi-agent", text=True) + # Run first ast-grep to scan nodes (matching specific pattern or wildcard) + output = subprocess.check_output( + ["ast-grep", "run", "--pattern", ".*", "--json", abs_path], + cwd="/data/data/com.termux/files/home/termux-multi-agent", + text=True + ) nodes = json.loads(output) - with sqlite3.connect(DB_PATH) as conn: - cursor = conn.cursor() - for node in nodes: - node_id = f"{relative_path}:{node.get('range', {}).get('start', {}).get('line', 0)}" - cursor.execute( - "INSERT OR REPLACE INTO nodes VALUES (?, ?, ?, ?, ?, ?)", - (node_id, relative_path, lang, node.get('kind'), node.get('text', '')[:50], node.get('range', {}).get('start', {}).get('line', 0)) - ) + + # Run second ast-grep to scan imports import_pattern = "import $MOD from '$PATH'" if lang == 'javascript' else "import $MOD" import_output = subprocess.check_output( - ["ast-grep", "run", "--pattern", import_pattern, "--json", abs_path], cwd="/data/data/com.termux/files/home/termux-multi-agent", text=True + ["ast-grep", "run", "--pattern", import_pattern, "--json", abs_path], + cwd="/data/data/com.termux/files/home/termux-multi-agent", + text=True ) import_nodes = json.loads(import_output) - with sqlite3.connect(DB_PATH) as conn: + + # Batch node database entries + node_data = [] + for node in nodes: + node_id = f"{relative_path}:{node.get('range', {}).get('start', {}).get('line', 0)}" + node_data.append(( + node_id, relative_path, lang, node.get('kind'), node.get('text', '')[:50], + node.get('range', {}).get('start', {}).get('line', 0) + )) + + # Batch import edge database entries + edge_data = [] + for imp in import_nodes: + imp_text = imp.get('text', '') + quoted_paths = re.findall(r'["\'](.*?)["\']', imp_text) + for target in quoted_paths: + clean_target = target.lstrip('./').replace('.js', '').replace('.py', '') + edge_data.append((relative_path, clean_target, "imports")) + + # Database transaction using batch executemany for high performance + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + + try: cursor = conn.cursor() - for imp in import_nodes: - imp_text = imp.get('text', '') - quoted_paths = re.findall(r'["\'](.*?)["\']', imp_text) - for target in quoted_paths: - clean_target = target.lstrip('./').replace('.js', '').replace('.py', '') - cursor.execute( - "INSERT OR IGNORE INTO edges VALUES (?, ?, ?)", - (relative_path, clean_target, "imports") - ) - conn.commit() + if node_data: + cursor.executemany("INSERT OR REPLACE INTO nodes VALUES (?, ?, ?, ?, ?, ?)", node_data) + if edge_data: + cursor.executemany("INSERT OR IGNORE INTO edges VALUES (?, ?, ?)", edge_data) + if close_conn: + conn.commit() + finally: + if close_conn: + conn.close() except Exception: pass + +def batch_insert_fts_messages(messages, conn=None): + """ + Insert message records into the full-text search index. + + Parameters: + messages: Message dictionaries or tuples containing content, session ID, and message index. + conn: Optional SQLite database connection to use. + """ + data = [] + for msg in messages: + if isinstance(msg, dict): + content = msg.get('content', '') + session_id = msg.get('session_id', '') + msg_idx = msg.get('msg_idx', 0) + else: + content, session_id, msg_idx = msg + data.append((content, session_id, msg_idx)) + + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + try: + cursor = conn.cursor() + if data: + cursor.executemany("INSERT INTO messages_fts(content, session_id, msg_idx) VALUES (?, ?, ?)", data) + if close_conn: + conn.commit() + finally: + if close_conn: + conn.close() + +def search_fts_messages(query, limit=10, conn=None): + """ + Search indexed messages using an FTS5 query. + + Parameters: + query: The FTS5 query expression. + limit: Maximum number of matching messages to return. + + Returns: + A list of tuples containing highlighted message snippets, session IDs, and message indexes. + """ + close_conn = False + if conn is None: + conn = sqlite3.connect(DB_PATH) + close_conn = True + try: + cursor = conn.cursor() + cursor.execute( + "SELECT snippet(messages_fts, 0, '', '', '…', 40), session_id, msg_idx FROM messages_fts WHERE content MATCH ? LIMIT ?", + (query, limit) + ) + return cursor.fetchall() + finally: + if close_conn: + conn.close() diff --git a/termux-multi-agent/workspace/run.py b/termux-multi-agent/workspace/run.py index 7e63ca4107..24920fd3f8 100644 --- a/termux-multi-agent/workspace/run.py +++ b/termux-multi-agent/workspace/run.py @@ -67,6 +67,14 @@ def get_refactor_goal(workspace_path): return default_goal def main(): + """ + Run the refactoring pipeline for the configured workspace and target file. + + Initializes the project database, indexes workspace files, determines the + refactoring goal, collects codebase context, and invokes the agent with Python + compilation as the validation command. Creates a default workspace and sample + target file when the configured workspace does not exist. + """ init_db() workspace_path = os.environ.get("TASK_WORKSPACE", "/data/data/com.termux/files/home/termux-multi-agent/workspace") @@ -78,11 +86,23 @@ def main(): print("[+] Re-run the script or trigger run_agent.sh to start the operational pipeline loop.") sys.exit(0) - # 1nd3x 4ll pr0j3ct f1l3s - for root, _, files in os.walk(workspace_path): - for file in files: - rel_path = os.path.relpath(os.path.join(root, file), workspace_path) - index_project_file(workspace_path, rel_path) + # 1nd3x 4ll pr0j3ct f1l3s (using a single shared sqlite3 connection for speed) + import sqlite3 + from src.db import DB_PATH + try: + conn = sqlite3.connect(DB_PATH) + for root, _, files in os.walk(workspace_path): + for file in files: + rel_path = os.path.relpath(os.path.join(root, file), workspace_path) + index_project_file(workspace_path, rel_path, conn=conn) + conn.commit() + except Exception: + pass + finally: + try: + conn.close() + except Exception: + pass # D3t3rm1n3 t4rg3t f1l3 target_name = os.environ.get("TARGET_FILE", "test_script.py") diff --git a/tests/test_db_optimized.py b/tests/test_db_optimized.py new file mode 100644 index 0000000000..ecb429b0a4 --- /dev/null +++ b/tests/test_db_optimized.py @@ -0,0 +1,109 @@ +import os +import sqlite3 +import pytest +import subprocess +from src.db import init_db, index_project_file, DB_PATH + +def test_db_operations(tmp_path, monkeypatch): + # Set DB path to a temporary one + temp_db = tmp_path / "test_repo.db" + monkeypatch.setattr("src.db.DB_PATH", str(temp_db)) + + # Initialize the DB + init_db() + + # Check that database and tables are created + assert temp_db.exists() + conn = sqlite3.connect(str(temp_db)) + cursor = conn.cursor() + cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") + tables = [r[0] for r in cursor.fetchall()] + assert "nodes" in tables + assert "edges" in tables + assert "run_history" in tables + conn.close() + +def test_index_project_file_no_ast_grep(tmp_path, monkeypatch): + # Ensure no-op when ast-grep isn't there + temp_db = tmp_path / "test_repo.db" + monkeypatch.setattr("src.db.DB_PATH", str(temp_db)) + init_db() + + # Create a dummy python file + test_file = tmp_path / "test_file.py" + test_file.write_text("def test(): pass\n") + + # Since ast-grep is not installed/functional in this sandbox, it should catch Exception and pass gracefully + # Calling index_project_file should not crash + index_project_file(str(tmp_path), "test_file.py") + +def test_index_project_file_success(tmp_path, monkeypatch): + temp_db = tmp_path / "test_repo.db" + monkeypatch.setattr("src.db.DB_PATH", str(temp_db)) + init_db() + + # Create dummy files + test_file = tmp_path / "test_file.py" + test_file.write_text("import 'os'\n") + + # Mock subprocess.check_output to return mock nodes and mock imports + call_count = 0 + def mock_check_output(cmd, **kwargs): + nonlocal call_count + call_count += 1 + if call_count == 1: + # Nodes + return '[{"kind": "class", "range": {"start": {"line": 10}}, "text": "class Test"}]' + else: + # Imports + return '[{"text": "import \'os\'"}]' + + monkeypatch.setattr(subprocess, "check_output", mock_check_output) + + # Call indexing + index_project_file(str(tmp_path), "test_file.py") + + # Verify that nodes and edges are populated using executemany batch writes + conn = sqlite3.connect(str(temp_db)) + cursor = conn.cursor() + cursor.execute("SELECT * FROM nodes;") + nodes = cursor.fetchall() + assert len(nodes) == 1 + assert nodes[0][1] == "test_file.py" + assert nodes[0][3] == "class" + assert nodes[0][4] == "class Test" + + cursor.execute("SELECT * FROM edges;") + edges = cursor.fetchall() + assert len(edges) == 1 + assert edges[0][0] == "test_file.py" + assert edges[0][1] == "os" + conn.close() + +def test_fts5_virtual_table(tmp_path, monkeypatch): + temp_db = tmp_path / "test_repo_fts.db" + monkeypatch.setattr("src.db.DB_PATH", str(temp_db)) + init_db() + + from src.db import batch_insert_fts_messages, search_fts_messages + + # Batch insert mock messages + messages = [ + {"content": "How to dispatch a task into the queue", "session_id": "sess-01", "msg_idx": 1}, + {"content": "Optimizing SQLite loops with shared connections", "session_id": "sess-02", "msg_idx": 5}, + {"content": "Irrelevant content message block", "session_id": "sess-03", "msg_idx": 12} + ] + batch_insert_fts_messages(messages) + + # Query for "dispatch" + results = search_fts_messages("dispatch") + assert len(results) == 1 + assert "sess-01" in results[0][1] + assert results[0][2] == 1 + assert "dispatch" in results[0][0] + + # Query for "SQLite" + results = search_fts_messages("SQLite") + assert len(results) == 1 + assert "sess-02" in results[0][1] + assert "SQLite" in results[0][0] diff --git a/wiki/Architecture.md b/wiki/Architecture.md new file mode 100644 index 0000000000..c036539b8d --- /dev/null +++ b/wiki/Architecture.md @@ -0,0 +1,62 @@ +# Architecture + +High-level layout of `timerloggedout-spec/termux-monorepo`. + +Visual overview (in-repo): `termux-ecosystem-architecture.html` +(Terminal β†’ ArchWiz / Harmonizer / DeepSeek CLI-TUI / Central Mapper / Multi-Agent β†’ DeepSeek API, local cache, workspace). + +Prefer **TOOL_INDEX** + **CONCEPT_INDEX** under `archwiz/` for tool-level truth. + +## Core automation & agents + +### deepcli/ + +DeepSeek-oriented CLI (sessions, streaming send, thinking mode, attach, fork, export). + +- Entry: `deepcli.py`, `deepapi.py`, `deepseek_proxy.py` +- Related: `deepcli-tui/`, `.deepcli/`, `deepseek-cli/` + +### termux-multi-agent/ + +Multi-agent orchestration for Termux: provision, run, patch, dashboard, Cedar MCP. + +| Path | Role | +|------|------| +| `provision_agent.py` | Agent provisioning | +| `run.py` / `run_agent.sh` | Run loop | +| `dashboard.py` | Status / control UI | +| `patch_files.py` | Patch application | +| `cedar-mcp-server.js` | CedarScript MCP server | + +### cli-synthegration/ + +Conversation synthesis: branching, export, account/token management, metrics, Chronos, Cedar bridge. + +### archwiz/ + +ArchWizard β€” indexing, provenance, recovery indices, automation cockpit. + +- Docs: `TOOL_INDEX.md`, `CONCEPT_INDEX.md`, `REFERENCE_HUB.md`, `METHODOLOGY_INDEX.md`, `PROCEDURES.md`, … +- Role: dashboard + pipeline control + +## Harmonizer, multi-AI, swarm + +| Directory | Role | +|-----------|------| +| `harmonizer-prod_cli/` | Production Harmonizer CLI | +| `harmony_hub/` | Harmony hub integration | +| `multi-ai-cli/` | Multi-model CLI surface | +| `commingle-swarm/` | Template / scavenge-only external clone | + +## Mapping & workspace + +- `central_mapper_v420.py`, `mapper_graph.py` +- `workspace/` (incl. llm_map indices) +- `sandbox/`, `src/`, `bin/`, `config/` + +## Notes + +- `refTemplates/` on `master` is largely a stub; full metadata skeleton lives on `recreate/refTemplates-skeleton`. +- Submodules: prefer selective depth-1 updates; avoid recursive `submodule update` by default. + +For recovery history and prioritized actions, see the root README and `docs/RECON.md`. diff --git a/wiki/DeepWiki-Mirror.md b/wiki/DeepWiki-Mirror.md new file mode 100644 index 0000000000..e944d063f6 --- /dev/null +++ b/wiki/DeepWiki-Mirror.md @@ -0,0 +1,57 @@ +# DeepWiki β†’ GitHub Wiki mirror + +## Source + +| Source | URL | +|--------|-----| +| Private Devin Wiki | https://app.devin.ai/org/timerloggedout-spec/wiki/timerloggedout-spec/termux-monorepo | +| Public DeepWiki | https://deepwiki.com/timerloggedout-spec/termux-monorepo | + +Devin generates structured docs (architecture, modules, diagrams). GitHub Wiki is a separate git repo (`*.wiki.git`) of Markdown pages. There is no official one-click sync; this repo uses a **folder + Action** pattern. + +## How the mirror works + +1. **Source of truth in-repo:** the `wiki/` directory (Markdown pages). +2. **Publisher:** `.github/workflows/publish-wiki.yml` runs `Andrew-Chen-Wang/github-wiki-action@v5` on pushes to `master` / `master-staging` that touch `wiki/**`, or via **workflow_dispatch**. +3. **Target:** the repository’s GitHub Wiki (`https://github.com/timerloggedout-spec/termux-monorepo/wiki`). + +### One-time bootstrap (required) + +GitHub only creates the `*.wiki.git` backend after the first wiki page exists: + +1. Open the repo β†’ **Wiki** tab. +2. Create any page (e.g. title `Home`, body `bootstrap`). +3. Merge this feature branch (or push `wiki/` to `master`). +4. Run **Actions β†’ Publish wiki β†’ Run workflow** (or push any change under `wiki/`). + +If the first Action run fails because the wiki was empty, temporarily set `strategy: init` in the workflow (force-push), run once, then switch back to `strategy: clone`. + +## Refreshing content from Devin DeepWiki + +Private Devin Wiki pages are not exposed to the public DeepWiki MCP without indexing/auth. Practical refresh paths: + +1. **Manual / browser** + Open the Devin Wiki, export or copy pages (Chrome β€œDeepWiki to Markdown” extensions exist), save as `wiki/.md`. + +2. **CLI exporters** (public DeepWiki once indexed) + - `dw2md timerloggedout-spec/termux-monorepo -o /tmp/out.md` + - Other tools: `deepwiki-to-md`, interactive exporters on GitHub. + +3. **Ask Devin** + In a Devin session: β€œExport the current wiki pages for this repo as Markdown files suitable for a GitHub Wiki (Home.md + one file per page).” Commit the result under `wiki/`. + +4. **Conventions** + - `Home.md` is the landing page (not `README.md`). + - Filenames become titles (`My-Page.md` β†’ β€œMy Page”). + - Avoid `\ / : * ? " < > |` in titles. + - Mermaid fenced blocks usually render. + - Prefer relative wiki links: `[Architecture](Architecture)`. + +## Steering Devin’s generation + +Optional repo file `.devin/wiki.json` (repo notes + optional explicit `pages` list) steers regeneration inside Devin. That does not automatically update this GitHub Wiki; re-export into `wiki/` after regenerating. + +## Related + +- Workflow: `.github/workflows/publish-wiki.yml` +- Action docs: https://github.com/Andrew-Chen-Wang/github-wiki-action diff --git a/wiki/Home.md b/wiki/Home.md new file mode 100644 index 0000000000..2b5107bc4f --- /dev/null +++ b/wiki/Home.md @@ -0,0 +1,36 @@ +# termux-monorepo + +> GitHub Wiki mirror of the Devin DeepWiki for this monorepo. + +**Live AI wiki (source of truth for generated docs):** + +- Private Devin Wiki: [app.devin.ai …/termux-monorepo](https://app.devin.ai/org/timerloggedout-spec/wiki/timerloggedout-spec/termux-monorepo) +- Public DeepWiki (if indexed): [deepwiki.com/timerloggedout-spec/termux-monorepo](https://deepwiki.com/timerloggedout-spec/termux-monorepo) + +This GitHub Wiki is kept in-repo under `wiki/` and published by `.github/workflows/publish-wiki.yml` on every push that touches `wiki/**`. + +--- + +## TL;DR + +Monorepo recovery cockpit + live project map for Termux / DeepSeek / multi-agent tooling. + +- Prefer **ArchWiz indices** for day-to-day navigation (see [Navigation](Navigation)). +- Core surfaces: `deepcli/`, `termux-multi-agent/`, `cli-synthegration/`, `archwiz/`, harmonizer / multi-AI / swarm trees. +- Recovery & refTemplates history: root `README.md` and `docs/RECON.md`. + +--- + +## Quick links + +| Page | Purpose | +|------|---------| +| [Architecture](Architecture) | Ecosystem layout and main components | +| [Navigation](Navigation) | SSOT ladder + command table | +| [DeepWiki-Mirror](DeepWiki-Mirror) | How this mirror is maintained | + +--- + +## Status + +Initial seed from repository README (2026-08). Re-export pages from Devin DeepWiki into `wiki/*.md` and push to `master` (or `master-staging`) to refresh. diff --git a/wiki/Navigation.md b/wiki/Navigation.md new file mode 100644 index 0000000000..8f35588c1a --- /dev/null +++ b/wiki/Navigation.md @@ -0,0 +1,29 @@ +# Navigation + +Single source of truth ladder when orienting in the tree. + +| Priority | Start here | What you get | +|----------|------------|--------------| +| 1 | `archwiz/TOOL_INDEX.md` | 28 tools / 7 categories | +| 2 | `archwiz/CONCEPT_INDEX.md` | Concepts + status + backlog | +| 3 | `archwiz/REFERENCE_HUB.md` | Links to manifests and maps | +| 4 | `archwiz/METHODOLOGY_INDEX.md` | Approaches tried / what stuck | +| 5 | `archwiz/PROCEDURES.md`, `ARCHWIZARD_TASKS.md` | Runbooks and tasks | +| 6 | `docs/RECON.md` | Branch/PR critique, proposals | +| 7 | `replit.md` on `critical-proposal` | Critical path / config issues | +| 8 | `_Entry+ReadMe.md` | One-line command β†’ entry table | +| 9 | `termux-ecosystem-architecture.html` | Visual ecosystem diagram | +| 10 | `refTemplates/README_RECOVERY.md` (skeleton branch) | Metadata-only restore policy | + +## Quick commands + +| What you want to do | Where you start | +|---------------------|-----------------| +| Research a file's history | `archaeo ` | +| Check impact before changing | `oracle ` | +| Make a change | `dispatch ` or `agent-shell run ` | +| Validate & promote | `validate_promotion.py` β†’ promote | +| Rebuild indices | `map-build && map-func && fore` | +| Open cockpit | `python3 archwiz/archwiz.py` | + +Also see root `README.md` and `_Entry+ReadMe.md`. diff --git a/wiki/_Sidebar.md b/wiki/_Sidebar.md new file mode 100644 index 0000000000..b30d6c5a65 --- /dev/null +++ b/wiki/_Sidebar.md @@ -0,0 +1,10 @@ +**termux-monorepo** + +- [Home](Home) +- [Architecture](Architecture) +- [Navigation](Navigation) +- [DeepWiki Mirror](DeepWiki-Mirror) + +--- + +[Devin Wiki β†—](https://app.devin.ai/org/timerloggedout-spec/wiki/timerloggedout-spec/termux-monorepo) diff --git a/workspace/llm_map/master_tasks.json b/workspace/llm_map/master_tasks.json index dc4039239a..875589ed49 100644 --- a/workspace/llm_map/master_tasks.json +++ b/workspace/llm_map/master_tasks.json @@ -689,7 +689,7 @@ "priority": "medium", "assigned_agent": "developer", "account": "primary", - "status": "pending", + "status": "done", "sandbox": "~/sandbox/arch-015", "branch_from": "root", "target_file": "",