@geraldmaron/construct 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -44
- package/agents/prompts/cx-accessibility.md +3 -3
- package/agents/prompts/cx-ai-engineer.md +7 -7
- package/agents/prompts/cx-architect.md +6 -6
- package/agents/prompts/cx-business-strategist.md +6 -6
- package/agents/prompts/cx-data-analyst.md +7 -7
- package/agents/prompts/cx-data-engineer.md +3 -3
- package/agents/prompts/cx-debugger.md +6 -6
- package/agents/prompts/cx-designer.md +5 -5
- package/agents/prompts/cx-devil-advocate.md +4 -4
- package/agents/prompts/cx-docs-keeper.md +5 -5
- package/agents/prompts/cx-engineer.md +5 -5
- package/agents/prompts/cx-evaluator.md +2 -2
- package/agents/prompts/cx-explorer.md +8 -8
- package/agents/prompts/cx-legal-compliance.md +2 -2
- package/agents/prompts/cx-operations.md +5 -5
- package/agents/prompts/cx-orchestrator.md +10 -10
- package/agents/prompts/cx-platform-engineer.md +5 -5
- package/agents/prompts/cx-product-manager.md +4 -4
- package/agents/prompts/cx-qa.md +8 -8
- package/agents/prompts/cx-rd-lead.md +9 -9
- package/agents/prompts/cx-release-manager.md +5 -5
- package/agents/prompts/cx-researcher.md +22 -22
- package/agents/prompts/cx-reviewer.md +7 -7
- package/agents/prompts/cx-security.md +10 -10
- package/agents/prompts/cx-sre.md +7 -7
- package/agents/prompts/cx-test-automation.md +3 -3
- package/agents/prompts/cx-trace-reviewer.md +8 -8
- package/agents/prompts/cx-ux-researcher.md +3 -3
- package/bin/construct +470 -4
- package/commands/build/feature.md +4 -4
- package/commands/build/fix.md +8 -8
- package/commands/design/access.md +3 -3
- package/commands/design/flow.md +3 -3
- package/commands/design/ui.md +4 -4
- package/commands/measure/experiment.md +5 -5
- package/commands/measure/metrics.md +3 -3
- package/commands/measure/results.md +4 -4
- package/commands/plan/api.md +3 -3
- package/commands/plan/challenge.md +3 -3
- package/commands/plan/decide.md +3 -3
- package/commands/plan/feature.md +7 -7
- package/commands/plan/requirements.md +3 -3
- package/commands/remember/context.md +5 -5
- package/commands/remember/handoff.md +3 -3
- package/commands/remember/runbook.md +3 -3
- package/commands/review/code.md +8 -8
- package/commands/review/quality.md +4 -4
- package/commands/review/security.md +3 -3
- package/commands/ship/ready.md +3 -3
- package/commands/ship/release.md +3 -3
- package/commands/ship/status.md +4 -4
- package/commands/understand/docs.md +3 -3
- package/commands/understand/research.md +5 -3
- package/commands/understand/this.md +4 -4
- package/commands/understand/why.md +8 -8
- package/commands/work/clean.md +14 -14
- package/commands/work/drive.md +10 -10
- package/commands/work/optimize-prompts.md +9 -9
- package/commands/work/parallel-review.md +8 -8
- package/db/schema/006_graph.sql +24 -0
- package/examples/provider-plugin/README.md +7 -7
- package/examples/seed-observations/README.md +6 -6
- package/examples/seed-observations/anti-patterns.md +14 -14
- package/examples/seed-observations/decisions.md +4 -4
- package/examples/seed-observations/patterns.md +14 -14
- package/lib/auto-docs.mjs +10 -5
- package/lib/cli-commands.mjs +45 -1
- package/lib/comment-lint.mjs +7 -1
- package/lib/config/schema.mjs +3 -0
- package/lib/flavors/loader.mjs +136 -0
- package/lib/hooks/agent-tracker.mjs +22 -3
- package/lib/hooks/pre-push-gate.mjs +14 -1
- package/lib/hooks/session-optimize.mjs +3 -2
- package/lib/hooks/session-reflect.mjs +68 -0
- package/lib/init-unified.mjs +25 -2
- package/lib/intake/classify.mjs +61 -183
- package/lib/intake/prepare.mjs +7 -0
- package/lib/intake/tables/creative.mjs +94 -0
- package/lib/intake/tables/operations.mjs +85 -0
- package/lib/intake/tables/research.mjs +85 -0
- package/lib/intake/tables/rnd.mjs +175 -0
- package/lib/knowledge/graph.mjs +213 -0
- package/lib/knowledge/research-store.mjs +109 -0
- package/lib/mcp/server.mjs +187 -1
- package/lib/mcp/tools/profile.mjs +270 -0
- package/lib/observation-store.mjs +19 -0
- package/lib/outcomes/aggregate.mjs +104 -0
- package/lib/outcomes/record.mjs +115 -0
- package/lib/parity.mjs +6 -9
- package/lib/profiles/lifecycle.mjs +388 -0
- package/lib/profiles/loader.mjs +123 -0
- package/lib/profiles/validate-custom.mjs +114 -0
- package/lib/reflect/extractor.mjs +193 -0
- package/lib/reflect.mjs +89 -2
- package/lib/sandbox.mjs +102 -0
- package/package.json +6 -1
- package/personas/construct.md +20 -20
- package/platforms/claude/CLAUDE.md +6 -6
- package/platforms/claude/settings.template.json +13 -0
- package/rules/common/agents.md +2 -2
- package/rules/common/beads-hygiene.md +11 -11
- package/rules/common/code-review.md +1 -1
- package/rules/common/coding-style.md +1 -1
- package/rules/common/comments.md +8 -8
- package/rules/common/commit-approval.md +4 -4
- package/rules/common/cx-agent-routing.md +2 -2
- package/rules/common/cx-skill-routing.md +2 -2
- package/rules/common/development-workflow.md +1 -1
- package/rules/common/doc-ownership.md +2 -2
- package/rules/common/efficiency.md +3 -3
- package/rules/common/framing.md +1 -1
- package/rules/common/git-workflow.md +1 -1
- package/rules/common/patterns.md +1 -1
- package/rules/common/performance.md +1 -1
- package/rules/common/release-gates.md +7 -7
- package/rules/common/research.md +4 -4
- package/rules/common/security.md +1 -1
- package/rules/common/skill-composition.md +8 -8
- package/rules/common/testing.md +1 -1
- package/rules/golang/coding-style.md +2 -2
- package/rules/golang/hooks.md +1 -1
- package/rules/golang/patterns.md +1 -1
- package/rules/golang/security.md +1 -1
- package/rules/golang/testing.md +1 -1
- package/rules/python/coding-style.md +1 -1
- package/rules/python/hooks.md +1 -1
- package/rules/python/patterns.md +1 -1
- package/rules/python/security.md +1 -1
- package/rules/python/testing.md +1 -1
- package/rules/swift/coding-style.md +3 -3
- package/rules/swift/hooks.md +2 -2
- package/rules/swift/patterns.md +2 -2
- package/rules/swift/security.md +4 -4
- package/rules/swift/testing.md +2 -2
- package/rules/typescript/coding-style.md +1 -1
- package/rules/typescript/hooks.md +1 -1
- package/rules/typescript/patterns.md +1 -1
- package/rules/typescript/security.md +1 -1
- package/rules/typescript/testing.md +1 -1
- package/rules/web/coding-style.md +1 -1
- package/rules/web/design-quality.md +1 -1
- package/rules/web/hooks.md +1 -1
- package/rules/web/patterns.md +1 -1
- package/rules/web/performance.md +1 -1
- package/rules/web/security.md +1 -1
- package/rules/web/testing.md +1 -1
- package/scripts/sync-agents.mjs +11 -0
- package/skills/ai/agent-dev.md +1 -1
- package/skills/ai/llm-security.md +1 -1
- package/skills/ai/ml-ops.md +6 -6
- package/skills/ai/orchestration-workflow.md +1 -1
- package/skills/ai/prompt-and-eval.md +1 -1
- package/skills/ai/prompt-optimizer.md +13 -13
- package/skills/ai/rag-system.md +1 -1
- package/skills/architecture/api-design.md +1 -1
- package/skills/architecture/caching.md +1 -1
- package/skills/architecture/cloud-native.md +1 -1
- package/skills/architecture/message-queue.md +1 -1
- package/skills/architecture/security-arch.md +1 -1
- package/skills/compliance/ai-disclosure.md +1 -1
- package/skills/compliance/data-privacy.md +1 -1
- package/skills/compliance/license-audit.md +2 -2
- package/skills/compliance/regulatory-review.md +1 -1
- package/skills/development/cpp.md +1 -1
- package/skills/development/go.md +1 -1
- package/skills/development/java.md +1 -1
- package/skills/development/kotlin.md +9 -9
- package/skills/development/mobile-crossplatform.md +13 -13
- package/skills/development/python.md +1 -1
- package/skills/development/rust.md +1 -1
- package/skills/development/shell.md +1 -1
- package/skills/development/swift.md +6 -6
- package/skills/development/typescript.md +1 -1
- package/skills/devops/ci-cd.md +5 -5
- package/skills/devops/containerization.md +9 -9
- package/skills/devops/cost-optimization.md +1 -1
- package/skills/devops/data-engineering.md +2 -2
- package/skills/devops/database.md +1 -1
- package/skills/devops/dependency-management.md +3 -3
- package/skills/devops/devsecops.md +1 -1
- package/skills/devops/git-workflow.md +1 -1
- package/skills/devops/incident-response.md +18 -18
- package/skills/devops/monorepo.md +5 -5
- package/skills/devops/observability.md +1 -1
- package/skills/devops/performance.md +1 -1
- package/skills/devops/testing.md +1 -1
- package/skills/docs/adr-workflow.md +2 -2
- package/skills/docs/backlog-proposal-workflow.md +1 -1
- package/skills/docs/customer-profile-workflow.md +1 -1
- package/skills/docs/document-ingest-workflow.md +1 -1
- package/skills/docs/evidence-ingest-workflow.md +1 -1
- package/skills/docs/init-docs.md +15 -15
- package/skills/docs/init-project.md +1 -1
- package/skills/docs/prd-workflow.md +3 -3
- package/skills/docs/prfaq-workflow.md +1 -1
- package/skills/docs/product-intelligence-review.md +1 -1
- package/skills/docs/product-intelligence-workflow.md +1 -1
- package/skills/docs/product-signal-workflow.md +9 -9
- package/skills/docs/research-workflow.md +10 -10
- package/skills/docs/runbook-workflow.md +2 -2
- package/skills/docs/strategy-workflow.md +3 -3
- package/skills/exploration/repo-map.md +11 -11
- package/skills/frameworks/django.md +15 -15
- package/skills/frameworks/nextjs.md +16 -16
- package/skills/frameworks/react.md +12 -12
- package/skills/frameworks/spring-boot.md +12 -12
- package/skills/frontend-design/accessibility.md +6 -6
- package/skills/frontend-design/component-patterns.md +1 -1
- package/skills/frontend-design/engineering.md +1 -1
- package/skills/frontend-design/state-management.md +1 -1
- package/skills/frontend-design/ui-aesthetics.md +1 -1
- package/skills/frontend-design/ux-principles.md +1 -1
- package/skills/operating/orchestration-reference.md +27 -27
- package/skills/quality-gates/review-work.md +3 -3
- package/skills/quality-gates/verify-change.md +1 -1
- package/skills/quality-gates/verify-module.md +1 -1
- package/skills/quality-gates/verify-quality.md +1 -1
- package/skills/quality-gates/verify-security.md +1 -1
- package/skills/roles/architect.ai-systems.md +4 -2
- package/skills/roles/architect.data.md +4 -2
- package/skills/roles/architect.enterprise.md +4 -2
- package/skills/roles/architect.integration.md +4 -2
- package/skills/roles/architect.md +7 -5
- package/skills/roles/architect.platform.md +4 -2
- package/skills/roles/data-analyst.experiment.md +4 -2
- package/skills/roles/data-analyst.md +9 -7
- package/skills/roles/data-analyst.product-intelligence.md +4 -2
- package/skills/roles/data-analyst.product.md +4 -2
- package/skills/roles/data-analyst.telemetry.md +4 -2
- package/skills/roles/data-engineer.pipeline.md +4 -2
- package/skills/roles/data-engineer.vector-retrieval.md +4 -2
- package/skills/roles/data-engineer.warehouse.md +4 -2
- package/skills/roles/debugger.md +7 -5
- package/skills/roles/designer.accessibility.md +4 -2
- package/skills/roles/designer.md +10 -8
- package/skills/roles/engineer.ai.md +4 -2
- package/skills/roles/engineer.data.md +5 -3
- package/skills/roles/engineer.md +14 -12
- package/skills/roles/engineer.platform.md +5 -3
- package/skills/roles/operator.docs.md +6 -4
- package/skills/roles/operator.md +6 -4
- package/skills/roles/operator.release.md +4 -2
- package/skills/roles/operator.sre.md +5 -3
- package/skills/roles/orchestrator.md +5 -3
- package/skills/roles/product-manager.ai-product.md +4 -2
- package/skills/roles/product-manager.business-strategy.md +4 -2
- package/skills/roles/product-manager.enterprise.md +4 -2
- package/skills/roles/product-manager.growth.md +4 -2
- package/skills/roles/product-manager.md +6 -4
- package/skills/roles/product-manager.platform.md +4 -2
- package/skills/roles/product-manager.product.md +4 -2
- package/skills/roles/qa.ai-eval.md +4 -2
- package/skills/roles/qa.api-contract.md +4 -2
- package/skills/roles/qa.data-pipeline.md +4 -2
- package/skills/roles/qa.md +7 -5
- package/skills/roles/qa.test-automation.md +5 -3
- package/skills/roles/qa.web-ui.md +4 -2
- package/skills/roles/researcher.explorer.md +4 -2
- package/skills/roles/researcher.md +11 -9
- package/skills/roles/researcher.ux.md +4 -2
- package/skills/roles/reviewer.devil-advocate.md +4 -2
- package/skills/roles/reviewer.evaluator.md +4 -2
- package/skills/roles/reviewer.md +14 -12
- package/skills/roles/reviewer.trace.md +4 -2
- package/skills/roles/security.ai.md +4 -2
- package/skills/roles/security.appsec.md +4 -2
- package/skills/roles/security.cloud.md +4 -2
- package/skills/roles/security.legal-compliance.md +4 -2
- package/skills/roles/security.md +7 -5
- package/skills/roles/security.privacy.md +4 -2
- package/skills/roles/security.supply-chain.md +4 -2
- package/skills/routing.md +14 -14
- package/skills/security/blue-team.md +1 -1
- package/skills/security/code-audit.md +1 -1
- package/skills/security/pentest.md +1 -1
- package/skills/security/red-team.md +1 -1
- package/skills/security/threat-intel.md +1 -1
- package/skills/security/vuln-research.md +1 -1
- package/skills/utility/clean-code.md +2 -2
- package/templates/docs/changelog-entry.md +1 -1
- package/templates/docs/construct_guide.md +13 -13
- package/templates/docs/meta-prd.md +16 -16
- package/templates/docs/one-pager.md +1 -1
- package/templates/docs/persona-artifact.md +36 -0
- package/templates/docs/prd-business.md +1 -1
- package/templates/docs/prd-platform.md +1 -1
- package/templates/docs/prd.md +17 -17
- package/templates/docs/research-brief.md +8 -8
- package/templates/docs/research-finding.md +26 -0
- package/templates/docs/rfc.md +1 -1
- package/templates/docs/skill-artifact.md +27 -0
- package/templates/docs/strategy.md +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* lib/hooks/session-reflect.mjs — Session end auto-reflect hook.
|
|
4
|
+
*
|
|
5
|
+
* Runs as a Stop hook. Reads the transcript, extracts a deterministic session
|
|
6
|
+
* summary, and records it via the observation store so subsequent sessions
|
|
7
|
+
* can search what happened. Closes the manual-reflect gap that left learning
|
|
8
|
+
* to operator discipline.
|
|
9
|
+
*
|
|
10
|
+
* Hard 500ms wall-clock budget. Exits 0 on any failure — observation capture
|
|
11
|
+
* is best-effort by design.
|
|
12
|
+
*
|
|
13
|
+
* Opt-out: CONSTRUCT_REFLECT_AUTO=off
|
|
14
|
+
*
|
|
15
|
+
* @p95ms 300
|
|
16
|
+
* @maxBlockingScope Stop
|
|
17
|
+
*/
|
|
18
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
|
|
21
|
+
const HARD_BUDGET_MS = 500;
|
|
22
|
+
const startedAt = Date.now();
|
|
23
|
+
|
|
24
|
+
// Opt-out before any heavy work — the env check is cheaper than parsing input.
|
|
25
|
+
if (process.env.CONSTRUCT_REFLECT_AUTO === 'off') process.exit(0);
|
|
26
|
+
|
|
27
|
+
let input = {};
|
|
28
|
+
try { input = JSON.parse(readFileSync(0, 'utf8')); } catch { process.exit(0); }
|
|
29
|
+
|
|
30
|
+
const cwd = input?.cwd || process.cwd();
|
|
31
|
+
const projectName = cwd.split('/').pop() || 'project';
|
|
32
|
+
|
|
33
|
+
// Only run for Construct projects — same gate as session-optimize.mjs.
|
|
34
|
+
if (projectName !== 'construct' && !existsSync(join(cwd, '.cx'))) process.exit(0);
|
|
35
|
+
|
|
36
|
+
const transcriptPath =
|
|
37
|
+
input?.transcript_path ||
|
|
38
|
+
input?.transcriptPath ||
|
|
39
|
+
process.env.CLAUDE_TRANSCRIPT_PATH ||
|
|
40
|
+
null;
|
|
41
|
+
|
|
42
|
+
if (!transcriptPath) process.exit(0);
|
|
43
|
+
|
|
44
|
+
// Wall-clock budget guard. If the extractor blows past the cap (it shouldn't
|
|
45
|
+
// — it's deterministic and O(n) over transcript lines), the parent process
|
|
46
|
+
// exits without writing. The next session-stop tries again.
|
|
47
|
+
const deadline = setTimeout(() => process.exit(0), HARD_BUDGET_MS);
|
|
48
|
+
deadline.unref();
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const { runReflectAuto } = await import('../reflect.mjs');
|
|
52
|
+
const sessionId = input?.session_id || input?.sessionId || null;
|
|
53
|
+
const durationMs = input?.session_duration_ms || null;
|
|
54
|
+
await runReflectAuto({ transcriptPath, cwd, sessionId, durationMs });
|
|
55
|
+
} catch {
|
|
56
|
+
// Best-effort — observation capture must not affect session exit.
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const elapsed = Date.now() - startedAt;
|
|
60
|
+
if (elapsed > HARD_BUDGET_MS) {
|
|
61
|
+
// Log only if budget exceeded — surfaces in construct doctor if it becomes
|
|
62
|
+
// a pattern. Otherwise silent.
|
|
63
|
+
try {
|
|
64
|
+
process.stderr.write(`[session-reflect] over budget: ${elapsed}ms\n`);
|
|
65
|
+
} catch { /* stderr closed — nothing to do */ }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
process.exit(0);
|
package/lib/init-unified.mjs
CHANGED
|
@@ -49,6 +49,12 @@ const interactive = args.includes("--interactive") || args.includes("-i");
|
|
|
49
49
|
const quiet = args.includes("--quiet") || args.includes("-q");
|
|
50
50
|
const skipInteractive = !interactive;
|
|
51
51
|
|
|
52
|
+
// Active profile selector. `--profile=<id>` writes the field into the
|
|
53
|
+
// project's construct.config.json so resolveActiveProfile picks it up
|
|
54
|
+
// on first run. Unknown ids are rejected with the available catalog.
|
|
55
|
+
const profileArg = args.find((arg) => arg.startsWith("--profile="));
|
|
56
|
+
const profileId = profileArg ? profileArg.split("=")[1] : null;
|
|
57
|
+
|
|
52
58
|
const created = [];
|
|
53
59
|
const skipped = [];
|
|
54
60
|
|
|
@@ -795,12 +801,29 @@ function initializeBeadsTracker(target) {
|
|
|
795
801
|
|
|
796
802
|
async function main() {
|
|
797
803
|
const projectName = inferProjectName(target);
|
|
798
|
-
|
|
804
|
+
|
|
799
805
|
const { clean } = preflight(target);
|
|
800
|
-
|
|
806
|
+
|
|
801
807
|
if (!quiet) {
|
|
802
808
|
console.log(`Initializing Construct in ${path.relative(process.cwd(), target) || "."}`);
|
|
803
809
|
}
|
|
810
|
+
|
|
811
|
+
// Persist --profile=<id> into construct.config.json. Validate against the
|
|
812
|
+
// curated catalog so a typo never silently falls back to rnd.
|
|
813
|
+
if (profileId) {
|
|
814
|
+
const { loadProfile, listProfiles } = await import('./profiles/loader.mjs');
|
|
815
|
+
if (!loadProfile(profileId)) {
|
|
816
|
+
console.error(`Unknown profile: ${profileId}. Available: ${listProfiles().join(', ')}`);
|
|
817
|
+
process.exit(1);
|
|
818
|
+
}
|
|
819
|
+
const { findProjectConfigPath, loadProjectConfig, writeProjectConfig, PROJECT_CONFIG_FILENAME } = await import('./config/project-config.mjs');
|
|
820
|
+
const found = findProjectConfigPath(target);
|
|
821
|
+
const cfgPath = found || path.join(target, PROJECT_CONFIG_FILENAME);
|
|
822
|
+
const cfg = found ? (loadProjectConfig(target) || { version: 1 }) : { version: 1 };
|
|
823
|
+
cfg.profile = profileId;
|
|
824
|
+
writeProjectConfig(cfgPath, cfg, { validate: true });
|
|
825
|
+
if (!quiet) console.log(`Profile set to ${profileId}.`);
|
|
826
|
+
}
|
|
804
827
|
|
|
805
828
|
// Always create core Construct files
|
|
806
829
|
writeStampedIfMissing({
|
package/lib/intake/classify.mjs
CHANGED
|
@@ -1,47 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* lib/intake/classify.mjs —
|
|
2
|
+
* lib/intake/classify.mjs — Profile-aware triage classification for intake packets.
|
|
3
3
|
*
|
|
4
|
-
* Deterministic, keyword-driven classifier that maps a raw intake signal
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* Deterministic, keyword-driven classifier that maps a raw intake signal onto
|
|
5
|
+
* the active org profile's loop. Returns a triage object with: intakeType,
|
|
6
|
+
* rdStage, primaryOwner, recommendedChain, recommendedAction, risk,
|
|
7
|
+
* requiresApproval, confidence, rationale.
|
|
8
8
|
*
|
|
9
9
|
* NO LLM call. The daemon path must remain synchronous and cheap; intent
|
|
10
10
|
* verification belongs in offline measurement, not inline classification.
|
|
11
|
-
*
|
|
11
|
+
*
|
|
12
|
+
* Default profile is `rnd` so existing R&D users see no behavior change.
|
|
13
|
+
* The `tests/intake/golden-rnd.test.mjs` test locks that invariant.
|
|
12
14
|
*/
|
|
13
15
|
|
|
14
16
|
import path from 'node:path';
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'eval-finding',
|
|
23
|
-
'architecture',
|
|
24
|
-
'incident',
|
|
25
|
-
'launch-asset',
|
|
26
|
-
'ops',
|
|
27
|
-
'security',
|
|
28
|
-
'legal-compliance',
|
|
29
|
-
'unknown',
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
export const RD_STAGES = [
|
|
33
|
-
'signal',
|
|
34
|
-
'framing',
|
|
35
|
-
'hypothesis',
|
|
36
|
-
'research',
|
|
37
|
-
'artifact',
|
|
38
|
-
'design',
|
|
39
|
-
'implementation',
|
|
40
|
-
'evaluation',
|
|
41
|
-
'release',
|
|
42
|
-
'operations',
|
|
43
|
-
'unknown',
|
|
44
|
-
];
|
|
18
|
+
// Backward-compatible exports. Default to RND values for any module that
|
|
19
|
+
// imports these constants directly (the symbol surface predates B2 and is
|
|
20
|
+
// referenced by intake-config, prepare, and tests).
|
|
21
|
+
import rndTable from './tables/rnd.mjs';
|
|
22
|
+
export const INTAKE_TYPES = rndTable.INTAKE_TYPES;
|
|
23
|
+
export const RD_STAGES = rndTable.STAGES;
|
|
45
24
|
|
|
46
25
|
export const RECOMMENDED_ACTIONS = [
|
|
47
26
|
'summarize',
|
|
@@ -60,146 +39,36 @@ export const RECOMMENDED_ACTIONS = [
|
|
|
60
39
|
'archive',
|
|
61
40
|
];
|
|
62
41
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
requiresApproval: true,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
intakeType: 'incident',
|
|
83
|
-
keywords: ['incident', 'outage', 'slo breach', 'sla breach', 'latency spike', 'availability', 'down', 'p0 ', 'p1 ', 'pagerduty', '5xx', 'oncall'],
|
|
84
|
-
rdStage: 'operations',
|
|
85
|
-
primaryOwner: 'sre',
|
|
86
|
-
recommendedChain: ['sre', 'debugger', 'platform-engineer'],
|
|
87
|
-
recommendedAction: 'create-runbook',
|
|
88
|
-
risk: 'high',
|
|
89
|
-
requiresApproval: true,
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
intakeType: 'legal-compliance',
|
|
93
|
-
keywords: ['gdpr', 'ccpa', 'hipaa', 'sox', 'soc2', 'license', 'lawsuit', 'dpa', 'data retention', 'pii', 'subpoena', 'compliance audit'],
|
|
94
|
-
rdStage: 'operations',
|
|
95
|
-
primaryOwner: 'legal-compliance',
|
|
96
|
-
recommendedChain: ['legal-compliance', 'security', 'product-manager'],
|
|
97
|
-
recommendedAction: 'clarify',
|
|
98
|
-
risk: 'high',
|
|
99
|
-
requiresApproval: true,
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
intakeType: 'architecture',
|
|
103
|
-
keywords: ['architecture', 'adr', 'rfc', 'interface', 'tradeoff', 'boundary', 'system design', 'data model', 'api contract', 'migration plan'],
|
|
104
|
-
rdStage: 'design',
|
|
105
|
-
primaryOwner: 'architect',
|
|
106
|
-
recommendedChain: ['architect', 'devil-advocate', 'engineer'],
|
|
107
|
-
recommendedAction: 'draft-rfc',
|
|
108
|
-
risk: 'medium',
|
|
109
|
-
requiresApproval: false,
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
intakeType: 'eval-finding',
|
|
113
|
-
keywords: ['eval', 'evaluation', 'hallucination', 'judge', 'trace', 'score regression', 'recall@', 'precision@', 'mrr', 'ndcg', 'failure case', 'rubric'],
|
|
114
|
-
rdStage: 'evaluation',
|
|
115
|
-
primaryOwner: 'evaluator',
|
|
116
|
-
recommendedChain: ['evaluator', 'ai-engineer', 'trace-reviewer'],
|
|
117
|
-
recommendedAction: 'evaluate',
|
|
118
|
-
risk: 'medium',
|
|
119
|
-
requiresApproval: false,
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
intakeType: 'bug',
|
|
123
|
-
keywords: ['bug', 'broken', 'error', 'stack trace', 'regression', 'crash', 'exception', 'fails', 'failing', 'throws', 'not working', 'reproduce', 'repro:'],
|
|
124
|
-
rdStage: 'implementation',
|
|
125
|
-
primaryOwner: 'debugger',
|
|
126
|
-
recommendedChain: ['debugger', 'engineer', 'qa', 'reviewer'],
|
|
127
|
-
recommendedAction: 'diagnose',
|
|
128
|
-
risk: 'medium',
|
|
129
|
-
requiresApproval: false,
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
intakeType: 'experiment',
|
|
133
|
-
keywords: ['hypothesis', 'experiment', 'spike', 'prototype', 'falsifiable', 'research question', 'a/b test', 'pilot'],
|
|
134
|
-
rdStage: 'hypothesis',
|
|
135
|
-
primaryOwner: 'rd-lead',
|
|
136
|
-
recommendedChain: ['rd-lead', 'researcher', 'evaluator'],
|
|
137
|
-
recommendedAction: 'create-experiment',
|
|
138
|
-
risk: 'low',
|
|
139
|
-
requiresApproval: false,
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
intakeType: 'launch-asset',
|
|
143
|
-
keywords: ['release', 'changelog', 'version bump', 'ship', 'launch', 'rollout', 'cut a release', 'rc1', 'rc2', 'release candidate'],
|
|
144
|
-
rdStage: 'release',
|
|
145
|
-
primaryOwner: 'release-manager',
|
|
146
|
-
recommendedChain: ['release-manager', 'qa', 'docs-keeper'],
|
|
147
|
-
recommendedAction: 'release-review',
|
|
148
|
-
risk: 'medium',
|
|
149
|
-
requiresApproval: false,
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
intakeType: 'research',
|
|
153
|
-
keywords: ['competitor', 'market', 'pricing', 'positioning', 'industry', 'state of the art', 'literature', 'benchmark study', 'desk research'],
|
|
154
|
-
rdStage: 'research',
|
|
155
|
-
primaryOwner: 'business-strategist',
|
|
156
|
-
recommendedChain: ['business-strategist', 'researcher', 'product-manager'],
|
|
157
|
-
recommendedAction: 'research',
|
|
158
|
-
risk: 'low',
|
|
159
|
-
requiresApproval: false,
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
intakeType: 'user-signal',
|
|
163
|
-
keywords: ['customer', 'feedback', 'pain point', 'user says', 'user feedback', 'support ticket', 'churn', 'nps', 'usability', 'frustrated'],
|
|
164
|
-
rdStage: 'signal',
|
|
165
|
-
primaryOwner: 'product-manager',
|
|
166
|
-
recommendedChain: ['product-manager', 'ux-researcher', 'researcher'],
|
|
167
|
-
recommendedAction: 'clarify',
|
|
168
|
-
risk: 'low',
|
|
169
|
-
requiresApproval: false,
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
intakeType: 'requirement',
|
|
173
|
-
keywords: ['acceptance criteria', 'requirement', 'must have', 'should have', 'feature request', 'prd', 'use case', 'success metric'],
|
|
174
|
-
rdStage: 'framing',
|
|
175
|
-
primaryOwner: 'product-manager',
|
|
176
|
-
recommendedChain: ['product-manager', 'architect', 'engineer'],
|
|
177
|
-
recommendedAction: 'draft-prd',
|
|
178
|
-
risk: 'low',
|
|
179
|
-
requiresApproval: false,
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
intakeType: 'ops',
|
|
183
|
-
keywords: ['runbook', 'cron', 'scheduled job', 'maintenance', 'backup', 'restore', 'capacity plan', 'cost optimization', 'dependency upgrade'],
|
|
184
|
-
rdStage: 'operations',
|
|
185
|
-
primaryOwner: 'operations',
|
|
186
|
-
recommendedChain: ['operations', 'sre', 'engineer'],
|
|
187
|
-
recommendedAction: 'create-runbook',
|
|
188
|
-
risk: 'low',
|
|
189
|
-
requiresApproval: false,
|
|
190
|
-
},
|
|
191
|
-
];
|
|
42
|
+
// Static profile → table map. New curated profiles register themselves here.
|
|
43
|
+
// Custom profiles (escape hatch) declare classificationTable as a repo-relative
|
|
44
|
+
// path; that path is loaded dynamically in classifyRdIntake when a profile arg
|
|
45
|
+
// supplies it.
|
|
46
|
+
import operationsTable from './tables/operations.mjs';
|
|
47
|
+
import creativeTable from './tables/creative.mjs';
|
|
48
|
+
import researchTable from './tables/research.mjs';
|
|
49
|
+
import { outcomeBoost } from '../outcomes/aggregate.mjs';
|
|
50
|
+
|
|
51
|
+
// Outcome boost is a soft re-rank applied when a cwd is supplied. Capped at
|
|
52
|
+
// ±0.05 in outcomeBoost itself, so the primary keyword signal (integer hits)
|
|
53
|
+
// always dominates. Returns 0 if no outcome data exists for the role.
|
|
54
|
+
function outcomeBoostFor(cwd, role) {
|
|
55
|
+
if (!cwd || !role) return 0;
|
|
56
|
+
try { return outcomeBoost(cwd, role); } catch { return 0; }
|
|
57
|
+
}
|
|
192
58
|
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
recommendedAction: 'summarize',
|
|
199
|
-
risk: 'low',
|
|
200
|
-
requiresApproval: false,
|
|
59
|
+
const TABLES = {
|
|
60
|
+
rnd: rndTable,
|
|
61
|
+
operations: operationsTable,
|
|
62
|
+
creative: creativeTable,
|
|
63
|
+
research: researchTable,
|
|
201
64
|
};
|
|
202
65
|
|
|
66
|
+
function resolveTable(profile) {
|
|
67
|
+
if (!profile) return rndTable;
|
|
68
|
+
const id = typeof profile === 'string' ? profile : profile.id;
|
|
69
|
+
return TABLES[id] || rndTable;
|
|
70
|
+
}
|
|
71
|
+
|
|
203
72
|
function normalize(text) {
|
|
204
73
|
return String(text || '').toLowerCase();
|
|
205
74
|
}
|
|
@@ -225,27 +94,35 @@ function buildSignalText({ sourcePath, extractedText, related }) {
|
|
|
225
94
|
}
|
|
226
95
|
|
|
227
96
|
/**
|
|
228
|
-
* Classify an
|
|
97
|
+
* Classify an intake signal against the active profile (defaults to RND).
|
|
98
|
+
*
|
|
99
|
+
* Backward-compatible: callers that did not pass a `profile` arg keep getting
|
|
100
|
+
* RND output, byte-identical to the pre-B2 behavior.
|
|
229
101
|
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
102
|
+
* @param {object} input
|
|
103
|
+
* @param {string} [input.sourcePath]
|
|
104
|
+
* @param {string} [input.extractedText]
|
|
105
|
+
* @param {Array} [input.related]
|
|
106
|
+
* @param {string|object} [input.profile] - profile id (string) or full profile object
|
|
233
107
|
*/
|
|
234
|
-
export function classifyRdIntake({ sourcePath = '', extractedText = '', related = [] } = {}) {
|
|
108
|
+
export function classifyRdIntake({ sourcePath = '', extractedText = '', related = [], profile = null, cwd = null } = {}) {
|
|
109
|
+
const table = resolveTable(profile);
|
|
235
110
|
const signal = buildSignalText({ sourcePath, extractedText, related });
|
|
236
111
|
|
|
237
112
|
let best = null;
|
|
238
|
-
for (const entry of CLASSIFICATION_TABLE) {
|
|
113
|
+
for (const entry of table.CLASSIFICATION_TABLE) {
|
|
239
114
|
const { hits, matched } = countMatches(signal, entry.keywords);
|
|
240
115
|
if (hits === 0) continue;
|
|
241
|
-
|
|
242
|
-
|
|
116
|
+
const boost = cwd ? outcomeBoostFor(cwd, entry.primaryOwner) : 0;
|
|
117
|
+
const score = hits + boost;
|
|
118
|
+
if (!best || score > best.score) {
|
|
119
|
+
best = { entry, hits, matched, score };
|
|
243
120
|
}
|
|
244
121
|
}
|
|
245
122
|
|
|
246
123
|
if (!best) {
|
|
247
124
|
return {
|
|
248
|
-
...UNKNOWN_TRIAGE,
|
|
125
|
+
...table.UNKNOWN_TRIAGE,
|
|
249
126
|
confidence: 0.3,
|
|
250
127
|
rationale: 'No classification keywords matched filename, content excerpt, or related-doc titles.',
|
|
251
128
|
};
|
|
@@ -272,7 +149,8 @@ export function classifyRdIntake({ sourcePath = '', extractedText = '', related
|
|
|
272
149
|
export function formatTriageLine(sourcePath, triage) {
|
|
273
150
|
const basename = sourcePath ? path.basename(sourcePath) : '(unknown source)';
|
|
274
151
|
if (!triage || triage.intakeType === 'unknown') {
|
|
275
|
-
return `${basename} → unclassified · owner: orchestrator · next: summarize`;
|
|
152
|
+
return `${basename} → unclassified · owner: ${triage?.primaryOwner ?? 'orchestrator'} · next: ${triage?.recommendedAction ?? 'summarize'}`;
|
|
276
153
|
}
|
|
277
|
-
|
|
154
|
+
const ownerLabel = triage.primaryOwner ?? 'unassigned';
|
|
155
|
+
return `${basename} → ${triage.intakeType} / ${triage.rdStage} · owner: ${ownerLabel} · next: ${triage.recommendedAction}`;
|
|
278
156
|
}
|
package/lib/intake/prepare.mjs
CHANGED
|
@@ -29,6 +29,7 @@ import { suggestDocsLaneForFile } from '../docs-routing.mjs';
|
|
|
29
29
|
import { createIntakeQueue } from './queue.mjs';
|
|
30
30
|
import { classifyRdIntake } from './classify.mjs';
|
|
31
31
|
import { detectCustomerMentions, linkSignalToCustomer, updateCustomerProfile } from '../embed/customer-profiles.mjs';
|
|
32
|
+
import { resolveActiveProfile } from '../profiles/loader.mjs';
|
|
32
33
|
|
|
33
34
|
const DEFAULT_RELATED_LIMIT = 5;
|
|
34
35
|
const EXCERPT_CHARS = 800;
|
|
@@ -67,10 +68,16 @@ export async function prepareIntakeForIngestedFile({
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
const lane = suggestDocsLaneForFile(ingestedFile.sourcePath, extracted) || null;
|
|
71
|
+
// Resolve the active profile so non-RND projects route to their own table.
|
|
72
|
+
// Falls back to rnd for any project without explicit configuration, which
|
|
73
|
+
// preserves prior behavior for every existing user.
|
|
74
|
+
const activeProfile = resolveActiveProfile(rootDir);
|
|
70
75
|
const triage = classifyFn({
|
|
71
76
|
sourcePath: ingestedFile.sourcePath,
|
|
72
77
|
extractedText: extracted,
|
|
73
78
|
related,
|
|
79
|
+
profile: activeProfile?.id,
|
|
80
|
+
cwd: rootDir,
|
|
74
81
|
});
|
|
75
82
|
|
|
76
83
|
// Detect customer mentions and update profiles
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/intake/tables/creative.mjs — Creative production intake classification.
|
|
3
|
+
*
|
|
4
|
+
* Loop: brief → research → draft → review → publish → measure. Covers content
|
|
5
|
+
* creation, campaigns, design work. Roles are creative-org roles, not engineering.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const INTAKE_TYPES = ['brief', 'content-request', 'asset', 'experiment', 'report', 'legal-compliance', 'ops', 'unknown'];
|
|
9
|
+
export const STAGES = ['brief', 'research', 'draft', 'review', 'publish', 'measure'];
|
|
10
|
+
|
|
11
|
+
export const UNKNOWN_TRIAGE = {
|
|
12
|
+
intakeType: 'unknown',
|
|
13
|
+
rdStage: 'unknown',
|
|
14
|
+
primaryOwner: 'operator',
|
|
15
|
+
recommendedChain: ['operator'],
|
|
16
|
+
recommendedAction: 'summarize',
|
|
17
|
+
risk: 'low',
|
|
18
|
+
requiresApproval: false,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const CLASSIFICATION_TABLE = [
|
|
22
|
+
{
|
|
23
|
+
intakeType: 'legal-compliance',
|
|
24
|
+
keywords: ['gdpr', 'ccpa', 'privacy', 'consent', 'unsubscribe', 'can-spam', 'cookie banner', 'disclosure', 'trademark'],
|
|
25
|
+
rdStage: 'review',
|
|
26
|
+
primaryOwner: 'legal-compliance',
|
|
27
|
+
recommendedChain: ['legal-compliance', 'reviewer'],
|
|
28
|
+
recommendedAction: 'clarify',
|
|
29
|
+
risk: 'high',
|
|
30
|
+
requiresApproval: true,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
intakeType: 'brief',
|
|
34
|
+
keywords: ['brief', 'campaign', 'launch plan', 'go-to-market', 'gtm', 'positioning', 'narrative', 'audience'],
|
|
35
|
+
rdStage: 'brief',
|
|
36
|
+
primaryOwner: 'product-lead',
|
|
37
|
+
recommendedChain: ['product-lead', 'researcher', 'content-writer'],
|
|
38
|
+
recommendedAction: 'draft-prd',
|
|
39
|
+
risk: 'medium',
|
|
40
|
+
requiresApproval: false,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
intakeType: 'content-request',
|
|
44
|
+
keywords: ['blog', 'article', 'landing page', 'social post', 'newsletter', 'email copy', 'video script', 'headline', 'post', 'content'],
|
|
45
|
+
rdStage: 'draft',
|
|
46
|
+
primaryOwner: 'content-writer',
|
|
47
|
+
recommendedChain: ['content-writer', 'reviewer'],
|
|
48
|
+
recommendedAction: 'draft-rfc',
|
|
49
|
+
risk: 'low',
|
|
50
|
+
requiresApproval: false,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
intakeType: 'asset',
|
|
54
|
+
keywords: ['asset', 'logo', 'image', 'banner', 'mockup', 'figma', 'brand guide', 'illustration'],
|
|
55
|
+
rdStage: 'draft',
|
|
56
|
+
primaryOwner: 'designer',
|
|
57
|
+
recommendedChain: ['designer', 'reviewer'],
|
|
58
|
+
recommendedAction: 'draft-rfc',
|
|
59
|
+
risk: 'low',
|
|
60
|
+
requiresApproval: false,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
intakeType: 'experiment',
|
|
64
|
+
keywords: ['a/b test', 'experiment', 'hypothesis', 'multivariate', 'pilot', 'audience test'],
|
|
65
|
+
rdStage: 'measure',
|
|
66
|
+
primaryOwner: 'data-analyst',
|
|
67
|
+
recommendedChain: ['data-analyst', 'researcher'],
|
|
68
|
+
recommendedAction: 'create-experiment',
|
|
69
|
+
risk: 'low',
|
|
70
|
+
requiresApproval: false,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
intakeType: 'report',
|
|
74
|
+
keywords: ['report', 'dashboard', 'attribution', 'ctr', 'cpa', 'roas', 'conversion', 'funnel', 'engagement'],
|
|
75
|
+
rdStage: 'measure',
|
|
76
|
+
primaryOwner: 'data-analyst',
|
|
77
|
+
recommendedChain: ['data-analyst', 'product-lead'],
|
|
78
|
+
recommendedAction: 'evaluate',
|
|
79
|
+
risk: 'low',
|
|
80
|
+
requiresApproval: false,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
intakeType: 'ops',
|
|
84
|
+
keywords: ['process', 'workflow', 'template', 'sla', 'calendar', 'planning', 'editorial calendar'],
|
|
85
|
+
rdStage: 'review',
|
|
86
|
+
primaryOwner: 'operator',
|
|
87
|
+
recommendedChain: ['operator', 'product-lead'],
|
|
88
|
+
recommendedAction: 'create-runbook',
|
|
89
|
+
risk: 'low',
|
|
90
|
+
requiresApproval: false,
|
|
91
|
+
},
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
export default { INTAKE_TYPES, STAGES, CLASSIFICATION_TABLE, UNKNOWN_TRIAGE };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/intake/tables/operations.mjs — Operations intake classification.
|
|
3
|
+
*
|
|
4
|
+
* Loop: request → triage → resolve → document → improve. Optimized for teams
|
|
5
|
+
* whose primary work is fulfilling requests and keeping things running, not
|
|
6
|
+
* building new product. Owners are operations roles (operator, sre, engineer).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const INTAKE_TYPES = ['request', 'bug', 'incident', 'ops', 'security', 'docs', 'unknown'];
|
|
10
|
+
export const STAGES = ['request', 'triage', 'resolve', 'document', 'improve'];
|
|
11
|
+
|
|
12
|
+
export const UNKNOWN_TRIAGE = {
|
|
13
|
+
intakeType: 'unknown',
|
|
14
|
+
rdStage: 'unknown',
|
|
15
|
+
primaryOwner: 'operator',
|
|
16
|
+
recommendedChain: ['operator'],
|
|
17
|
+
recommendedAction: 'summarize',
|
|
18
|
+
risk: 'low',
|
|
19
|
+
requiresApproval: false,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const CLASSIFICATION_TABLE = [
|
|
23
|
+
{
|
|
24
|
+
intakeType: 'security',
|
|
25
|
+
keywords: ['security', 'cve', 'vulnerability', 'leak', 'auth bypass', 'pii', 'secret'],
|
|
26
|
+
rdStage: 'resolve',
|
|
27
|
+
primaryOwner: 'security',
|
|
28
|
+
recommendedChain: ['security', 'engineer', 'reviewer'],
|
|
29
|
+
recommendedAction: 'diagnose',
|
|
30
|
+
risk: 'high',
|
|
31
|
+
requiresApproval: true,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
intakeType: 'incident',
|
|
35
|
+
keywords: ['incident', 'outage', 'down', 'p0 ', 'p1 ', 'oncall', 'pager', '5xx', 'sla breach'],
|
|
36
|
+
rdStage: 'resolve',
|
|
37
|
+
primaryOwner: 'sre',
|
|
38
|
+
recommendedChain: ['sre', 'engineer'],
|
|
39
|
+
recommendedAction: 'create-runbook',
|
|
40
|
+
risk: 'high',
|
|
41
|
+
requiresApproval: true,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
intakeType: 'bug',
|
|
45
|
+
keywords: ['bug', 'broken', 'error', 'fails', 'crash', 'exception', 'stack trace'],
|
|
46
|
+
rdStage: 'resolve',
|
|
47
|
+
primaryOwner: 'engineer',
|
|
48
|
+
recommendedChain: ['engineer', 'qa', 'reviewer'],
|
|
49
|
+
recommendedAction: 'diagnose',
|
|
50
|
+
risk: 'medium',
|
|
51
|
+
requiresApproval: false,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
intakeType: 'docs',
|
|
55
|
+
keywords: ['docs', 'documentation', 'how to', 'guide', 'readme', 'wiki', 'runbook missing'],
|
|
56
|
+
rdStage: 'document',
|
|
57
|
+
primaryOwner: 'docs-keeper',
|
|
58
|
+
recommendedChain: ['docs-keeper', 'reviewer'],
|
|
59
|
+
recommendedAction: 'create-runbook',
|
|
60
|
+
risk: 'low',
|
|
61
|
+
requiresApproval: false,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
intakeType: 'ops',
|
|
65
|
+
keywords: ['cron', 'scheduled job', 'maintenance', 'backup', 'restore', 'rotation', 'capacity', 'upgrade'],
|
|
66
|
+
rdStage: 'improve',
|
|
67
|
+
primaryOwner: 'sre',
|
|
68
|
+
recommendedChain: ['sre', 'engineer'],
|
|
69
|
+
recommendedAction: 'create-runbook',
|
|
70
|
+
risk: 'low',
|
|
71
|
+
requiresApproval: false,
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
intakeType: 'request',
|
|
75
|
+
keywords: ['request', 'access', 'feature request', 'integration', 'new tool', 'change request', 'how do i', 'can someone'],
|
|
76
|
+
rdStage: 'triage',
|
|
77
|
+
primaryOwner: 'operator',
|
|
78
|
+
recommendedChain: ['operator', 'engineer'],
|
|
79
|
+
recommendedAction: 'clarify',
|
|
80
|
+
risk: 'low',
|
|
81
|
+
requiresApproval: false,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
export default { INTAKE_TYPES, STAGES, CLASSIFICATION_TABLE, UNKNOWN_TRIAGE };
|