# Repository Guidelines

## Project Structure & Module Organization
This repo is a TypeScript CLI for fetching Jira issues, classifying them with Gemini, and loading to BigQuery.
Core source lives in `lib/` (CLI entry, Jira fetch, AI classification, BigQuery upload). Build output goes to `dist/`.
The CLI entry point is `bin/cli.js` for the packaged command.
Operational assets live in `prompt/` (LLM prompts) and `sql/` (BigQuery schema).
Automation scripts are in `scripts/` (e.g., `local-sync.sh`, test helpers).
Docs and integrations live in `docs/` and `larkbot/`.
Generated artifacts are commonly stored under `reports/`, `temp/`, or `test-output/`; keep large JSON outputs out of commits.

## Ticket Classification Standards
This repo uses a **multi-dimensional** ticket classification system. Each dimension answers a different question and is filled at a different time.

- `Problem Pattern` (L1/L2): symptom-level technical pattern, filled at creation/triage.
- `Issue Type`: user intent (why they contacted us), filled at creation/triage.
- `Problem Domain`: business scenario (what they were doing), array field, filled at creation/triage.
- `Root Cause` (L1/L2/L3): technical root cause, filled at resolution.
- `Service Type`: service depth delivered, filled at resolution.
- `Effort Hours`: workload estimate, filled at resolution.
- `Wetech Classification`: Wetech team's 3-level classification (L1: Category, L2: Domain, L3: Type), filled at resolution.

### Dimension Configuration (Single Source of Truth)
All classification dimensions are defined in `lib/dimensions.ts`. This is the **single source of truth** for:
- Dimension metadata (ID, name, structure type, levels)
- Enum values with rich descriptions and examples
- AI field names and verified field names
- Field relationships (is_verified, verified_at)
- Prompt instructions for AI classification
- Hierarchical structures (L1 → L2 → L3 trees)

**To add a new dimension or modify existing ones, only edit `lib/dimensions.ts`.**
The following are auto-generated from this configuration:
- Zod schemas (`lib/schema-generator.ts`)
- BigQuery MERGE SQL (`lib/sql-builder.ts`)
- Verified field merge logic (`lib/merge-utils.ts`)
- System prompts (`lib/prompt-generator.ts`)

### Architecture: Single Maintenance Point
The codebase follows a "single source of truth" architecture:

1. **`lib/dimensions.ts`**: Contains all dimension definitions with:
   - Value enums and descriptions
   - Detailed descriptions for AI prompts
   - Examples and keywords for classification
   - Hierarchical structures (L1/L2/L3 trees)

2. **`lib/prompt-generator.ts`**: Dynamically generates system prompts from dimensions.ts

3. **`context/category_*.md`**: Human-readable documentation for AI agents to query. These docs describe the classification standards and are derived from dimensions.ts.


### How to Add a New Classification Dimension

**Step 1: Edit `lib/dimensions.ts`**

Add a new entry to the `DIMENSIONS` object:

```typescript
// Flat dimension with rich descriptions
new_dimension: {
  id: "new_dimension",
  name: "New Dimension",
  structure: "flat",        // or "hierarchical" for L1/L2/L3
  isArray: false,           // true if multiple values allowed
  levels: 1,                // 1 for flat, 2-3 for hierarchical
  aiField: "ai_predicted_new_dimension",
  verifiedField: "verified_new_dimension",
  isVerifiedField: "new_dimension_is_verified",
  verifiedAtField: "new_dimension_verified_at",
  zodType: "enum",
  description: "Short description",
  promptInstruction: "Detailed instruction for AI classification",
  classifyAt: "creation" | "triage" | "resolution",
  audience: "Support, Engineering",
  applicableProjects: ["ST", "APID"],  // Optional: restrict to specific projects
  values: [
    {
      value: "option_a",
      description: "Short description",
      detailedDescription: "Detailed explanation for AI prompt",
      examples: ["Example user statement 1", "Example 2"],
      keywords: ["keyword1", "keyword2"],
    },
  ],
  // For hierarchical dimensions, add:
  hierarchy: [
    {
      value: "l1_value",
      description: "L1 description",
      children: [
        { value: "l2_value", description: "L2 description" },
      ],
    },
  ],
},
```

