diff --git a/.gemini/GEMINI.md b/.gemini/GEMINI.md index 13f1dee..ce9211f 100644 --- a/.gemini/GEMINI.md +++ b/.gemini/GEMINI.md @@ -81,14 +81,14 @@ BUILD_ID=$(gcloud builds list --project=propane-will-491900-m5 --limit=1 --forma gcloud builds log $BUILD_ID --project=propane-will-491900-m5 2>&1 | tail -100 # 2. Les Cloud Run-logg -gcloud logging read - 'resource.type=cloud_run_revision AND resource.labels.service_name=osvauco-agent' - --project=propane-will-491900-m5 --limit=50 --order=desc +gcloud logging read \ + 'resource.type=cloud_run_revision AND resource.labels.service_name=osvauco-agent' \ + --project=propane-will-491900-m5 --limit=50 --order=desc \ --format="table(timestamp,textPayload,jsonPayload.message)" # 3. Sjekk service-state -gcloud run services describe osvauco-agent - --project=propane-will-491900-m5 --region=us-central1 +gcloud run services describe osvauco-agent \ + --project=propane-will-491900-m5 --region=us-central1 \ --format="value(status.conditions)" ``` @@ -206,16 +206,16 @@ TOKEN=$(gcloud auth print-identity-token) curl -si $SMOKE_URL/health -H "Authorization: Bearer $TOKEN" # Auth — IAP Load Balancer opax.vauco.no (MUST use metadata server + SA token) -TOKEN=$(curl -s -H "Metadata-Flavor: Google" +TOKEN=$(curl -s -H "Metadata-Flavor: Google" \ "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=357036551735-kq8nt7ld38hfqlcfb3n52ef7tala4meo.apps.googleusercontent.com&format=full") curl -si https://opax.vauco.no/health -H "Authorization: Bearer $TOKEN" # Forventet: HTTP/2 200 # Ny Cloud Run-tjeneste: gi invoker-rettighet med en gang -gcloud run services add-iam-policy-binding [SERVICE] - --region=us-central1 - --member="serviceAccount:357036551735@cloudbuild.gserviceaccount.com" - --role="roles/run.invoker" +gcloud run services add-iam-policy-binding [SERVICE] \ + --region=us-central1 \ + --member="serviceAccount:357036551735@cloudbuild.gserviceaccount.com" \ + --role="roles/run.invoker" \ --project=propane-will-491900-m5 ``` @@ -252,8 +252,8 @@ gcloud run services add-iam-policy-binding [SERVICE] ### Bootstrap ```bash -bash <(curl -s "http://chris:$(gcloud secrets versions access latest - --secret=gitea-api-token --project=propane-will-491900-m5 +bash <(curl -s "http://chris:$(gcloud secrets versions access latest \ + --secret=gitea-api-token --project=propane-will-491900-m5 \ )@34.170.51.84:3000/chris/OSVauco/raw/branch/main/emma/setup.sh") echo 'source ~/.emma_env' >> ~/.bashrc && source ~/.emma_env @@ -302,8 +302,8 @@ Format: `ENV_VAR_NAME=SECRET_NAME:latest` Eksempel (generisk — bytt ut navn): ``` -gcloud run services update - --region= +gcloud run services update \ + --region= \ --update-secrets="VAR1=SECRET1:latest,VAR2=SECRET2:latest" ``` @@ -316,8 +316,8 @@ gcloud run services update **Gi tilgang:** ``` -gcloud secrets add-iam-policy-binding - --member="serviceAccount:" +gcloud secrets add-iam-policy-binding \ + --member="serviceAccount:" \ --role="roles/secretmanager.secretAccessor" ``` @@ -438,3 +438,13 @@ AI stopper alltid ved: - agents/core-logic/root_agent.py → samme guard - main.py → notifyemail Gmail + /voice-intent - requirements.txt → google-api-python-client (ikke sendgrid) + +--- + +## Mandatory operating protocol + +1. Read `docs/WORKING_STATE.md`. +2. Read `docs/DECISIONS.md`. +3. Follow `docs/AGENT_OPERATING_PROTOCOL.md`. +4. Run `scripts/workspace-status.sh` before proposing work. +5. Avoid mutation until explicit approval. diff --git a/docs/AGENT_OPERATING_PROTOCOL.md b/docs/AGENT_OPERATING_PROTOCOL.md new file mode 100644 index 0000000..5bbb05f --- /dev/null +++ b/docs/AGENT_OPERATING_PROTOCOL.md @@ -0,0 +1,49 @@ +# Agent Operating Protocol + +This document outlines the mandatory protocol for all agents operating within the OSVauco repository. + +## Evidence hierarchy +1. **Live platform/API state** is authoritative for runtime, IAM, build, deploy, traffic, and infrastructure state. +2. **Remote Git branch and immutable commit SHA** are authoritative for versioned repository artifacts. +3. **Local Git state** is authoritative for the current workstation checkout. +4. **`WORKING_STATE.md` and `DECISIONS.md`** communicate intended work, known status, and rationale, but do not override live verification. +5. **Chat, terminal scrollback, and agent memory** are non-authoritative context. + +## Session startup protocol +Every agent must perform the following steps at the beginning of a new session: + +1. Read `docs/WORKING_STATE.md` and `docs/DECISIONS.md`. +2. Run the approved read-only workspace status command: `bash scripts/workspace-status.sh`. +3. State the current branch, local SHA, remote SHA, any dirty files, the current objective, verified facts, blockers, and propose one single next action based on this information. +4. Wait for explicit approval from the operator before taking any action that modifies files or infrastructure. + +## Change protocol +Every agent must adhere to the following protocol when making changes: + +1. Identify the smallest possible set of files affected by the proposed change. +2. Present a concrete proposed diff or an exact, detailed plan of the changes to be made. +3. After receiving approval, execute the change. +4. Run focused, relevant tests to verify the change. Do not run unrelated tests. +5. Report the exact test commands used and their pass/fail results. +6. Commit changes in small, coherent, logical units. +7. Push commits to the remote repository only after explicit approval or as part of a pre-approved workflow. +8. Deploy changes only through the canonical, approved deployment flow and only after receiving explicit approval for the deployment itself. + +## Completion protocol +Upon completing a task, every agent must: + +1. State the exact files that were created or changed. +2. State the exact tests that were run and their results. +3. State what was *not* changed to provide clarity on the scope of the work. +4. Update `docs/WORKING_STATE.md` if the `Current objective`, `Current deployment state`, `Current blockers`, or `Next single action` have changed as a result of the work. +5. Never claim infrastructure state (e.g., "deployed") without performing a live, read-only verification command and showing the result. An agent must distinguish committed, pushed, build-created, build-succeeded, revision-created, traffic-shifted, and live-verified states. + +## Hard-stop protocol +An agent must stop all work and ask the operator for direction when any of the following conditions are met: + +- Required configuration, source code, identity, or a target branch is unknown or ambiguous. +- A proposed command would create, modify, or deploy infrastructure unexpectedly. +- A test failure occurs that is unrelated to the approved task. +- A proposed change would expand permissions, firewall rules, or security scope. +- It is suspected that an existing system or component may already solve the problem at hand. +- The requested action conflicts with the current objective or rules listed in `docs/WORKING_STATE.md` or `docs/DECISIONS.md`. diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md new file mode 100644 index 0000000..8c25dfc --- /dev/null +++ b/docs/DECISIONS.md @@ -0,0 +1,64 @@ +# Architectural Decision Log + +## D-001: Git/Gitea as the Source of Truth for Versioned Artifacts + +**Status:** Accepted + +**Date:** 2026-09-20 + +**Decision:** +Git/Gitea is the authoritative source for versioned repository artifacts: source code, committed configuration, documentation, and commit history. Remote branch state and immutable commit SHA are canonical references for code state. + +**Reason:** +To ensure consistency and avoid drift between different sources, a single, version-controlled repository must be the ultimate authority for versioned artifacts. This prevents ambiguity and provides a reliable foundation for development and auditing. Existing documentation (`.gemini/GEMINI.md`, `docs/HANDOFF.md`) already establishes this convention for code. This decision formalizes the scope of that authority. + +**Consequences:** +- All work on versioned artifacts must be committed to Gitea to be considered canonical. +- Other sources (local workstations, chat history) are considered non-authoritative for versioned artifacts. +- Automation and deployment pipelines must pull code and configuration from the Gitea repository. +- Live cloud state, including deployed revisions, traffic, build status, IAM, VPC Service Controls, and runtime configuration, must be determined through live read-only platform/API verification, not from Git alone. + +**Verification / rollback:** +- Verification: `git remote -v` should show Gitea as the `origin`. +- Rollback: Not applicable. + +## D-002: WORKING_STATE.md as Canonical Handoff + +**Status:** Proposed + +**Date:** 2026-09-20 + +**Decision:** +`docs/WORKING_STATE.md` will serve as the canonical, versioned handoff document for human and agent operators. It provides a concise, structured overview of the current project state. + +**Reason:** +The project needs a single, easily parsable document to answer critical questions about the current state of work. While `docs/HANDOFF.md` has served this purpose, a more structured format is needed to ensure clarity and reduce ambiguity for automated agents. + +**Consequences:** +- All operators (human and agent) must consult `docs/WORKING_STATE.md` at the beginning of a session. +- The file must be kept up-to-date as the project state changes. +- This document records intended and last-verified operational status, but it does not replace the need for live verification of cloud resources. + +**Verification / rollback:** +- Verification: The file exists and is readable. Agents and operators can successfully parse it to determine the project state. +- Rollback: Revert to using `docs/HANDOFF.md` as the primary handoff document. + +## D-003: Immutable Commit SHAs for Deployment + +**Status:** Accepted + +**Date:** 2026-09-20 + +**Decision:** +All deployment requests and processes must resolve a mutable branch name to an immutable 40-character commit SHA before source retrieval and build submission. + +**Reason:** +Using commit SHAs ensures that deployments are deterministic, reproducible, and auditable. A branch name can move, leading to ambiguity about what code is actually being deployed. This principle is critical for stability and security. + +**Consequences:** +- Deployment systems must be designed to work with commit SHAs, not just branch names. +- Tooling must exist to resolve a branch to its current HEAD SHA at the time of deployment. + +**Verification / rollback:** +- Verification: Inspect the implemented deploy-MCP path and build submission request once that implementation exists. Do not infer compliance solely from documentation. +- Rollback: Not applicable. This is a fundamental best practice. diff --git a/docs/WORKING_STATE.md b/docs/WORKING_STATE.md new file mode 100644 index 0000000..b52c3a2 --- /dev/null +++ b/docs/WORKING_STATE.md @@ -0,0 +1,55 @@ +# OSVauco Working State + +## Current objective +The working-state system has been created locally and is awaiting review and +commit. The next engineering objective, after this documentation commit is +approved, is to complete the safe source-to-Cloud-Build handoff for the +existing deploy MCP. + +## Code state +- **Last verified code baseline before this documentation change:** `b802a294826e0a55d19f6bf1ec6f8668f06c6783` +- **Current branch, local SHA, remote SHA, and working-tree status:** Always verify with `bash scripts/workspace-status.sh`; do not duplicate transient Git status manually in this document. + +## Verified facts +- The configured Git remote `origin` points to the project Gitea repository. Remote Gitea branch state and immutable commit SHA are the source of truth for versioned repository artifacts. +- Live cloud runtime, IAM, deployment, build, and traffic state must be verified from the relevant live platform/API; Git alone does not prove live state. + +## Current deployment state +- Live deployment state for the current branch was not verified during this documentation-only Phase 2 session. The branch is committed and pushed at the Phase 1 SHA, but committed/pushed status must not be interpreted as built, deployed, traffic-serving, or live. +- The repository documents an obsolete trigger-based deployment path. A previous read-only investigation reported no active Cloud Build triggers. This fact must be re-verified live before relying on it operationally. + +## Current blockers +- The deploy MCP source-to-Cloud-Build handoff is incomplete. The next design must safely resolve an allowed branch to an immutable commit SHA, obtain the corresponding source, submit it to the existing declarative build flow, and return an auditable build result. No Cloud Build trigger creation is approved or assumed. + +## Next single action +Perform a read-only design review of the existing deploy MCP path and its +source-to-Cloud-Build handoff. Identify the smallest safe implementation plan +that resolves an allowed branch to an immutable commit SHA, obtains only that +source, submits it to the existing declarative build flow, and returns an +auditable build result. Do not implement, deploy, change IAM, or create Cloud +Build triggers without separate explicit approval. + +## Explicit no-go actions +- Do not deploy the current branch without explicit separate deployment approval. +- Do not create a Cloud Build trigger or replacement deployment architecture. +- Do not modify IAM, VPC Service Controls, Cloud Run services, Dockerfiles, buckets, service accounts, or application behavior as part of this work. +- Do not delete, deprecate, rename, or replace existing documentation, including `docs/HANDOFF.md`, `.gemini/GEMINI.md`, and `docs/AGENT_RULEBOOK.md`. +- Do not treat Git history, WORKING_STATE, chat history, terminal output, or agent memory as proof of live cloud state. + +## Verification commands +```bash +# Check Git status +git status +git rev-parse HEAD +git remote show origin +``` + +### Optional live deployment verification +Run only when explicitly approved and when authenticated GCP access is available. +```bash +# Check for Cloud Build triggers +gcloud builds triggers list --project=propane-will-491900-m5 +``` + +## Last updated +2026-09-20 diff --git a/scripts/workspace-status.sh b/scripts/workspace-status.sh new file mode 100755 index 0000000..9f25f3a --- /dev/null +++ b/scripts/workspace-status.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +# This script provides a read-only overview of the repository's status. +# It does not modify any files, Git history, or infrastructure. + +set -euo pipefail + +# Go to the repository root. +REPO_ROOT=$(git rev-parse --show-toplevel) +cd "$REPO_ROOT" + +echo "--- Git Status ---" +# Refresh local remote-tracking metadata only. Does not change source files, history, or branches. +echo "Refreshing remote-tracking branches..." +git fetch --prune origin &> /dev/null || echo "WARN: Could not fetch from origin." + +echo "Repository root: $REPO_ROOT" + +# Get current branch +CURRENT_BRANCH=$(git branch --show-current) +echo "Current branch: $CURRENT_BRANCH" + +# Get local HEAD SHA and subject +LOCAL_HEAD_SHA=$(git rev-parse HEAD) +LOCAL_HEAD_SUBJECT=$(git log -1 --format=%s) +echo "Local HEAD: $LOCAL_HEAD_SHA ($LOCAL_HEAD_SUBJECT)" + +# --- Remote Status --- +# Check for a configured upstream branch +UPSTREAM_BRANCH=$(git rev-parse --abbrev-ref --symbolic-full-name "@{u}" 2>/dev/null || echo "") + +# Check for a remote-tracking ref matching the current branch name +MATCHING_REMOTE_REF="origin/$CURRENT_BRANCH" +REMOTE_TRACKING_REF=$(git rev-parse --verify "$MATCHING_REMOTE_REF" 2>/dev/null || echo "") + +if [ -n "$UPSTREAM_BRANCH" ]; then + echo "Configured upstream: $UPSTREAM_BRANCH" + REMOTE_REF_TO_COMPARE="$UPSTREAM_BRANCH" +else + echo "Configured upstream: unavailable" + if [ -n "$REMOTE_TRACKING_REF" ]; then + REMOTE_REF_TO_COMPARE="$MATCHING_REMOTE_REF" + else + REMOTE_REF_TO_COMPARE="" + fi +fi + +if [ -n "$REMOTE_REF_TO_COMPARE" ]; then + REMOTE_HEAD_SHA=$(git rev-parse "$REMOTE_REF_TO_COMPARE") + AHEAD_BEHIND=$(git rev-list --left-right --count "$REMOTE_REF_TO_COMPARE"...HEAD) + BEHIND=$(echo "$AHEAD_BEHIND" | cut -f1) + AHEAD=$(echo "$AHEAD_BEHIND" | cut -f2) + echo "Remote tracking ref: $REMOTE_REF_TO_COMPARE" + echo "Remote HEAD: $REMOTE_HEAD_SHA" + echo "Ahead: $AHEAD" + echo "Behind: $BEHIND" +else + echo "Remote tracking ref: unavailable" + echo "Remote HEAD: unavailable" + echo "Ahead: unavailable" + echo "Behind: unavailable" +fi + +echo "" +echo "--- Working Tree Status ---" +git status --short + +echo "" +echo "--- Last 5 Commits (current branch) ---" +git log -5 --oneline --decorate + +echo "" +echo "--- Documentation State ---" +if [ -f "docs/WORKING_STATE.md" ]; then + echo "- WORKING_STATE.md: Present" +else + echo "- WORKING_STATE.md: Missing" +fi + +if [ -f "docs/DECISIONS.md" ]; then + echo "- DECISIONS.md: Present" +else + echo "- DECISIONS.md: Missing" +fi + +if [ -f "docs/AGENT_OPERATING_PROTOCOL.md" ]; then + echo "- AGENT_OPERATING_PROTOCOL.md: Present" +else + echo "- AGENT_OPERATING_PROTOCOL.md: Missing" +fi