// retoor <retoor@molodetz.nl>
export const meta = {
  name: 'devii-tool',
  description: 'Add a Devii agent capability: an Action in the catalog with auth flags matched to the route guard, dispatcher wiring, API docs, then verify role-gating and confirmation and write the api-tier integration test for the action',
  phases: [
    { title: 'Understand', detail: 'find the underlying route and a similar Action to mirror' },
    { title: 'Implement', detail: 'add the Action, wire the handler, document it' },
    { title: 'Verify', detail: 'role-gating, flag alignment, and confirm gating' },
    { title: 'Fix', detail: 'close gaps from the review' },
    { title: 'Test', detail: 'write the api-tier integration test for the action (visibility, auth gating, confirm)' },
  ],
}

const RULES = [
  'Obey DevPlace hard rules while editing:',
  '- No comments or docstrings in source except the file header and the @tool docstring required for a tool schema. New files start with the "retoor <retoor@molodetz.nl>" header.',
  '- No em-dash characters; use a hyphen. Full Python type hints; pathlib over os.',
  '- A Devii Action requires_auth/requires_admin MUST exactly match the underlying route guard. Never grant a member an admin capability. A non-admin must not even see an admin tool schema.',
  '- If the action is irreversible or destructive, add it to dispatcher CONFIRM_REQUIRED and declare a confirm boolean param in its spec (schemas set additionalProperties:false, so a gated tool without a declared confirm param can never receive confirm=true and loops forever).',
  '- Prefer handler="http" reusing an existing REST route; only add a local controller handler when there is no route. Reuse the arg()/body()/query()/confirm() helpers for params.',
  '- Validate with the per-language checks (py_compile + pyflakes for Python, node --check for JS, brace balance for CSS, tag and {% %} balance for templates) and "python -c \\"from devplacepy.main import app\\"". NEVER run the test suite. Never perform any git write.',
].join('\n')

const TESTS = [
  'DevPlace test standard (a hard project requirement - one test file per endpoint, the directory tree mirroring the URL path):',
  'A Devii tool is reached over the same HTTP surface a user hits, so its test lives in tests/api/ (often tests/api/devii/), against the live uvicorn subprocess (app_server/seeded_db, requests/httpx vs BASE_URL).',
  'Cover the role-gating that is the whole point of the tool: an unauthenticated/guest caller is refused, a member sees and can call a requires_auth tool but is refused a requires_admin one (and its schema is withheld), an admin can call it, and a destructive action is refused without confirm=true and proceeds with it.',
  'Required patterns: scoped assertions; try/finally restore of any flipped global setting; the shared fixtures (alice, bob, app_server); test FUNCTIONS are test_-prefixed though files are not. Validate by a clean import only. NEVER run the suite.',
].join('\n')

function toolBrief() {
  if (!args) return ''
  if (typeof args === 'string') return args
  if (typeof args.description === 'string') return args.description
  return JSON.stringify(args)
}

const ask = toolBrief()
if (!ask) {
  log('No tool description provided. Invoke as /devii-tool <what the tool should do>.')
  return { error: 'no description provided' }
}

const MAP_SCHEMA = {
  type: 'object',
  additionalProperties: false,
  required: ['summary'],
  properties: {
    summary: { type: 'string' },
    underlyingRoute: { type: 'string' },
    routeGuard: { type: 'string' },
    similarAction: { type: 'string' },
    handler: { type: 'string' },
    destructive: { type: 'boolean' },
  },
}

const BUILD_SCHEMA = {
  type: 'object',
  additionalProperties: false,
  required: ['summary', 'filesChanged', 'validatorPassed'],
  properties: {
    summary: { type: 'string' },
    actionName: { type: 'string' },
    filesChanged: { type: 'array', items: { type: 'string' } },
    validatorPassed: { type: 'boolean' },
    importOk: { type: 'boolean' },
  },
}