**Project-Specific Dimensions:**
Some dimensions only apply to certain Jira projects. Use `applicableProjects` to restrict:
- If `applicableProjects` is not set or empty → applies to all projects
- If set (e.g., `["ST", "APID"]`) → only applies to those projects

Helper functions in `lib/dimensions.ts`:
- `isDimensionApplicable(dimId, projectKey)` - Check if dimension applies to project
- `getDimensionsForProject(projectKey)` - Get all dimensions for a project
- `getUniversalDimensions()` - Get dimensions that apply to all projects
- `getProjectSpecificDimensions()` - Get map of restricted dimensions and their projects

**Step 2: Update BigQuery Schema**

Add corresponding columns to `sql/ticket_schema.sql`:
```sql
-- AI predicted field
ai_predicted_new_dimension STRING,
-- Verified fields
verified_new_dimension STRING,
new_dimension_is_verified BOOL DEFAULT FALSE,
new_dimension_verified_at TIMESTAMP,
```

**Step 3: Update `transformIssueForBigQuery` in `lib/csv.ts`**

Add the new fields to the return object:
```typescript
ai_predicted_new_dimension: issue.ai_predicted_new_dimension || "",
verified_new_dimension: null,
new_dimension_is_verified: false,
new_dimension_verified_at: null,
```

**Step 4: Validate**
```bash
pnpm test                      # Run unit tests
pnpm exec tsc --noEmit         # Type check
./scripts/validate-local.sh    # End-to-end dry run
```

**Step 5: Deploy BigQuery Schema Change**

Run the ALTER TABLE or recreate the table in BigQuery before deploying code.

References (definitions and full tables):
- [context/category_design.md](context/category_design.md)
- [context/category_problem.md](context/category_problem.md)
- [context/category_root_cause.md](context/category_root_cause.md)
- [context/category_issue_type.md](context/category_issue_type.md)
- [context/category_service_type.md](context/category_service_type.md)
- [context/category_problem_domain.md](context/category_problem_domain.md)
- [context/category_wetech.md](context/category_wetech.md)
- [context/data_schema_design.md](context/data_schema_design.md)

## Build, Test, and Development Commands
- `pnpm install`: install dependencies (Node 22.x, pnpm 10.x).
- `pnpm build`: compile TypeScript into `dist/`.
- `pnpm watch`: watch mode type-checking without emitting.
- `pnpm exec tsc --noEmit`: type-check only.
- `pnpm exec biome check .`: lint the codebase.
- `pnpm exec biome format --write .`: auto-format.
- `pnpm exec tsx lib/cli.ts <cmd>`: run the CLI in dev (see README for `fetch`, `classify`, `merge`, `upload`).
- `./scripts/local-sync.sh`: run the end-to-end daily sync locally.

## Coding Style & Naming Conventions
Use the existing TypeScript style: ES module imports, 2-space indentation, double quotes, and semicolons.
Prefer small, single-purpose functions; avoid deep nesting.
Naming: `camelCase` for functions/variables, `PascalCase` for types/classes, and `kebab-case` for scripts.
Run Biome before committing to keep formatting consistent.

## Testing Guidelines
Unit tests live in `test/` and use Vitest. Run with:
- `pnpm test`: run all tests once
- `pnpm test:watch`: watch mode for development

Key test files:
- `test/dimensions.test.ts`: validates dimension configuration integrity
- `test/schema-generator.test.ts`: ensures generated schemas match hardcoded ones
- `test/sql-builder.test.ts`: verifies SQL field lists and MERGE generation
- `test/merge-utils.test.ts`: tests verified field merging logic

For new logic, add a small script or CLI smoke test that exercises the change with `--dry-run` where possible.
Use `./scripts/validate-local.sh` for end-to-end validation without uploading to BigQuery/Feishu.

## Commit & Pull Request Guidelines
Commit messages follow Conventional Commits (e.g., `refactor: ...`, `fix: ...`, `chore: ...`).
PRs should include: a short rationale, impact on the Jira to BigQuery pipeline, and any schema changes in `sql/`.
If outputs change, attach a small sample or `--dry-run` output excerpt.

## Security & Configuration Tips
Do not commit `.env` or credential files. Required env vars include `JIRA_*`, `GOOGLE_GENERATIVE_AI_API_KEY`,
and BigQuery auth (`GOOGLE_APPLICATION_CREDENTIALS` or CI OIDC). Keep API keys out of logs and artifacts.
