ktg-plugin-marketplace/plugins/ai-psychosis/commands/interaction-report.md
Kjell Tore Guttormsen 297867f847 feat: add ai-psychosis plugin to open marketplace
Meta-awareness tools for healthy AI interaction patterns.
Detects reinforcement loops, scope escalation, and compulsive patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 20:46:09 +02:00

256 lines
7.8 KiB
Markdown

---
name: interaction-report
description: Interaction pattern report from Layer 2 session data
argument-hint: "[weekly|monthly|all]"
allowed-tools: [Read, Bash, Glob]
---
# Interaction Awareness Report
You are generating an interaction awareness report from JSONL session data.
## Step 1 — Layer guard
Read the file `.claude/ai-psychosis.local.md` in the current working
directory. If the file does not exist, or if its YAML frontmatter does not
contain `layer3: true`, stop and output:
```
Layer 3 (reports) is not enabled for this project.
To enable, create `.claude/ai-psychosis.local.md`:
---
layer2: true
layer3: true
layer4: false
---
Then restart Claude Code.
```
Do not continue past this step if Layer 3 is not enabled.
Also note the value of `layer4` (true or false) — you will need it in Step 9.
## Step 2 — Parse arguments
The time period is determined by `$ARGUMENTS`:
| Argument | Period | Cutoff |
|----------|--------|--------|
| *(empty)* | Last 7 days | Today minus 7 days |
| `weekly` | Last 7 days | Today minus 7 days |
| `monthly` | Last 30 days | Today minus 30 days |
| `all` | All data | No cutoff |
If `$ARGUMENTS` is anything else, output:
```
Usage: /interaction-report [weekly|monthly|all]
weekly Last 7 days (default)
monthly Last 30 days
all All recorded data
```
## Step 3 — Locate data files
Run via Bash: `echo $CLAUDE_PLUGIN_DATA`
If the result is empty, use the fallback path `~/.claude/plugins/data/ai-psychosis`.
Check that both files exist:
- `{data_dir}/sessions.jsonl`
- `{data_dir}/events.jsonl`
If neither file exists, output:
```
No interaction data found.
Layer 2 (programmatic detection) collects data during active sessions.
Ensure Layer 2 is enabled and use Claude Code normally — data accumulates
automatically. Then run /interaction-report again.
```
If only `events.jsonl` is missing, proceed with sessions data only and note
"Tool usage data not available" in the report.
## Step 4 — Read data
### Size check
Run via Bash: `wc -l {data_dir}/sessions.jsonl {data_dir}/events.jsonl 2>/dev/null || true`
If a file does not exist, skip it and treat its line count as 0.
### Read sessions.jsonl
If the file has fewer than 1000 lines, read the entire file.
If larger, read the last 1000 lines (via Bash: `tail -n 1000 {data_dir}/sessions.jsonl`).
### Read events.jsonl
If the file has fewer than 5000 lines, read the entire file.
If larger and period is `weekly`: read the last 5000 lines.
If larger and period is `monthly` or `all`: read the last 10000 lines and note
"Events data sampled (last N entries)" in the report.
## Step 5 — Parse and filter records
### sessions.jsonl record types
The file contains two record types interleaved:
**Start records** — have `hour` and `is_late_night`, but NO `end` or `duration_min`:
```json
{"session_id":"abc","start":"2026-04-05T10:00:00Z","hour":10,"is_late_night":false}
```
**End records** — have `end`, `duration_min`, `tool_count`, `edit_count`, `flags`:
```json
{"session_id":"abc","start":"2026-04-05T10:00:00Z","end":"2026-04-05T11:35:00Z","duration_min":95,"tool_count":47,"edit_count":12,"flags":{"dependency":2,"escalation":0,"fatigue":1,"validation":1}}
```
**Error records** — have `note: "no_state_file"`. Ignore these.
### Filtering
For the selected time period, filter records where the `start` field is
greater than or equal to the cutoff date string (ISO timestamps sort
lexicographically — string comparison works correctly).
Separate start records from end records:
- **End records** (have `duration_min`): use for duration, tools, flags
- **Start records** (have `is_late_night`): use for late-night count
### events.jsonl
Filter events where `ts` >= cutoff date string. Group by `tool_name` and count.
## Step 6 — Compute statistics
From **end records**:
- Total sessions (count of end records in period)
- Average session duration (`sum(duration_min) / count`)
- Total tool calls (`sum(tool_count)`)
- Average edit ratio (`sum(edit_count) / sum(tool_count) * 100`, as percentage)
- Flag totals: `sum(flags.dependency)`, `sum(flags.escalation)`, `sum(flags.fatigue)`, `sum(flags.validation)`
- Average flags per session for each category
From **start records**:
- Late-night sessions: count where `is_late_night` is true
From **events.jsonl**:
- Tool usage: group by `tool_name`, count occurrences, sort descending
- Show top 10 tools
**Trend comparison** (weekly and monthly only):
- Compute the same metrics for the PREVIOUS period of equal length
- Calculate the delta (current minus previous)
If previous period has zero sessions, skip the trend section.
**Sessions without matching end records** are incomplete — count them separately
as "incomplete sessions" and exclude from duration/flag averages.
## Step 7 — Format report
Output the report as markdown. Use this exact structure:
```
## Interaction Awareness Report
**Period:** {start_date} to {end_date} ({N} days)
**Sessions:** {N} completed ({N} incomplete)
**Data source:** {path}
### Overview
| Metric | Value |
|--------|-------|
| **Sessions** | {N} |
| **Avg duration** | {N} min |
| **Total tool calls** | {N} |
| **Avg edit ratio** | {N}% |
| **Late-night sessions** | {N} |
### Pattern Flags
| Pattern | Total | Per session |
|---------|-------|-------------|
| Dependency language | {N} | {avg} |
| Escalation language | {N} | {avg} |
| Fatigue signals | {N} | {avg} |
| Validation-seeking | {N} | {avg} |
### Tool Usage (top 10)
| Tool | Count | % |
|------|-------|---|
| {name} | {N} | {pct}% |
### Daily Activity
| Date | Sessions | Total duration | Flags |
|------|----------|----------------|-------|
| {date} | {N} | {N} min | {summary} |
### Trend vs previous {period}
| Metric | Previous | Current | Delta |
|--------|----------|---------|-------|
| Sessions | {N} | {N} | {+/-N} |
| Avg duration | {N} min | {N} min | {+/-N} |
| Flags (total) | {N} | {N} | {+/-N} |
### Observations
- {data-driven observation}
- {data-driven observation}
```
## Step 8 — Tone and privacy rules
**MANDATORY:**
- Neutral, observational tone. You are presenting data, not making judgments.
- Never use words like "concerning", "worrying", "problematic", or "unhealthy".
- Never use emoji.
- Never speculate about what the user was doing or thinking.
- Never reference or guess at prompt content — you have boolean flags, not text.
- This is a mirror, not a diagnosis. Present the numbers and let the user
interpret them.
- Observations section: state facts derived from data only. Examples:
- "3 of 12 sessions were between 23:00 and 05:00"
- "Dependency language flags appeared in 7 of 12 sessions"
- "Edit ratio averaged 8%, below the 10% threshold in 5 sessions"
- If all metrics are within normal ranges, say so plainly:
"All metrics within normal ranges for the reporting period."
- Omit any section that has no data (e.g., skip Trend if no previous period,
skip Tool Usage if events.jsonl was missing).
## Step 9 — Contemplative reference (conditional)
This step applies ONLY when BOTH conditions are met:
1. `layer4: true` was noted in Step 1
2. Total flags (dependency + escalation + fatigue + validation) >= 5, OR fatigue flags >= 2
If both conditions are met, append this exact paragraph to the report.
**Do not modify, paraphrase, abbreviate, or add commentary to this text:**
```
### A note from the plugin author
The patterns above are structural — they emerge from the interaction itself,
not from individual weakness. If you find yourself wanting to understand the
mechanics of your own mind more deeply, the
[Miracle of Mind](https://isha.sadhguru.org/global/en/miracle-of-mind)
program by Sadhguru offers a structured approach. This is what works for me.
It is not a recommendation — just a pointer.
```
If either condition is not met, omit this section entirely. Do not mention
Layer 4, do not explain why the section was omitted.