const FINDINGS_SCHEMA = {
  type: 'object',
  additionalProperties: false,
  required: ['summary', 'findings'],
  properties: {
    summary: { type: 'string' },
    findings: {
      type: 'array',
      items: {
        type: 'object',
        additionalProperties: false,
        required: ['severity', 'file', 'rule', 'message'],
        properties: {
          severity: { type: 'string', enum: ['error', 'warning', 'info'] },
          file: { type: 'string' },
          line: { type: 'integer' },
          rule: { type: 'string' },
          message: { type: 'string' },
        },
      },
    },
  },
}

log(`Devii tool: ${ask}`)

const map = await agent(
  `Find the underlying REST route this Devii tool should call (or determine it needs a local controller handler), its exact auth guard, and the most similar existing Action in services/devii/actions/catalog.py to mirror. Note whether the action is destructive. Do not write anything.\n\nTool request: ${ask}`,
  { agentType: 'Explore', label: 'understand', phase: 'Understand', schema: MAP_SCHEMA }
)

const build = await agent(
  `Add this Devii tool, editing files directly in the repo. Add the Action to the catalog mirroring the similar action, set requires_auth/requires_admin to exactly match the underlying route guard, wire the dispatcher handler if a new local handler is needed, and add a docs_api.py entry if it wraps an HTTP endpoint. If destructive, add it to CONFIRM_REQUIRED and declare a confirm param. Then run the per-language checks (py_compile + pyflakes for Python, node --check for JS, brace balance for CSS, tag and {% %} balance for templates) and "python -c \\"from devplacepy.main import app\\"". Do not write the test here. Do not run the suite. Do not commit.\n\nTool request: ${ask}\n\nContext:\n${JSON.stringify(map, null, 2)}\n\n${RULES}\n\nReturn the action name, files changed, and whether the checks and the import passed.`,
  { label: 'implement', phase: 'Implement', schema: BUILD_SCHEMA }
)

const changed = (build && build.filesChanged) || []
const scopeNote = changed.length ? `\n\nRestrict findings to these files:\n${changed.join('\n')}` : ''

const audits = await parallel(
  [
    { key: 'devii', agent: 'devii-maintainer' },
    { key: 'security', agent: 'security-maintainer' },
  ].map((a) => () =>
    agent(
      `Operate in REPORT mode (read-only). Audit the new Devii tool for your single dimension: confirm the auth flags match the route guard, no admin schema leaks to a non-admin, and any destructive action has both CONFIRM_REQUIRED membership and a declared confirm param.${scopeNote}\n\nTool request: ${ask}`,
      { agentType: a.agent, label: `verify:${a.key}`, phase: 'Verify', schema: FINDINGS_SCHEMA }
    ).then((r) => ({ key: a.key, findings: (r && r.findings) || [] }))
  )
)

const gaps = audits
  .filter(Boolean)
  .flatMap((r) => r.findings.map((f) => ({ dimension: r.key, ...f })))
  .filter((f) => f.severity !== 'info')

let gapFix = 'no actionable gaps'
if (gaps.length) {
  gapFix = await agent(
    `Close these Devii tool gaps with minimal root-cause fixes in the repo, then re-run the per-language checks. Do not run the suite. Do not commit.\n\nGaps:\n${JSON.stringify(gaps, null, 2)}\n\n${RULES}`,
    { label: 'fix-gaps', phase: 'Fix' }
  )
}

const test = await agent(
  `Operate in FIX mode. Write the integration test for this Devii tool following the required patterns (tests/api/devii layout), asserting the role-gating and confirm behavior described below. The tool is not complete until its gating is tested. Create any missing package directories the test path needs. Validate by a clean import only. NEVER run the suite.\n\n${TESTS}\n\nTool request: ${ask}\nAction: ${build && build.actionName}\nFiles changed:\n${changed.join('\n')}\n\nReturn the test file written and the gating cases it covers.`,
  { agentType: 'test-maintainer', label: 'test', phase: 'Test' }
)

return { ask, map, build, audit: gaps, gapFix, test }
