Skip to content

Work Classifier

The work classifier determines the domain of a Work Unit using weighted signals from code paths, lane names, WU type, and description keywords. It returns abstract capability tags and test methodology hints for vendor-agnostic integration.

Framework-specific file conventions are treated as optional signals, not baseline truth. LumenFlow ships generic UI patterns such as stylesheets, components/, and pages/; if your repo relies on framework-specific directories such as Next.js app-router files, declare them through methodology.work_classification.ui.code_path_patterns.

Classify the work domain from multiple weighted signals.

Parameters:

ParameterTypeDescription
docobjectWU document with code_paths, lane, type, description
configWorkClassificationConfigOptional config to extend default patterns

Returns: WorkClassification

import { classifyWork, WORK_DOMAINS } from '@lumenflow/core';

const result = classifyWork({
  code_paths: ['src/components/Button.tsx'],
  lane: 'Framework: Core',
});
// { domain: 'ui', confidence: 1.0, signals: [...], capabilities: [...], testMethodologyHint: 'smoke-test' }
interface WorkClassification {
  /** Detected work domain: 'ui' | 'backend' | 'docs' | 'infra' | 'mixed' */
  domain: WorkDomain;
  /** Confidence score (max signal weight, 0 if no match) */
  confidence: number;
  /** Individual signals that contributed to classification */
  signals: WorkSignal[];
  /** Abstract capability tags (NOT client skill names) */
  capabilities: string[];
  /** Test methodology hint, e.g. 'smoke-test' for UI work */
  testMethodologyHint?: string;
}
interface WorkSignal {
  source: string; // 'code_paths' | 'lane' | 'type' | 'description'
  domain: WorkDomain;
  weight: number;
  match: string; // The pattern or keyword that matched
}
SignalWeightDescription
code_paths1.0Glob pattern matching against file paths
lane0.6Lane parent/sublane name matching
type0.3WU type field (e.g., documentation)
description0.2Keyword matching in description text

Confidence = max(matched signal weights), not sum. Domain is assigned only when confidence >= 0.3.

const WORK_DOMAINS = {
  UI: 'ui',
  BACKEND: 'backend',
  DOCS: 'docs',
  INFRA: 'infra',
  MIXED: 'mixed',
};
const SIGNAL_WEIGHTS = {
  CODE_PATHS: 1.0,
  LANE: 0.6,
  TYPE: 0.3,
  DESCRIPTION: 0.2,
};

Built-in glob patterns for detecting UI work via code paths:

  • **/*.css, **/*.scss, **/*.less
  • **/*.module.css, **/*.module.scss
  • **/*.styled.ts, **/*.styled.tsx
  • **/components/**, **/pages/**

Next.js app-router patterns are intentionally not built into the default list. Add them via config when a workspace actually uses them.

Built-in lane parent hints: Experience, Frontend, UI, Design.

The classifier returns abstract capability tags (not client-specific skill names):

DomainCapabilities
uiui-design-awareness, component-reuse-check
docsdocumentation-structure, link-validation
infrainfrastructure-review, security-check
mixedcross-domain-awareness
backend(none)

Extend default patterns via methodology.work_classification in workspace.yaml. Custom values extend the built-in defaults; they do not replace them.

methodology:
  work_classification:
    ui:
      code_path_patterns:
        - 'src/widgets/*.tsx'
        - 'src/views/**'
        - 'app/**/page.tsx'
        - 'app/**/layout.tsx'
      lane_hints:
        - 'Design'
        - 'Visual'
interface WorkClassificationConfig {
  ui?: {
    /** Additional glob patterns (extend defaults) */
    code_path_patterns?: string[];
    /** Additional lane hints (extend defaults) */
    lane_hints?: string[];
  };
}

The classifier emits methodology hints as recommendations for prompt composition. They are not a hardcoded software-engineering mandate.

When the detected domain is ui and confidence >= 0.5, the classifier returns testMethodologyHint: 'smoke-test'. The default wu:brief composition uses this to prefer integration, E2E, smoke, and manual verification for UI work, while reserving unit tests for pure logic or explicitly required verification.

When every declared code path is structured content (.yaml, .yml, .json, .md, .mdx), the classifier returns testMethodologyHint: 'structured-content'. The default wu:brief composition uses this to prefer parsing, linting, schema, evaluator, and smoke evidence instead of forcing backend-style TDD.

The work classifier is wired into wu:brief generation (WU-1900) at four points:

Capabilities are mapped to client-specific skills via capabilities_map in client config:

agents:
  clients:
    claude-code:
      capabilities_map:
        ui-design-awareness: frontend-design
        component-reuse-check: library-first

When classifier capabilities match keys in the map, the corresponding skill names appear in the brief’s Soft Policy section. This keeps the classifier vendor-agnostic while allowing each client to define its own skill names.

A ## Design Context section is added to the brief for UI-classified work, with guidance on pattern checks, viewport verification, and accessibility. This section contains no /skill syntax or client-specific names.

The classifier also feeds prompt-template conditions such as work.domain and work.testMethodologyHint. The built-in defaults use those fields to include sections like visual-directive, structured-content-directive, and design-context-ui.

The constraints block’s TDD CHECKPOINT is omitted when work is classified as UI domain or methodology is none.

Backend-only repo with Next-style filenames but no configured UI signals

Section titled “Backend-only repo with Next-style filenames but no configured UI signals”
classifyWork({
  code_paths: ['app/dashboard/page.tsx'],
});
// domain: 'backend', confidence: 0
classifyWork({
  code_paths: ['apps/web/src/styles/main.css'],
  lane: 'Framework: Core',
});
// domain: 'ui', confidence: 1.0
classifyWork({
  type: 'documentation',
  code_paths: [],
});
// domain: 'docs', confidence: 0.3
classifyWork({
  code_paths: ['src/components/Header.tsx', 'docs/api.md'],
});
// domain: 'mixed', confidence: 1.0
classifyWork({
  code_paths: ['packages/core/src/utils.ts'],
});
// domain: 'backend', confidence: 0