#!/usr/bin/env node
// configure-mines-agents.mjs — one-shot maintenance.
//
// 1. Sets an accurate mission + deliverable `expected_output` contract on each
//    of the five Mines specialist agents (their hand-written system_prompts are
//    left untouched — they are already grounded). Idempotent.
// 2. Deletes the four archived `planify-*` duplicate agents that the old seed
//    loop left behind (the live `personal-*` agents are the canonical ones).
// 3. Clears any leftover `ati-planify-*` agent_template_installations rows.
//
// Usage:
//   node scripts/configure-mines-agents.mjs          # dry-run (no writes)
//   node scripts/configure-mines-agents.mjs --apply  # configure + delete

process.env.MADARX_DISABLE_INPROC_DAEMON = '1';

const APPLY = process.argv.includes('--apply');

const MINES = {
  'mines-analyst': {
    mission:
      'Guide users through the Mines module: answer questions about imported projects, surface data gaps, route specialist work, and produce cited executive summaries — never guessing numbers or geology.',
    expected_output: [
      'An English executive summary or direct answer that an investor can read cold. Required:',
      '1. A clear answer / summary up top.',
      '2. Every numeric value (grade, tonnage, depth, price) cited to its source row ID — mines_assay_samples / mines_drill_holes / mines_extracted_facts. No uncited numbers.',
      '3. Every geological, historical, or status claim cited to a mines_document_chunks.id + page number.',
      '4. An explicit "Data not imported" callout for anything the system cannot answer (name the specific data type needed) — never an estimate.',
      '5. A routing line when the request belongs to a specialist (valuation → mines-valuation-analyst, ingestion → mines-data-interpreter, market → mines-market-researcher, packaging → mines-report-packager).',
      'Spanish technical terms preserved in parentheses on first use.',
    ].join('\n'),
  },
  'mines-data-interpreter': {
    mission:
      'Ingest, parse, and classify raw mining files into structured SQL tables and the RAG document store; own data quality and provenance at the extraction layer.',
    expected_output: [
      'A Data Quality & Ingestion report (markdown) backed entirely by actual DB row counts — no inferred or interpolated numbers. Required:',
      '1. Files ingested grouped by document_category (00–22 folder taxonomy), with ambiguous classifications logged.',
      '2. Rows written per table (mines_assay_samples, mines_drill_holes, mines_document_chunks) — every data row has source_document_id; every chunk has its embedding populated before its SourceDocument is marked extracted.',
      '3. Scanned-PDF handling: OCR applied, or ocr_skipped:true logged (never silently skipped).',
      '4. Blank cells left null — no zero-fill, no neighbor-fill.',
      '5. An explicit gap list: what is missing, what blocks downstream valuation/reporting.',
      'Spanish text extracted as-is (not translated at ingestion).',
    ].join('\n'),
  },
  'mines-valuation-analyst': {
    mission:
      'Produce tiered, defensible financial valuations grounded in SQL-resident data and approved market inputs; select the tier from the data and disclose confidence.',
    expected_output: [
      'A Valuation report (markdown), in English. Required, in order:',
      '1. Chosen tier (T1 in-situ/comparable or T2 DCF) stated FIRST, with the reason — derived from mines_assumption_validate. If INSUFFICIENT_DATA: stop, emit a gap summary, produce no numbers.',
      '2. Base / downside / upside scenarios with sensitivities (price, grade, recovery, and for T2: opex, capex, discount).',
      '3. Every input tagged as either a DB row ID citation (AssaySample/DrillHole/ExtractedFact) or source:\'default_assumption\' with the default\'s source stated. Never invent resource tonnage.',
      '4. T2 DCF withheld for exploration-stage assets regardless of the request.',
      '5. A Confidence section: tier, data quality (indicative / preliminary / definitive), key uncertainties, and what would raise the confidence level.',
      'Carries a decision-support (not investment-certification) disclaimer.',
    ].join('\n'),
  },
  'mines-market-researcher': {
    mission:
      'Provide commodity market context and comparable-transaction intelligence grounded in cited, dated public sources; supply valuation inputs, not valuations.',
    expected_output: [
      'A Market Trends memo (markdown), in English. Required:',
      '1. Every price, trend statement, and comparable cited to a source URL + retrieval date — or to a mines_market_snapshots row ID.',
      '2. The data path disclosed: mines_market_snapshot tool (if enabled) vs web_search/web_fetch public sources.',
      '3. Explicit statement when market data is unavailable (provider off, rate-limited) or stale — disclose age, never substitute a silent guess.',
      '4. Comparable-transaction data drawn only from public disclosures.',
      '5. Commodity forecasts clearly separated from current prices (never presented as current).',
      'No project valuation — that is mines-valuation-analyst.',
    ].join('\n'),
  },
  'mines-feasibility-lead': {
    mission:
      'Assess how close an asset is to a Pre-Feasibility Study and produce honest PFS-readiness gap reports against the NI 43-101 / S-K 1300 / JORC rubric — never writing or fabricating a PFS, never declaring a resource or reserve the data does not contain.',
    expected_output: [
      'A PFS-readiness assessment (report_kind: pfs_readiness_report), in English. Required:',
      '1. A verdict up top: is a PFS supportable? If no Mineral Resource is declared, state plainly that a PFS cannot be produced and name the hard blocker (a maiden resource).',
      '2. Author ONLY the prose narrative slots (verdict, gap_intro, work_program, recommendation) and pass them to mines_report_generate. Every gate/section status and count is rendered by the tool from cited DB rows — never authored in prose.',
      '3. Never present a conceptual operator/exploration target or an indicative T1/T2 valuation scenario as a mineral resource or reserve.',
      '4. A critical-path gap list ordered to the G0–G5 decision gates, and a phased work program to reach PFS confidence.',
      '5. Keep the decision-support (not a PFS, not a QP opinion, not investment advice) disclaimer intact.',
      'Spanish source terms preserved in parentheses on first use.',
    ].join('\n'),
  },
  'mines-report-packager': {
    mission:
      'Compile existing Mines analysis artifacts into a final, formatted, access-controlled project package, and produce investor-facing presentations of an asset for non-technical stakeholders — composing and framing, never inventing numbers or geology.',
    expected_output: [
      'Either a mines_project_package OR a mines_investor_presentation artifact, in English.',
      'For a project package:',
      '1. Every section cites the component artifact ID it was drawn from — no copied text without its citation.',
      '2. Any section with no source artifact rendered as "Pending — [component artifact name] not yet generated" (never filled with new analysis).',
      '3. All local filesystem paths stripped; cited documents use mines_source_documents.id, not disk paths.',
      'For an investor presentation (report_kind: investor_presentation):',
      '4. Author only the prose narrative slots (hero, opportunity, findings_lead, upside_lead, risk_lead, the_ask) and pass them to mines_report_generate. Every numeric figure is rendered by the tool from cited DB rows — never authored in prose.',
      '5. Lead with the risk; never present a conceptual exploration target as a mineral resource; keep the decision-support (not investment-advice) disclaimer intact.',
      'Shared rules:',
      '6. Default ACL = private unless the user specified a different scope.',
      '7. Any external delivery (email_send or share link) confirmed with the user first; share-link expiry date (7 days) stated in the confirmation. email_send always passes through its approval banner.',
      'Spanish source terms preserved in parentheses.',
    ].join('\n'),
  },
};

