Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
d1ebc16
test(docs): pin the docs-vs-prompts sync and the retired-model phrase…
ahueb Aug 12, 2026
6db09f9
feat(engine): narrow the post-type vocabulary to pitch + assessment; …
ahueb Aug 12, 2026
274a773
test(engine): make the terminal_only tests discriminating
ahueb Aug 12, 2026
8a94611
feat(engine)!: remove the GrantBot/FOA surface (modules, tool, channe…
ahueb Aug 12, 2026
24e62c8
feat(engine): ex-funding threads follow the normal participation rule
ahueb Aug 12, 2026
4c1349c
feat(engine): drop FOA plumbing and the funding_only surgery from pro…
ahueb Aug 12, 2026
49a4a86
feat(engine)!: remove funding-thread logic and the phase-5 reply acti…
ahueb Aug 12, 2026
e1ee5bb
fix(migrate): bump preflight DEFAULT_TARGET to 0026 alongside the dro…
ahueb Aug 12, 2026
2b133b0
fix(prompts): pitch-era private-profile synthesis and PI-DM examples
ahueb Aug 12, 2026
707b337
fix(engine): purge the collaboration-preferences contract from the ll…
ahueb Aug 12, 2026
b41e14f
docs(plans): blackbird pitch-only deploy checklist
ahueb Aug 12, 2026
beeaec6
feat(engine)!: delete the memo/checkmark proposal lifecycle and priva…
ahueb Aug 12, 2026
bb2fc06
fix(tests): bump the harness-smoke head-revision pin to 0026
ahueb Aug 12, 2026
855b689
feat(engine): hub auto-activates an interview thread on every lab top…
ahueb Aug 12, 2026
19ed653
docs(plans): label the moneybag-closure script dry-run-first in the c…
ahueb Aug 12, 2026
8e3d45d
feat(engine): own-paper abstract lookups are uncapped; pitch-aware ow…
ahueb Aug 12, 2026
7806c1a
feat(engine): skip phase 2 in code; one pitch per day for labs
ahueb Aug 12, 2026
99b2b6b
docs(engine): correct the stale skip-streak comment after the private…
ahueb Aug 12, 2026
667f5fb
feat(engine): PI tags shape the next pitch instead of a dead reply path
ahueb Aug 12, 2026
1676a17
test(engine): pin the hub auto-activation already-active guard with a…
ahueb Aug 12, 2026
9001884
feat(engine): fail fast at startup when cohorts are not star-shaped
ahueb Aug 12, 2026
27b7fad
Merge branch 'b2-harnessfix' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
fa21fb5
Merge branch 'b2-task15' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
28fbcbc
Merge branch 'b2-task13' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
a23ab0c
Merge branch 'b2-taskgap' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
46a1d61
Merge branch 'b2-task8' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
9e4217c
Merge branch 'b2-task9' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
7fee69e
Merge branch 'b2-task11' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
b68fef0
Merge branch 'b2-task12' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
6c7f7b1
fix(engine): post-merge coherence — pi-flag test stubs, appears-below…
ahueb Aug 12, 2026
8374a8b
Merge branch 'b2-task10' into blackbird-engine-reconciliation
ahueb Aug 12, 2026
5b49b38
test(engine): bidirectional template-token contract; full suite green…
ahueb Aug 13, 2026
be732ff
test(characterization): regenerate golden masters for the pitch-only …
ahueb Aug 13, 2026
91af0bf
fix(tests): drop the import orphaned by the public-vs-private GM removal
ahueb Aug 13, 2026
fc94fa0
fix(migrate): support 0025 as a preflight start revision
ahueb Aug 13, 2026
ce424f2
docs(claude.md): drop the stale retrieve_foa withholding bullet
ahueb Aug 13, 2026
9c9e885
fix(email): rewrite the welcome email to the pitch-only model
ahueb Aug 13, 2026
84108d3
fix(agent): reword the memory-update prompt's clause (a) to pitch-era…
ahueb Aug 13, 2026
61e7e87
fix(agent): replace the retired mesh-era default system prompt fallback
ahueb Aug 13, 2026
9e7e8b6
test(residue): extend the collaboration-residue guard to email/agent/…
ahueb Aug 13, 2026
bd335c2
fix(tests,prompts): star-shape the live full-run fixture; drop stale …
ahueb Aug 13, 2026
252f364
chore(ci): lower the src/ lint ratchet 260 -> 249
ahueb Aug 13, 2026
f6c8755
fix(agent-page): reopen no longer creates a collab_private channel
ahueb Aug 13, 2026
5b20182
docs(design): reconcile three stale/underspecified spots in the PR34 …
ahueb Aug 13, 2026
52b07fa
Merge branch-1 removals into the engine branch (Task 4)
ahueb Aug 13, 2026
855be6a
feat(removal-cycle): Task 5 — remove private instructions + PI-intera…
ahueb Aug 13, 2026
23da58d
feat(removal-cycle): Task 6 — hub reply-only engine + assessment relo…
ahueb Aug 13, 2026
77db1da
Merge branch 'blackbird-prompt-refactor' into blackbird-engine-reconc…
ahueb Aug 13, 2026
2e4b448
feat(removal-cycle): Task 7 — delete Phase 2 engine + the interesting…
ahueb Aug 13, 2026
151c051
test(phase5): make the saturated-hub gate test actually discriminate
ahueb Aug 13, 2026
5f3bf62
feat(agent): warn when a hub's concluding reply has no persistable ve…
ahueb Aug 13, 2026
b7dcbb2
test(email): pin _handle_instruction's no-post contract
ahueb Aug 13, 2026
55822a4
fix(agent): pass phase4_guidance the reply's ordinal, not the prior c…
ahueb Aug 13, 2026
0fff649
test(agent): rework the hub-conclude warning tests for default config
ahueb Aug 13, 2026
e041caa
fix(agent): correct stale Phase-2 references; fix the missing-assessm…
ahueb Aug 13, 2026
d1ef831
fix(routers,services): remove the dead private-profile/PI-DM web rout…
ahueb Aug 13, 2026
bf6b3f1
fix(email): delete dead confirmation sender; welcome text matches the…
ahueb Aug 13, 2026
676097c
test(prompts): guard this cycle's removed phrases; drop dead pi_conte…
ahueb Aug 13, 2026
e56e63f
docs(plans): removal-cycle addendum; deploy-checklist verification si…
ahueb Aug 13, 2026
8a8fb12
test(characterization): regenerate golden masters for the removal cyc…
ahueb Aug 13, 2026
af5d652
chore(tests,ci): drop the inert private-profile fixture line; ratchet…
ahueb Aug 13, 2026
b40d04a
fix(agent,routers): complete the PI-interaction removal (C1)
ahueb Aug 13, 2026
3210867
test(profile-pipeline): align live T4 assertions to the post-removal …
ahueb Aug 13, 2026
48373fc
chore(agent,config,docs): delete daily_post_cap and message_count_off…
ahueb Aug 13, 2026
7b341dc
fix(message-log): narrow the human-row filter to bot-facing reads per…
ahueb Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,26 @@ authoritative.)
## BlackbirdBot (the scout_hub role)

