---
name: update
description: |
  Apply vetted weekly Investibook update artifacts to Investibook environments.
  Use when a user asks to mark filtered TCOC tickets as manual_not_incident, or link time-correlated workspaces to incident dossiers.
  Prod updates are split into one script per input artifact.
---

# Investibook Weekly Updates

## Purpose

Use this skill after weekly export/filter/correlation artifacts have already been
generated under `exports/<date>/`.

It applies these updates:

1. Read `jira_tcoc_fliter_for_week.json` and mark the matching TCOC
   dossiers as `manual_not_incident`.
2. Read `time_standard_matches.json` and insert dossier/workspace links by
   resolving the current environment's `dossier_id` from
   `incident_dossier_issues.issue_key`.

The legacy dev script can still run both updates together. Prod updates are
intentionally decoupled:

- `investibook_prod_mark_not_incident.py` only reads
  `jira_tcoc_fliter_for_week.json`.
- `investibook_prod_link_workspaces.py` only reads
  `time_standard_matches.json`.

## Non-negotiable Rules

- Dev context:
  `arn:aws:eks:us-west-2:552185537300:cluster/devops-staging`
- Prod context:
  `arn:aws:eks:us-west-2:557537366020:cluster/devops-prod`
- Namespace is always `investibook`.
- Never add a CLI flag, environment fallback, or automatic context discovery that
  could switch a dev script to prod or a prod script to dev.
- Default execution is dry-run. Writes require explicit `--apply`.
- Use `issue_key` to resolve the current environment's `dossier_id`; do not
  trust stale `dossier_id` values from exported JSON when inserting workspace
  links.
- Stop on malformed JSON, missing files, missing backend pod, DB errors, or
  unexpected command failures.

## Quick Start

Run from the repository root:

```bash
# Legacy dev combined script.
python3 deployment/evolver/scripts/update/investibook_dev_updates.py --help

# Dry-run for exports/2026-06-01/.
python3 deployment/evolver/scripts/update/investibook_dev_updates.py 2026-06-01

# Apply both updates to dev.
python3 deployment/evolver/scripts/update/investibook_dev_updates.py 2026-06-01 --apply

# Apply only the manual_not_incident marks.
python3 deployment/evolver/scripts/update/investibook_dev_updates.py 2026-06-01 --apply --skip-workspace-links

# Apply only the workspace links.
python3 deployment/evolver/scripts/update/investibook_dev_updates.py 2026-06-01 --apply --skip-not-incident

# Prod: dry-run manual_not_incident marks only.
python3 deployment/evolver/scripts/update/investibook_prod_mark_not_incident.py 2026-06-01

# Prod: apply manual_not_incident marks only.
python3 deployment/evolver/scripts/update/investibook_prod_mark_not_incident.py 2026-06-01 --apply

# Prod: dry-run workspace links only.
python3 deployment/evolver/scripts/update/investibook_prod_link_workspaces.py 2026-06-01

# Prod: apply workspace links only.
python3 deployment/evolver/scripts/update/investibook_prod_link_workspaces.py 2026-06-01 --apply
```

The date argument selects:

```text
exports/<date>/jira_tcoc_fliter_for_week.json
exports/<date>/time_standard_matches.json
```

## Environments

- dev EKS context: `arn:aws:eks:us-west-2:552185537300:cluster/devops-staging`
- prod EKS context: `arn:aws:eks:us-west-2:557537366020:cluster/devops-prod`
- namespace: `investibook`
- backend pod: running and ready pod labeled `app=backend`
- SQLite DB path in pod: `/data/db/investibook.db`

The scripts discover the backend pod using the selected fixed context:

```bash
kubectl --context arn:aws:eks:us-west-2:552185537300:cluster/devops-staging \
  -n investibook get pods -l app=backend -o json

kubectl --context arn:aws:eks:us-west-2:557537366020:cluster/devops-prod \
  -n investibook get pods -l app=backend -o json
```

## Manual Not Incident Update

Input file:

```text
exports/<date>/jira_tcoc_fliter_for_week.json
```

Each record must contain an `issue_key`.

For each unique issue key, apply this logical update:

```sql
UPDATE incident_dossiers
SET manual_not_incident = 1,
    manual_not_incident_at = strftime('%s', 'now'),
    manual_not_incident_by = 'investibook_bot',
    updated_at = strftime('%s', 'now')
WHERE id = (
  SELECT dossier_id
  FROM incident_dossier_issues
  WHERE issue_key = :issue_key
  LIMIT 1
);
```

The implementation uses SQLite parameter binding for `issue_key`.

Prod script:

```bash
python3 deployment/evolver/scripts/update/investibook_prod_mark_not_incident.py <date> [--apply]
```

## Workspace Link Update

Input file:

```text
exports/<date>/time_standard_matches.json
```

Each record must contain:

- `issue_key`
- `workspace_id`

The exported `dossier_id` may be stale and is used only for reporting. Resolve
the current dossier from `issue_key` and apply:

```sql
INSERT OR IGNORE INTO incident_dossier_workspaces (
  dossier_id,
  workspace_id,
  created_at,
  created_by
)
SELECT
  dossier_id,
  :workspace_id,
  strftime('%s', 'now'),
  'investibook_bot'
FROM incident_dossier_issues
WHERE issue_key = :issue_key
LIMIT 1;
```

This form inserts zero rows if the `issue_key` is missing in the selected
environment.

Prod script:

```bash
python3 deployment/evolver/scripts/update/investibook_prod_link_workspaces.py <date> [--apply]
```

## Required Final Report

Report:

- selected export date and input directory
- selected context and backend pod
- dry-run or apply mode
- number of unique TCOC issue keys loaded
- manual-not-incident matched, missing, already marked, and updated counts
- number of time-standard matches loaded
- workspace link inserted, ignored/existing, and missing-issue counts
- any stale file `dossier_id` values that differ from current dev `dossier_id`