const DUPES = [
  'planify-engineering-lead',
  'planify-marketing-lead',
  'planify-meeting-notes',
  'planify-personal-assistant',
];

const { getAgent, updateAgent, deleteAgent } = await import('../lib/runtime.js');
const { getDb } = await import('../lib/db.js');

console.log(`[configure-mines] mode: ${APPLY ? 'APPLY' : 'dry-run'}`);

// ── 1. Configure Mines agents ───────────────────────────────────────────────
console.log('\n[configure-mines] Mines agent configuration:');
for (const [id, cfg] of Object.entries(MINES)) {
  const existing = getAgent(id);
  if (!existing) { console.log(`  ! ${id} — NOT FOUND, skipping`); continue; }
  console.log(`  • ${id} (${existing.name})`);
  console.log(`      mission ← ${cfg.mission.slice(0, 80)}…`);
  console.log(`      expected_output ← ${cfg.expected_output.length} chars`);
  if (APPLY) {
    const res = updateAgent(id, { mission: cfg.mission, expected_output: cfg.expected_output });
    if (!res.ok) console.log(`      FAILED: ${res.error}`);
  }
}

// ── 2. Delete archived planify-* duplicates ─────────────────────────────────
console.log('\n[configure-mines] Duplicate deletion:');
for (const id of DUPES) {
  const existing = getAgent(id);
  if (!existing) { console.log(`  - ${id} — already gone`); continue; }
  console.log(`  • ${id} (${existing.name}, status=${existing.status})`);
  if (APPLY) {
    const res = deleteAgent(id);
    if (!res.ok) console.log(`      FAILED: ${res.error}`);
  }
}

// ── 3. Clear leftover ati-planify-* installation rows ───────────────────────
const db = getDb();
const leftover = db.prepare("SELECT id FROM agent_template_installations WHERE id LIKE 'ati-planify-%'").all();
console.log(`\n[configure-mines] leftover ati-planify-* installation rows: ${leftover.length}`);
leftover.forEach(r => console.log(`  - ${r.id}`));
if (APPLY && leftover.length) {
  db.prepare("DELETE FROM agent_template_installations WHERE id LIKE 'ati-planify-%'").run();
}

console.log(`\n[configure-mines] ${APPLY ? 'done.' : 'dry run — pass --apply to write.'}`);