BlackbirdBot screens PI ideas against `data/Blackbird_initial_priorities-criteria_v1.pdf`.
The rubric lives in **`profiles/private/blackbird.md`** (loaded per-agent from
`profiles/private/{agent_id}.md` and injected under the `## Your Private Instructions`
header that `Agent._compose_system_prompt` builds into every phase's system prompt); the
per-phase behaviour lives in `prompts/roles/scout_hub/` and `src/agent/thread_guidance.py`.
The rubric criteria and the `<assessment_json>` skeleton live directly in
`prompts/roles/scout_hub/phase4-thread-reply.md`; the per-phase behaviour otherwise lives
in `prompts/roles/scout_hub/` and `src/agent/thread_guidance.py`. As of the 2026-08-12
removal cycle (private instructions + reply-only hub), there is no runtime "private
profile" mechanism — `Agent._compose_system_prompt` no longer injects a `## Your Private
Instructions` header, and nothing reads `profiles/private/{agent_id}.md` per-agent.
**`profiles/private/blackbird.md`** is untracked and unread at runtime; archive-and-diff it
against the tracked rubric text before any deploy in case it holds content that was never
migrated (see the deploy checklist).

- **Interview guidance is per-role Python**, not a prompt: `src/agent/thread_guidance.py`.
The `pi_lab` strings there are byte-identical to the pre-refactor literals and are pinned
by `tests/characterization/__snapshots__/test_agent_turn_gm.ambr` — do not reword them,
and never run `pytest --snapshot-update` to make a mismatch go away.
- **Assessments are durable.** A `:mag:` Opportunity Assessment must carry an
`<assessment_json>` sidecar (bare JSON, *no* ``` fence — a fenced block would be parsed
as the phase-5 action and silently no-op the post). It is stripped from the Slack body
and written to `opportunity_assessments`, visible at `/admin/assessments`.
- **The hub is reply-only — it never makes a top-level post.** An Opportunity Assessment is
not a post type: it is an `<assessment_json>` sidecar carried inside the hub's CONCLUDING
reply in the interview thread (bare JSON, *no* ``` fence). It is stripped from the Slack
body before anything is posted and written to `opportunity_assessments`, visible at
`/admin/assessments`. `:mag:` names the sidecar, not a post label — it never appears on
anything a PI or another lab sees.
- **`weighted_score` is computed**, never taken from the model:
`src/services/blackbird_rubric.py`. `recommendation` (which may be
`route-to-incubation`) comes straight from the model's verdict and the computed `band`
Expand All @@ -261,7 +268,3 @@ per-phase behaviour lives in `prompts/roles/scout_hub/` and `src/agent/thread_gu
most specific terms when the full phrase misses — before that backoff existed, every
production search ANDed in domain-generic words like "inhibitor" and returned zero hits,
reported to PIs as clean novelty. An empty title search is never FTO.
- **`retrieve_foa` is withheld** from this role by `prompts/roles/scout_hub/role.toml`'s
tool allow-list. `prompts/roles/scout_hub/agent-system.md` explicitly tells the agent it
does not have this tool (so it doesn't hallucinate calling it); the phase-4 template
(`phase4-thread-reply.md`) has no need to and does not mention it either way.
46 changes: 46 additions & 0 deletions alembic/versions/0026_drop_grantbot_posted_foas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Drop grantbot_posted_foas (GrantBot/FOA surface retired)

Revision ID: 0026
Revises: 0025
Create Date: 2026-08-12 00:00:00.000000

GrantBot and the whole funding/FOA leaf surface are being removed (branch-2
engine reconciliation, Task 3). ``grantbot_posted_foas`` was its own dedicated
FOA-dedup coordination table (see 0012), not a column on a shared table, so
dropping it is a clean, isolated migration. No production data in this table
has any value once GrantBot itself is gone — it recorded only "which FOAs
were already posted."

Downgrade recreates the table exactly as 0012's upgrade() built it (4 columns,
no legacy-JSON backfill — that one-time seed step is not reproducible here).
"""

from typing import Sequence, Union

import sqlalchemy as sa

from alembic import op

revision: str = "0026"
down_revision: Union[str, None] = "0025"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.drop_table("grantbot_posted_foas")


def downgrade() -> None:
op.create_table(
"grantbot_posted_foas",
sa.Column("foa_number", sa.String(50), primary_key=True),
sa.Column(
"posted_at",
sa.DateTime(timezone=True),
server_default=sa.func.now(),
nullable=False,
),
sa.Column("channel", sa.String(100), nullable=True),
sa.Column("title", sa.Text(), nullable=True),
)
27 changes: 0 additions & 27 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,33 +109,6 @@ services:
awslogs-create-group: "true"
awslogs-region: ${AWS_REGION:-us-east-2}

grantbot:
build:
context: .
restart: unless-stopped
command: ["python", "-m", "src.agent.grantbot", "scheduler", "--run-hour", "8", "--max-per-channel", "1"]
env_file: .env
environment:
DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-copi}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-copi}
# Fail fast at `docker compose up` if no secret is provided, and default
# the process to production so the insecure default SECRET_KEY is rejected.
SECRET_KEY: ${SECRET_KEY:?Set a strong random SECRET_KEY in .env}
ENVIRONMENT: ${ENVIRONMENT:-production}
volumes:
- ./profiles:/app/profiles
- ./prompts:/app/prompts
- ./data:/app/data
depends_on:
postgres:
condition: service_healthy
logging:
driver: awslogs
options:
awslogs-group: /copi/grantbot
tag: grantbot
awslogs-create-group: "true"
awslogs-region: ${AWS_REGION:-us-east-2}

nginx:
image: nginx:1.27-alpine
restart: unless-stopped
Expand Down
12 changes: 0 additions & 12 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,5 @@ services:
profiles:
- agent

grantbot:
build: .
command: python -m src.agent.grantbot scheduler --run-hour 8 --max-per-channel 1
env_file: .env
volumes:
- .:/app
- ./profiles:/app/profiles
- ./prompts:/app/prompts
depends_on:
postgres:
condition: service_healthy

volumes:
pgdata:
Loading