From 9c9be0891cbeaf4002df7ac6a9bd8062c2433552 Mon Sep 17 00:00:00 2001 From: Pedro Valerio Date: Tue, 17 Feb 2026 09:48:42 -0300 Subject: [PATCH 1/4] feat(code-intel): dev task enhancement with IDS G4 automation [Story NOG-3] Integrate code intelligence into @dev development tasks for automatic duplicate detection (IDS Gate G4), conventions checking, and blast radius assessment. All integrations use graceful fallback when no provider available. - Create dev-helper.js with 4 public functions (checkBeforeWriting, suggestReuse, getConventionsForPath, assessRefactoringImpact) - Modify dev-develop-story.md: add Code Intelligence Check step - Modify create-service.md: add pre-scaffold duplicate check - Modify dev-suggest-refactoring.md: add blast radius in analysis - Modify build-autonomous.md: add IDS G4 check in build loop - Add 24 unit tests (all passing) covering T1-T9 scenarios - Register dev-helper entity in entity-registry.yaml - QA gate: PASS (quality score 100/100) Co-Authored-By: Claude Opus 4.6 --- .../core/code-intel/helpers/dev-helper.js | 206 ++++++++ .aios-core/data/entity-registry.yaml | 27 ++ .../development/tasks/build-autonomous.md | 14 +- .../development/tasks/create-service.md | 23 + .../development/tasks/dev-develop-story.md | 18 +- .../tasks/dev-suggest-refactoring.md | 8 +- .aios-core/install-manifest.yaml | 220 ++++----- docs/qa/gates/nog-3-dev-task-enhancement.yml | 48 ++ .../story-NOG-3-dev-task-enhancement.md | 442 ++++++++++++++++++ tests/code-intel/dev-helper.test.js | 376 +++++++++++++++ 10 files changed, 1263 insertions(+), 119 deletions(-) create mode 100644 .aios-core/core/code-intel/helpers/dev-helper.js create mode 100644 docs/qa/gates/nog-3-dev-task-enhancement.yml create mode 100644 docs/stories/epics/epic-nogic-code-intelligence/story-NOG-3-dev-task-enhancement.md create mode 100644 tests/code-intel/dev-helper.test.js diff --git a/.aios-core/core/code-intel/helpers/dev-helper.js b/.aios-core/core/code-intel/helpers/dev-helper.js new file mode 100644 index 000000000..cc2c1c24b --- /dev/null +++ b/.aios-core/core/code-intel/helpers/dev-helper.js @@ -0,0 +1,206 @@ +'use strict'; + +const { getEnricher, getClient, isCodeIntelAvailable } = require('../index'); + +// Risk level thresholds based on blast radius (reference count) +const RISK_THRESHOLDS = { + LOW_MAX: 4, // 0-4 refs = LOW + MEDIUM_MAX: 15, // 5-15 refs = MEDIUM + // >15 refs = HIGH +}; + +// Minimum references to suggest REUSE (>threshold = REUSE, <=threshold = ADAPT) +const REUSE_MIN_REFS = 2; + +/** + * DevHelper — Code intelligence helper for @dev agent tasks. + * + * All functions return null gracefully when no provider is available. + * Never throws — safe to call unconditionally in task workflows. + */ + +/** + * Check for duplicates and similar code before writing a new file or function. + * Used by IDS Gate G4 in dev-develop-story and build-autonomous tasks. + * + * @param {string} fileName - Name of the file/function to be created + * @param {string} description - Description of what it does + * @returns {Promise<{duplicates: Object, references: Array, suggestion: string}|null>} + */ +async function checkBeforeWriting(fileName, description) { + if (!isCodeIntelAvailable()) { + return null; + } + + try { + const enricher = getEnricher(); + const dupes = await enricher.detectDuplicates(description, { path: '.' }); + + // Also search for the fileName as a symbol reference + const client = getClient(); + const nameRefs = await client.findReferences(fileName); + + const hasMatches = (dupes && dupes.matches && dupes.matches.length > 0) || + (nameRefs && nameRefs.length > 0); + + if (!hasMatches) { + return null; + } + + return { + duplicates: dupes, + references: nameRefs || [], + suggestion: _formatSuggestion(dupes, nameRefs), + }; + } catch { + return null; + } +} + +/** + * Suggest reuse of an existing symbol instead of creating a new one. + * Searches for definitions and references to determine REUSE vs ADAPT. + * + * @param {string} symbol - Symbol name to search for + * @returns {Promise<{file: string, line: number, references: number, suggestion: string}|null>} + */ +async function suggestReuse(symbol) { + if (!isCodeIntelAvailable()) { + return null; + } + + try { + const client = getClient(); + const [definition, refs] = await Promise.all([ + client.findDefinition(symbol), + client.findReferences(symbol), + ]); + + if (!definition && (!refs || refs.length === 0)) { + return null; + } + + const refCount = refs ? refs.length : 0; + // REUSE if widely used, ADAPT if exists but lightly used + const suggestion = refCount > REUSE_MIN_REFS ? 'REUSE' : 'ADAPT'; + + return { + file: definition ? definition.file : (refs[0] ? refs[0].file : null), + line: definition ? definition.line : (refs[0] ? refs[0].line : null), + references: refCount, + suggestion, + }; + } catch { + return null; + } +} + +/** + * Get naming conventions and patterns for a given path. + * Used to ensure new code follows existing project conventions. + * + * @param {string} targetPath - Path to analyze conventions for + * @returns {Promise<{patterns: Array, stats: Object}|null>} + */ +async function getConventionsForPath(targetPath) { + if (!isCodeIntelAvailable()) { + return null; + } + + try { + const enricher = getEnricher(); + return await enricher.getConventions(targetPath); + } catch { + return null; + } +} + +/** + * Assess refactoring impact with blast radius and risk level. + * Used by dev-suggest-refactoring to show impact before changes. + * + * @param {string[]} files - Files to assess impact for + * @returns {Promise<{blastRadius: number, riskLevel: string, references: Array, complexity: Object}|null>} + */ +async function assessRefactoringImpact(files) { + if (!isCodeIntelAvailable()) { + return null; + } + + try { + const enricher = getEnricher(); + const impact = await enricher.assessImpact(files); + + if (!impact) { + return null; + } + + return { + blastRadius: impact.blastRadius, + riskLevel: _calculateRiskLevel(impact.blastRadius), + references: impact.references, + complexity: impact.complexity, + }; + } catch { + return null; + } +} + +/** + * Format a Code Intelligence Suggestion message from duplicate detection results. + * @param {Object|null} dupes - Result from detectDuplicates + * @param {Array|null} nameRefs - Result from findReferences + * @returns {string} Formatted suggestion message + * @private + */ +function _formatSuggestion(dupes, nameRefs) { + const parts = []; + + if (dupes && dupes.matches && dupes.matches.length > 0) { + parts.push(`Found ${dupes.matches.length} similar match(es) in codebase`); + const firstMatch = dupes.matches[0]; + if (firstMatch.file) { + parts.push(`Closest: ${firstMatch.file}${firstMatch.line ? ':' + firstMatch.line : ''}`); + } + } + + if (nameRefs && nameRefs.length > 0) { + parts.push(`Symbol already referenced in ${nameRefs.length} location(s)`); + const firstRef = nameRefs[0]; + if (firstRef.file) { + parts.push(`First ref: ${firstRef.file}${firstRef.line ? ':' + firstRef.line : ''}`); + } + } + + parts.push('Consider REUSE or ADAPT before creating new code (IDS Article IV-A)'); + + return parts.join('. ') + '.'; +} + +/** + * Calculate risk level from blast radius count. + * @param {number} blastRadius - Number of references affected + * @returns {string} 'LOW' | 'MEDIUM' | 'HIGH' + * @private + */ +function _calculateRiskLevel(blastRadius) { + if (blastRadius <= RISK_THRESHOLDS.LOW_MAX) { + return 'LOW'; + } + if (blastRadius <= RISK_THRESHOLDS.MEDIUM_MAX) { + return 'MEDIUM'; + } + return 'HIGH'; +} + +module.exports = { + checkBeforeWriting, + suggestReuse, + getConventionsForPath, + assessRefactoringImpact, + // Exposed for testing + _formatSuggestion, + _calculateRiskLevel, + RISK_THRESHOLDS, + REUSE_MIN_REFS, +}; diff --git a/.aios-core/data/entity-registry.yaml b/.aios-core/data/entity-registry.yaml index 484d41351..108a559e8 100644 --- a/.aios-core/data/entity-registry.yaml +++ b/.aios-core/data/entity-registry.yaml @@ -5997,6 +5997,33 @@ entities: checksum: sha256:310884d94b81be976a346987822306a16a73ba812c08c3b805f4a03216ffef38 lastVerified: '2026-02-15T19:28:17.743Z' modules: + dev-helper: + path: .aios-core/core/code-intel/helpers/dev-helper.js + type: module + purpose: Code intelligence helper for @dev agent tasks - IDS G4 automation, duplicate detection, conventions, blast radius + keywords: + - code-intel + - dev-helper + - ids-g4 + - duplicate-detection + - blast-radius + - conventions + - reuse + usedBy: + - dev-develop-story + - create-service + - dev-suggest-refactoring + - build-autonomous + dependencies: + - code-intel + adaptability: + score: 0.7 + constraints: + - Requires code-intel module (NOG-1) + extensionPoints: + - Additional helper functions for other agents + checksum: '' + lastVerified: '2026-02-16T00:00:00.000Z' registry-syncer: path: .aios-core/core/code-intel/registry-syncer.js type: module diff --git a/.aios-core/development/tasks/build-autonomous.md b/.aios-core/development/tasks/build-autonomous.md index ff8fd8005..2bfa7b9d7 100644 --- a/.aios-core/development/tasks/build-autonomous.md +++ b/.aios-core/development/tasks/build-autonomous.md @@ -70,10 +70,16 @@ steps: action: | FOR EACH subtask in implementation.yaml: 1. Track attempt start (RecoveryTracker) - 2. Execute subtask (plan-execute-subtask.md workflow) - 3. Self-critique at steps 5.5 and 6.5 - 4. Verify completion (verify-subtask.md workflow) - 5. Create checkpoint on success + 2. **Code Intelligence IDS G4 Check** (before creating new files): + - If `isCodeIntelAvailable()` (from `.aios-core/core/code-intel`): + - Call `checkBeforeWriting(fileName, description)` from `dev-helper` + - If duplicates detected: log in decision-log and display as advisory + - Does NOT block execution (autonomous mode continues) + - If code intelligence not available: skip silently + 3. Execute subtask (plan-execute-subtask.md workflow) + 4. Self-critique at steps 5.5 and 6.5 + 5. Verify completion (verify-subtask.md workflow) + 6. Create checkpoint on success IF failure: - Increment attempt count diff --git a/.aios-core/development/tasks/create-service.md b/.aios-core/development/tasks/create-service.md index c95b830f2..2dcdf5099 100644 --- a/.aios-core/development/tasks/create-service.md +++ b/.aios-core/development/tasks/create-service.md @@ -151,6 +151,29 @@ Examples: API_KEY, BASE_URL, TIMEOUT_MS ## Implementation Steps +### Step 0: Code Intelligence Duplicate Check (Pre-Scaffold) + +Before scaffolding the service, check if a similar service already exists using code intelligence: + +```javascript +// Code Intelligence pre-scaffold check (graceful — never blocks) +const { isCodeIntelAvailable } = require('.aios-core/core/code-intel'); +const { checkBeforeWriting } = require('.aios-core/core/code-intel/helpers/dev-helper'); + +if (isCodeIntelAvailable()) { + const result = await checkBeforeWriting(serviceName, description); + if (result) { + // Display as advisory — does NOT block scaffold + console.log('⚠️ Code Intelligence Suggestion:'); + console.log(` ${result.suggestion}`); + console.log(' Consider REUSE or ADAPT before creating a new service.'); + // In interactive mode: prompt user to confirm proceeding + // In YOLO mode: log and continue + } +} +// If code intelligence not available: proceed normally (no impact) +``` + ### Step 1: Validate Inputs ```javascript // Validate service_name diff --git a/.aios-core/development/tasks/dev-develop-story.md b/.aios-core/development/tasks/dev-develop-story.md index b79c098de..c22473b18 100644 --- a/.aios-core/development/tasks/dev-develop-story.md +++ b/.aios-core/development/tasks/dev-develop-story.md @@ -478,12 +478,18 @@ const { ### Order of Execution 1. Read (first or next) task -2. Implement task and its subtasks -3. Write tests -4. Execute validations -5. **Only if ALL pass**: Mark task checkbox [x] -6. Update story File List (ensure all created/modified/deleted files listed) -7. Repeat until all tasks complete +2. **Code Intelligence Check (IDS G4)** — Before creating new files or functions: + - If code intelligence is available (`isCodeIntelAvailable()` from `.aios-core/core/code-intel`): + - Call `checkBeforeWriting(fileName, description)` from `.aios-core/core/code-intel/helpers/dev-helper` + - If result is not null, display as **"Code Intelligence Suggestion"** (non-blocking advisory) + - Log suggestion in decision-log if in YOLO mode + - If code intelligence is NOT available: skip silently (zero impact on workflow) +3. Implement task and its subtasks +4. Write tests +5. Execute validations +6. **Only if ALL pass**: Mark task checkbox [x] +7. Update story File List (ensure all created/modified/deleted files listed) +8. Repeat until all tasks complete ### Story File Updates (All Modes) diff --git a/.aios-core/development/tasks/dev-suggest-refactoring.md b/.aios-core/development/tasks/dev-suggest-refactoring.md index 7ddee3a73..3a426c002 100644 --- a/.aios-core/development/tasks/dev-suggest-refactoring.md +++ b/.aios-core/development/tasks/dev-suggest-refactoring.md @@ -825,11 +825,17 @@ module.exports = SuggestRefactoringTask; 3. Run pattern detectors 4. Generate suggestions 5. Prioritize by impact +6. **Code Intelligence Blast Radius** (if available): + - Call `assessRefactoringImpact(candidateFiles)` from `.aios-core/core/code-intel/helpers/dev-helper` + - If result is not null, enrich each suggestion with: + - `blastRadius`: number of affected references + - `riskLevel`: LOW (<5 refs) | MEDIUM (5-15) | HIGH (>15) + - If code intelligence not available: suggestions work as before (no blast radius shown) ### Review Phase 1. Display suggestions 2. Group by file/type -3. Show impact analysis +3. Show impact analysis (including blast radius and risk level when available) 4. Provide preview 5. Export for review diff --git a/.aios-core/install-manifest.yaml b/.aios-core/install-manifest.yaml index 34cfc13b9..c9471a5d1 100644 --- a/.aios-core/install-manifest.yaml +++ b/.aios-core/install-manifest.yaml @@ -8,9 +8,9 @@ # - File types for categorization # version: 4.2.13 -generated_at: "2026-02-17T01:52:56.970Z" +generated_at: "2026-02-17T12:48:43.195Z" generator: scripts/generate-install-manifest.js -file_count: 1006 +file_count: 1007 files: - path: cli/commands/config/index.js hash: sha256:ebcad2ce3807eda29dcddff76d7a95ddc9b7fa160df21fd608f94b802237e862 @@ -188,6 +188,10 @@ files: hash: sha256:0bea0c1953a21621afbb4c9755e782842940cf54cdc88a4318dd7242f1fb02a8 type: core size: 4320 + - path: core/code-intel/helpers/dev-helper.js + hash: sha256:2418a5f541003c73cc284e88a6b0cb666896a47ffd5ed4c08648269d281efc4c + type: core + size: 5770 - path: core/code-intel/index.js hash: sha256:ca8c54c2decbf64183d890ab42dc8ca2deafa675d4433492cb6ce423a284ad4d type: core @@ -859,7 +863,7 @@ files: - path: core/registry/registry-schema.json hash: sha256:02bc6cce5b4d7491e0c7cbfb27d50658196d231a96b34d39f0414c583f45d44e type: core - size: 5279 + size: 5445 - path: core/registry/service-registry.json hash: sha256:07123457d0b77216fb7074e0dfd94f23b1e425fe5b9af75caa2b5b1b3f5a7773 type: core @@ -1041,9 +1045,9 @@ files: type: data size: 34251 - path: data/entity-registry.yaml - hash: sha256:fefd5d2eba3de2c49a3dbf6219cda466062b05a05b894dc2f89886b1f937bd21 + hash: sha256:9cbf837d0b2151304c3ce8d28e6ac8efa1ef4b35a9dc4074bdbfaa9fd4afc77f type: data - size: 291072 + size: 291887 - path: data/learned-patterns.yaml hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc type: data @@ -1187,7 +1191,7 @@ files: - path: development/scripts/approval-workflow.js hash: sha256:10278d73d1904efcc0622c43ed07fa2434f6a96014f4d619dc503f078fdbbc99 type: script - size: 21553 + size: 22195 - path: development/scripts/audit-agent-config.js hash: sha256:861428491ec5bb6741877381fd7e8506b2150f8c81a00d061ae499b2480c524d type: script @@ -1199,7 +1203,7 @@ files: - path: development/scripts/backup-manager.js hash: sha256:4784782f5856bab5b405b95798614baf6e868853348a3a1dcf261bccf9547fce type: script - size: 16662 + size: 17268 - path: development/scripts/batch-update-agents-session-context.js hash: sha256:2f4c8b4f84b3cd86a5897909fcbb8d8c3ff4d48058fa9d04cbc924ab50f3fd32 type: script @@ -1207,19 +1211,19 @@ files: - path: development/scripts/branch-manager.js hash: sha256:2e6b1e434f3f5e2e1d1f1aec994c3fb56efccf7baacb4f188e769b13dabe03de type: script - size: 11536 + size: 11925 - path: development/scripts/code-quality-improver.js hash: sha256:acdfea90590a2d0d566e720540a8aad4a360cd531c58ad4e67cc4126522b7455 type: script - size: 39827 + size: 41138 - path: development/scripts/commit-message-generator.js hash: sha256:2e75d22307d0e3823b7762a6aff18c4c3842a632f876069215a221bc053336dc type: script - size: 25369 + size: 26218 - path: development/scripts/conflict-resolver.js hash: sha256:8971b9aca2ab23a9478ac70e59710ec843f483fcbe088371444f4fc9b56c5278 type: script - size: 19188 + size: 19862 - path: development/scripts/decision-context.js hash: sha256:ad19e9891fa3085ea1774a9d29efaaf871f13b361cd0691e844e3fd6a9c34ff3 type: script @@ -1239,7 +1243,7 @@ files: - path: development/scripts/dependency-analyzer.js hash: sha256:64d6433a789a68950758b467b47c8e4fb38cb4842ce5a3462bd3393d8553c9b2 type: script - size: 18024 + size: 18661 - path: development/scripts/dev-context-loader.js hash: sha256:63a43957d858e68142cd20ea19cc0aa648e58979ff75e1bec1f4c99c7d5def9f type: script @@ -1247,15 +1251,15 @@ files: - path: development/scripts/diff-generator.js hash: sha256:cad97b0096fc034fa6ed6cbd14a963abe32d880c1ce8034b6aa62af2e2239833 type: script - size: 10667 + size: 11018 - path: development/scripts/elicitation-engine.js hash: sha256:10f731ca75dbaf843997c4eb1a0e4619002463b6d697b8a145638260d90773ce type: script - size: 10583 + size: 10967 - path: development/scripts/elicitation-session-manager.js hash: sha256:4385acbfd7c184a38e123f7a20b5e7b06c1d89d645a6e1bae1c5e0e4232d5181 type: script - size: 8111 + size: 8410 - path: development/scripts/generate-greeting.js hash: sha256:49b857fe36a0216a0df8395a6847f14608bd6a228817276201d22598a6862a4f type: script @@ -1263,7 +1267,7 @@ files: - path: development/scripts/git-wrapper.js hash: sha256:2cc481d4cdaf2f34f6c907c54dcc6168f26859de3d1d3d71a6caf7a50de30e8c type: script - size: 11874 + size: 12335 - path: development/scripts/greeting-builder.js hash: sha256:a4a4ff094d41daf5840f55f807a775f698cb892e8c5d79f93148d4b437b0dadd type: script @@ -1279,11 +1283,11 @@ files: - path: development/scripts/manifest-preview.js hash: sha256:caccc28155efee736533622e3bc62c67abb9721e1f4e9bf761ef02f8d8a37026 type: script - size: 7527 + size: 7771 - path: development/scripts/metrics-tracker.js hash: sha256:e08baea0b02b2f54973794f9df786cee2432a98bd0ba0290e3922b025e629fef type: script - size: 21726 + size: 22501 - path: development/scripts/migrate-task-to-v2.js hash: sha256:50d0affb4b69de2237ec43c0a89d39d64faa40d25b76835d7ab8907553b4dc54 type: script @@ -1291,15 +1295,15 @@ files: - path: development/scripts/modification-validator.js hash: sha256:dc4d46220c92b968f4a9f18aebcf91fdf09bb01a2c7a40ffc46f696b2dc332ec type: script - size: 16486 + size: 17040 - path: development/scripts/pattern-learner.js hash: sha256:5bbc3f6f52e8fc6b65a2db072670e219f2e64e4cacfc448ccb839d3b4077493d type: script - size: 35067 + size: 36291 - path: development/scripts/performance-analyzer.js hash: sha256:6f59e8306afbbdae2795efc02ce21dfe336927526e99b5a40bddf37368a4614d type: script - size: 23410 + size: 24167 - path: development/scripts/populate-entity-registry.js hash: sha256:836f1261d296a949eb0c6d2e754afc1115854a39cff8927c82c6efd6fd693290 type: script @@ -1307,15 +1311,15 @@ files: - path: development/scripts/refactoring-suggester.js hash: sha256:d5183f79fae9dc4bf4d3c9136b3622e43a63643a7df622742c350931e45f18f4 type: script - size: 34675 + size: 35813 - path: development/scripts/rollback-handler.js hash: sha256:b18a9451fa3f8919733251857dbad2bc4b7ecbf782e6c114b88bc867358421a9 type: script - size: 16558 + size: 17088 - path: development/scripts/security-checker.js hash: sha256:8eb3952f865a045b2c7dfd9c3be42b42a97a7cf6d7cef8ac31002ab093c8bac0 type: script - size: 9520 + size: 9878 - path: development/scripts/skill-validator.js hash: sha256:1ce0d66fad12c9502ced60df2294a3002ee04c21a9d4b1607f57b237cbe057d6 type: script @@ -1383,15 +1387,15 @@ files: - path: development/scripts/template-engine.js hash: sha256:f388469146acad7c028190c8ca54286978e3db7da1dc1e214f1bf4bd03060fe0 type: script - size: 6957 + size: 7196 - path: development/scripts/template-validator.js hash: sha256:9f9039281dd3b8ca3fd8de29ae946b000f8235b10cf294a01d0cf1bf109356d8 type: script - size: 8331 + size: 8609 - path: development/scripts/test-generator.js hash: sha256:e552a212d859b0d71a141c219babc421d053530bbd2d3758b68ff0651c014aef type: script - size: 24936 + size: 25779 - path: development/scripts/test-greeting-system.js hash: sha256:a4b842ae6d1f7ea5224bd789e258b8dcda1b2e16b41c25f0cc603055eb091bda type: script @@ -1399,19 +1403,19 @@ files: - path: development/scripts/transaction-manager.js hash: sha256:c9a769a030b1357208852a1ac4a0cce756a2f3ba6b541a21699cf19be7472023 type: script - size: 17607 + size: 18196 - path: development/scripts/unified-activation-pipeline.js - hash: sha256:dd1ad8050ac6ea04ff634434be9b97f67239ee0a7342d669bc5618eb2b7a7f5b + hash: sha256:f822840facd618447032b71aefbde464dd2bce4aba630e5b4ec5241435761919 type: script - size: 29211 + size: 29786 - path: development/scripts/usage-tracker.js hash: sha256:b3079713787de7c6ac38a742255861f04e8359ef1b227836040920a64b7e8aac type: script - size: 19465 + size: 20138 - path: development/scripts/validate-filenames.js hash: sha256:20c20726b2f25ccef2ce301d421678a7c03e010c49469873b01ce1686dd66d8a type: script - size: 6247 + size: 6473 - path: development/scripts/validate-task-v2.js hash: sha256:5beacac341075d9ad7c393f1464b881c8c1d296da7fe1e97a4d4c97ff0208175 type: script @@ -1423,7 +1427,7 @@ files: - path: development/scripts/version-tracker.js hash: sha256:1c55ba6d8b2620c50546435231ac1b678e3f843627df326df8132182c0738801 type: script - size: 15887 + size: 16413 - path: development/scripts/workflow-navigator.js hash: sha256:d81e53dd6f41663af7bb822bf52c7a52678bdfb9046d295cde0bbb8ad0696c0c type: script @@ -1439,7 +1443,7 @@ files: - path: development/scripts/yaml-validator.js hash: sha256:b4a492a1dedbb11b6ddda9889ef6adb6cf792c2315c029ebc8c6b7ce7f57188f type: script - size: 10334 + size: 10730 - path: development/tasks/add-mcp.md hash: sha256:8a19ae5f343b68d7aace6a8400a18349fb7b4ebc92cecdab33e2a7f4f0d88512 type: task @@ -1525,9 +1529,9 @@ files: type: task size: 8997 - path: development/tasks/build-autonomous.md - hash: sha256:8e39b1c89f7f24f180101d82b37628019a07e84b16e5683b10ab196c35bf7028 + hash: sha256:332bf97df0ea910c9e8b8bb4f40ef42d0dd3ea929a719ca221478324ba23a366 type: task - size: 5617 + size: 6066 - path: development/tasks/build-component.md hash: sha256:992a116fae239712e6b371a61deb299ab592b58a5d64909664e2f5e22b7caeff type: task @@ -1601,9 +1605,9 @@ files: type: task size: 29544 - path: development/tasks/create-service.md - hash: sha256:6ce3eeeab6ed8ff6c5804b4fc4c3006c298009ab60c35b51afedac57082eeb34 + hash: sha256:31c4b50dbaede1c09d72a1dd5d9b1e5ca4edcbedc5204639d7399818e737c898 type: task - size: 8947 + size: 9882 - path: development/tasks/create-suite.md hash: sha256:8e57cba8aaed7f86a327e11185aca208af241ab41abc95188a2243375085ca15 type: task @@ -1713,9 +1717,9 @@ files: type: task size: 11021 - path: development/tasks/dev-develop-story.md - hash: sha256:6b76a6b428a1a45573431739d4740a78955a7af7a3156515d7151eb97bae2d90 + hash: sha256:6f7c7f5bc866ffd0bc1bf4ba90eee33aa02727e010f31b6457fcfa14d386c467 type: task - size: 26543 + size: 27075 - path: development/tasks/dev-improve-code-quality.md hash: sha256:8f8e6b0dcb1328cf7efcde263be95b93b2592176beafc7adfd3cdffbfa763be4 type: task @@ -1725,9 +1729,9 @@ files: type: task size: 29272 - path: development/tasks/dev-suggest-refactoring.md - hash: sha256:fb75f56fa178b72c9716a4a00f9a0df6a6d6348f362ef3e095cff45c16bd8f43 + hash: sha256:c69def336713b8ef2051c9aae725e3ecec228682c7adaeccd8a9a945bf59ab3a type: task - size: 24191 + size: 24669 - path: development/tasks/dev-validate-next-story.md hash: sha256:68af17e15d933588c5f82fac0133ad037a2941364f328f309bde09576f428b0a type: task @@ -2267,19 +2271,19 @@ files: - path: development/templates/service-template/__tests__/index.test.ts.hbs hash: sha256:04090b95bc0b606448c161d8e698fcf4d5c7da2517a5ac65663554a54c5acf91 type: template - size: 9573 + size: 9810 - path: development/templates/service-template/client.ts.hbs hash: sha256:3adbfb5a17d7f734a498bd2520fd44a1eadf05aad9f31b980f886ad6386394a6 type: template - size: 11810 + size: 12213 - path: development/templates/service-template/errors.ts.hbs hash: sha256:cc7139c0a2654dbd938ba79730fc97b6d30a79b8d1556fe43c61e0fca6553351 type: template - size: 5213 + size: 5395 - path: development/templates/service-template/index.ts.hbs hash: sha256:29d66364af401592a3ea0d5c4c4ebfb09e67373e62f21caac82b47b1bf78b3b8 type: template - size: 3086 + size: 3206 - path: development/templates/service-template/jest.config.js hash: sha256:1681bfd7fbc0d330d3487d3427515847c4d57ef300833f573af59e0ad69ed159 type: template @@ -2287,11 +2291,11 @@ files: - path: development/templates/service-template/package.json.hbs hash: sha256:7a25b377c72a98e44758afbe5a5b6d95971e47cca8e248b664ec63d7d1b7a590 type: template - size: 2227 + size: 2314 - path: development/templates/service-template/README.md.hbs hash: sha256:be6e4531587c37cc2ce1542dbd0c5487752d57f58c84e5dd23978d4173746c2e type: template - size: 3426 + size: 3584 - path: development/templates/service-template/tsconfig.json hash: sha256:8b465fcbdd45c4d6821ba99aea62f2bd7998b1bca8de80486a1525e77d43c9a1 type: template @@ -2299,7 +2303,7 @@ files: - path: development/templates/service-template/types.ts.hbs hash: sha256:2338ab2e1ade619bf33a2c8f22b149402b513c05a6d1d8a805c5273c7233d151 type: template - size: 2516 + size: 2661 - path: development/templates/squad-template/agents/example-agent.yaml hash: sha256:824a1b349965e5d4ae85458c231b78260dc65497da75dada25b271f2cabbbe67 type: agent @@ -2307,7 +2311,7 @@ files: - path: development/templates/squad-template/LICENSE hash: sha256:ff7017aa403270cf2c440f5ccb4240d0b08e54d8bf8a0424d34166e8f3e10138 type: template - size: 1071 + size: 1092 - path: development/templates/squad-template/package.json hash: sha256:c276fe1a238d9587f72cba1fabafae4ca227d212128f7ad339210c3b6a1bd955 type: template @@ -3035,11 +3039,11 @@ files: - path: infrastructure/templates/aios-sync.yaml.template hash: sha256:a22718c4eec5b7bc808cb283f18a96c96cfcbbed4a0ffec6e332da45a4a0a549 type: template - size: 8385 + size: 8567 - path: infrastructure/templates/coderabbit.yaml.template hash: sha256:a8f8e08e5c109b4c635a468e9b400bfb35361073de8a0883c5d4c9db84d7ed0a type: template - size: 8042 + size: 8321 - path: infrastructure/templates/core-config/core-config-brownfield.tmpl.yaml hash: sha256:de54c7ffc1d785ff2aa43fb268c0dc0ad8a7215b77080a4dc0aaf5e49e02bc58 type: template @@ -3051,11 +3055,11 @@ files: - path: infrastructure/templates/github-workflows/ci.yml.template hash: sha256:ad7ea9f338b7bfec281a6136d40df3954cbaf239245e41e2eb227abf15d001d4 type: template - size: 4920 + size: 5089 - path: infrastructure/templates/github-workflows/pr-automation.yml.template hash: sha256:46c334bd347a0b36a8de55a4c1db2eb9e66b350555a50439b05000f05fbe307b type: template - size: 10609 + size: 10939 - path: infrastructure/templates/github-workflows/README.md hash: sha256:d498f88d14a2eea695ff01dfb27886a9838576bf2be9a4dcbd923d5ae4b9f094 type: template @@ -3063,23 +3067,23 @@ files: - path: infrastructure/templates/github-workflows/release.yml.template hash: sha256:bd40c93023c56489a45690a5829beda662f738f0687beb46bef31475ceee8027 type: template - size: 6595 + size: 6791 - path: infrastructure/templates/gitignore/gitignore-aios-base.tmpl hash: sha256:eea52813b21c411ada64d2560913cc853a53b8d00ad916f0c9480cd11324b764 type: template - size: 788 + size: 851 - path: infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl hash: sha256:da10b4280d52fe7a76649d11ed9d72d452ece94bb5d46e06705ca585589d9e20 type: template - size: 488 + size: 506 - path: infrastructure/templates/gitignore/gitignore-node.tmpl hash: sha256:46d261d54d9b57cdecd54ae2d6f19b9971b380316700824caf6026543b6afe5b type: template - size: 951 + size: 1036 - path: infrastructure/templates/gitignore/gitignore-python.tmpl hash: sha256:f8da7c8fb5888a59332e63ea5137ed808f6cf1075fd175104a79c44479c749ba type: template - size: 1580 + size: 1725 - path: infrastructure/templates/project-docs/coding-standards-tmpl.md hash: sha256:f5eeba2464907e57fad287d842febc64ad22d27f2d33ea2fe74151646a57aaee type: template @@ -3171,47 +3175,47 @@ files: - path: manifests/schema/manifest-schema.json hash: sha256:39678986089918893f309a2469fa0615beb82b5c6f1e16e2f9b40bcac6465195 type: manifest - size: 5291 + size: 5481 - path: monitor/hooks/lib/__init__.py hash: sha256:26147f29392400ed7bb87ca750af1c1bdd191193990463952282eaaffc1f35a2 type: monitor - size: 29 + size: 30 - path: monitor/hooks/lib/enrich.py hash: sha256:f796c327b54e5282027babe325f9629ad21440275c2a3fdb277840898bdf3653 type: monitor - size: 1644 + size: 1702 - path: monitor/hooks/lib/send_event.py hash: sha256:2ec9ec9abfded4c0b67a49429d192f171758c0fb4e8a1bf1e47f2c8e32aa47ea type: monitor - size: 1190 + size: 1237 - path: monitor/hooks/notification.py hash: sha256:ae9e484772e090c557fcda3be46d19b9c48d7bec9789652cbfec17d7616a956f type: monitor - size: 499 + size: 528 - path: monitor/hooks/post_tool_use.py hash: sha256:5599de99f3292ce7b57ad754abe9a0bfb462b1babc95a2bab22016528eb2515b type: monitor - size: 1140 + size: 1185 - path: monitor/hooks/pre_compact.py hash: sha256:df11373948b986814a7602a9dd61a384055de13392a7aa246063b4c4ea75fddd type: monitor - size: 500 + size: 529 - path: monitor/hooks/pre_tool_use.py hash: sha256:e4a7bbd6cbb6e17b819f629ef88a24947612f4dffbe19fab897b9ff4a409efc2 type: monitor - size: 981 + size: 1021 - path: monitor/hooks/stop.py hash: sha256:9737bcedd34cfdf459641e2f0e74eacf7a56d0e7ad0fb05a32a40c0afc87443e type: monitor - size: 490 + size: 519 - path: monitor/hooks/subagent_stop.py hash: sha256:cfe2b5361a0b668f90d738bcd18f478e2ea49459304b203608377a1226d2bebb type: monitor - size: 512 + size: 541 - path: monitor/hooks/user_prompt_submit.py hash: sha256:f8f9a7550121832811c2d2d12b93d5d42fa7180ddec85c49ae3841c9d259ab76 type: monitor - size: 818 + size: 856 - path: package.json hash: sha256:dff580c83cc1554c75162c9cabb711b5cd85e679c9c8f4968ee74499e99de0c0 type: other @@ -3359,7 +3363,7 @@ files: - path: product/templates/adr.hbs hash: sha256:401c2a3ce81905cd4665439d4e2afece92a7c93a1499a927b3522272e6a58027 type: template - size: 2212 + size: 2337 - path: product/templates/agent-template.yaml hash: sha256:4ad34c41d9e7546c208e4680faa8a30969d6505d59d17111b27d2963a8a22e73 type: template @@ -3403,7 +3407,7 @@ files: - path: product/templates/component-react-tmpl.tsx hash: sha256:bfbfab502da2064527948f70c9a59174f20b81472ac2ea6eb999f02c9bcaf3df type: template - size: 2588 + size: 2686 - path: product/templates/current-approach-tmpl.md hash: sha256:ec258049a5cda587b24523faf6b26ed0242765f4e732af21c4f42e42cf326714 type: template @@ -3411,7 +3415,7 @@ files: - path: product/templates/dbdr.hbs hash: sha256:67de8a2a0fd90ed71111cb31a4c84209ff8b09b4ae263158a0f545ae3ac84cc5 type: template - size: 4139 + size: 4380 - path: product/templates/design-story-tmpl.yaml hash: sha256:bbf1a20323b217b668c8466307988e505e49f4e472df47b6411b6037511c9b7d type: template @@ -3439,35 +3443,35 @@ files: - path: product/templates/engine/schemas/adr.schema.json hash: sha256:2cd4c78d9c2664695df163d033709122b0b37c70fd4f92c9bf4ea17503d4db0b type: template - size: 2915 + size: 3017 - path: product/templates/engine/schemas/dbdr.schema.json hash: sha256:9d5f4e3774830f545617e801ec24ea6649afb2ab217fffda4f6fa3ec5136f2ea type: template - size: 5731 + size: 5936 - path: product/templates/engine/schemas/epic.schema.json hash: sha256:c2e898276cf89338b9fa8d619c18c40d1ed1e4390d63cc779b439c37380a5317 type: template - size: 4491 + size: 4666 - path: product/templates/engine/schemas/pmdr.schema.json hash: sha256:3e3883d552f2fa0f1b9cd6d1621e9788858d81f2c9faa66fbdfc20744cddf855 type: template - size: 4789 + size: 4964 - path: product/templates/engine/schemas/prd-v2.schema.json hash: sha256:b6a5fcb6aa6ba4417f55673f2432fdc96d3b178ccd494b56796b74271cbe9ebe type: template - size: 7822 + size: 8122 - path: product/templates/engine/schemas/prd.schema.json hash: sha256:a68c16308518ee12339d63659bef8b145d0101dcf7fe1e4e06ccad1c20a4b61a type: template - size: 4306 + size: 4458 - path: product/templates/engine/schemas/story.schema.json hash: sha256:23d037e35a7ebecc6af86ef30223b2c20e3a938a4c9f4b6ca18a8cec6646a005 type: template - size: 5884 + size: 6106 - path: product/templates/engine/schemas/task.schema.json hash: sha256:01ed077417b76d54bb2aa93f94d3ca4b9587bb957dd269ff31f7f707f1efda37 type: template - size: 3856 + size: 4010 - path: product/templates/engine/validator.js hash: sha256:159422012586b65933dca98f7cc0274ebc8a867c79533340b548fc9eaca41944 type: template @@ -3475,11 +3479,11 @@ files: - path: product/templates/epic.hbs hash: sha256:abc175a126ff12aaf8fc06201fd36ea8415806d49b95bb86197829997c17a610 type: template - size: 3868 + size: 4080 - path: product/templates/eslintrc-security.json hash: sha256:657d40117261d6a52083984d29f9f88e79040926a64aa4c2058a602bfe91e0d5 type: template - size: 909 + size: 941 - path: product/templates/front-end-architecture-tmpl.yaml hash: sha256:de0432b4f98236c3a1d6cc9975b90fbc57727653bdcf6132355c0bcf0b4dbb9c type: template @@ -3499,11 +3503,11 @@ files: - path: product/templates/github-actions-cd.yml hash: sha256:c9ef00ed1a691d634bb6a4927b038c96dcbc65e4337432eb2075e9ef302af85b type: template - size: 6992 + size: 7204 - path: product/templates/github-actions-ci.yml hash: sha256:b64abbfdaf10b61d28ce0391fbcc2c54136cf14f4996244808341bb5ced0168e type: template - size: 4492 + size: 4664 - path: product/templates/github-pr-template.md hash: sha256:f04dc7a2a98f3ada40a54a62d93ed2ee289c4b11032ef420acf10fbfe19d1dc5 type: template @@ -3583,7 +3587,7 @@ files: - path: product/templates/pmdr.hbs hash: sha256:90cb8dcb877938af538a6c7470233a0d908dc1a1041cffe845ad196887ab13a5 type: template - size: 3239 + size: 3425 - path: product/templates/prd-tmpl.yaml hash: sha256:f94734d78f9df14e0236719dfc63666a4506bcc076fbcdb5e5c5e5e1a3660876 type: template @@ -3591,11 +3595,11 @@ files: - path: product/templates/prd-v2.0.hbs hash: sha256:6a716525255c1236d75bfc1e2be6005006ba827fdf2b4d55e7453140a13df71a type: template - size: 4512 + size: 4728 - path: product/templates/prd.hbs hash: sha256:b110a469ae0ba12ccaf5cae59daefbf08ba6e1b96cb6f1d5afc49c1a2d6739d3 type: template - size: 3425 + size: 3626 - path: product/templates/project-brief-tmpl.yaml hash: sha256:b8d388268c24dc5018f48a87036d591b11cb122fafe9b59c17809b06ea5d9d58 type: template @@ -3619,7 +3623,7 @@ files: - path: product/templates/shock-report-tmpl.html hash: sha256:f6b3984683b9c0e22550aaab63f002c01d6d9d3fe2af0e344f7dafbd444e4a19 type: template - size: 16665 + size: 17167 - path: product/templates/spec-tmpl.md hash: sha256:5f3a97a1d4cc5c0fe81432d942cdd3ac2ec43c6785c3594ba3e1070601719718 type: template @@ -3643,7 +3647,7 @@ files: - path: product/templates/story.hbs hash: sha256:5a51064b2e371b3e2b22080df2993da0c2517c442c80e3cada3006387a4d29ab type: template - size: 5583 + size: 5846 - path: product/templates/task-execution-report.md hash: sha256:6ca0126115ddb0c31b584a964a9938dbbbb8e187e02d6001bd5b69d3d4359992 type: template @@ -3655,71 +3659,71 @@ files: - path: product/templates/task.hbs hash: sha256:6aacffe2c92bf87d3040f2de75f45a586d819f1f73fcdabfadeca6ecb30f1f20 type: template - size: 2705 + size: 2875 - path: product/templates/tmpl-comment-on-examples.sql hash: sha256:254002c3fbc63cfcc5848b1d4b15822ce240bf5f57e6a1c8bb984e797edc2691 type: template - size: 6215 + size: 6373 - path: product/templates/tmpl-migration-script.sql hash: sha256:44ef63ea475526d21a11e3c667c9fdb78a9fddace80fdbaa2312b7f2724fbbb5 type: template - size: 2947 + size: 3038 - path: product/templates/tmpl-rls-granular-policies.sql hash: sha256:36c2fd8c6d9eebb5d164acb0fb0c87bc384d389264b4429ce21e77e06318f5f3 type: template - size: 3322 + size: 3426 - path: product/templates/tmpl-rls-kiss-policy.sql hash: sha256:5210d37fce62e5a9a00e8d5366f5f75653cd518be73fbf96333ed8a6712453c7 type: template - size: 299 + size: 309 - path: product/templates/tmpl-rls-roles.sql hash: sha256:2d032a608a8e87440c3a430c7d69ddf9393d8813d8d4129270f640dd847425c3 type: template - size: 4592 + size: 4727 - path: product/templates/tmpl-rls-simple.sql hash: sha256:f67af0fa1cdd2f2af9eab31575ac3656d82457421208fd9ccb8b57ca9785275e type: template - size: 2915 + size: 2992 - path: product/templates/tmpl-rls-tenant.sql hash: sha256:36629ed87a2c72311809cc3fb96298b6f38716bba35bc56c550ac39d3321757a type: template - size: 4978 + size: 5130 - path: product/templates/tmpl-rollback-script.sql hash: sha256:8b84046a98f1163faf7350322f43831447617c5a63a94c88c1a71b49804e022b type: template - size: 2657 + size: 2734 - path: product/templates/tmpl-seed-data.sql hash: sha256:a65e73298f46cd6a8e700f29b9d8d26e769e12a57751a943a63fd0fe15768615 type: template - size: 5576 + size: 5716 - path: product/templates/tmpl-smoke-test.sql hash: sha256:aee7e48bb6d9c093769dee215cacc9769939501914e20e5ea8435b25fad10f3c type: template - size: 723 + size: 739 - path: product/templates/tmpl-staging-copy-merge.sql hash: sha256:55988caeb47cc04261665ba7a37f4caa2aa5fac2e776fdbc5964e0587af24450 type: template - size: 4081 + size: 4220 - path: product/templates/tmpl-stored-proc.sql hash: sha256:2b205ff99dc0adfade6047a4d79f5b50109e50ceb45386e5c886437692c7a2a3 type: template - size: 3839 + size: 3979 - path: product/templates/tmpl-trigger.sql hash: sha256:93abdc92e1b475d1370094e69a9d1b18afd804da6acb768b878355c798bd8e0e type: template - size: 5272 + size: 5424 - path: product/templates/tmpl-view-materialized.sql hash: sha256:47935510f03d4ad9b2200748e65441ce6c2d6a7c74750395eca6831d77c48e91 type: template - size: 4363 + size: 4496 - path: product/templates/tmpl-view.sql hash: sha256:22557b076003a856b32397f05fa44245a126521de907058a95e14dd02da67aff type: template - size: 4916 + size: 5093 - path: product/templates/token-exports-css-tmpl.css hash: sha256:d937b8d61cdc9e5b10fdff871c6cb41c9f756004d060d671e0ae26624a047f62 type: template - size: 5798 + size: 6038 - path: product/templates/token-exports-tailwind-tmpl.js hash: sha256:1e99f1be493b4b3dac1b2a9abc1ae1dd9146f26f86bed229c232690114c3a377 type: template @@ -3923,7 +3927,7 @@ files: - path: scripts/migrate-framework-docs.sh hash: sha256:b453931ec91e85b7f2e71d8508960e742aaa85fa44a89221ff257d472ab61ca3 type: script - size: 9488 + size: 9788 - path: scripts/pm.sh hash: sha256:ee05da6dc99078b710a34f9fb420684ff19876bcc0322571f1057a56cbbb6011 type: script diff --git a/docs/qa/gates/nog-3-dev-task-enhancement.yml b/docs/qa/gates/nog-3-dev-task-enhancement.yml new file mode 100644 index 000000000..899fc9bc7 --- /dev/null +++ b/docs/qa/gates/nog-3-dev-task-enhancement.yml @@ -0,0 +1,48 @@ +schema: 1 +story: NOG-3 +story_title: 'Dev Task Enhancement (IDS G4 + Conventions)' +gate: PASS +status_reason: 'All 4 ACs met with full test coverage (24/24). Graceful fallback verified for all functions. Task modifications are non-blocking advisory. No regressions in code-intel suite (116/116).' +reviewer: 'Quinn (Test Architect)' +updated: '2026-02-17T02:30:00.000Z' + +top_issues: [] +# Previously identified LOW issues resolved during review: +# - Dead code placeholder removed (enricher.findTests ? null : null) +# - REUSE/ADAPT threshold extracted to REUSE_MIN_REFS constant + +waiver: + active: false + +quality_score: 100 +expires: '2026-03-03T02:30:00.000Z' + +evidence: + tests_reviewed: + count: 24 + suite_total: 116 + all_passing: true + risks_identified: + count: 0 + trace: + ac_covered: [1, 2, 3, 4] + ac_gaps: [] + +nfr_validation: + security: + status: PASS + notes: 'No user input, no file mutations, no credentials. Read-only provider calls wrapped in try/catch.' + performance: + status: PASS + notes: 'Concurrent calls via Promise.all. Inherits circuit breaker (3 failures) and session cache (5min TTL). 5s timeout.' + reliability: + status: PASS + notes: 'Zero-throw guarantee. All functions return null gracefully on any error condition.' + maintainability: + status: PASS + notes: 'JSDoc on all public functions. Constants exported. Private helpers prefixed with underscore. Test coverage comprehensive.' + +recommendations: + immediate: [] + future: [] + # All previously identified issues resolved during QA review diff --git a/docs/stories/epics/epic-nogic-code-intelligence/story-NOG-3-dev-task-enhancement.md b/docs/stories/epics/epic-nogic-code-intelligence/story-NOG-3-dev-task-enhancement.md new file mode 100644 index 000000000..1c20805db --- /dev/null +++ b/docs/stories/epics/epic-nogic-code-intelligence/story-NOG-3-dev-task-enhancement.md @@ -0,0 +1,442 @@ +# Story NOG-3: Dev Task Enhancement (IDS G4 + Conventions) + +## Metadata +- **Story ID:** NOG-3 +- **Epic:** Code Intelligence Integration (Provider-Agnostic) +- **Status:** Ready for Review +- **Priority:** P1 - High +- **Points:** 3 +- **Agent:** @dev (Dex) +- **Blocked By:** NOG-1 +- **Created:** 2026-02-15 +- **Updated:** 2026-02-16 (v3.0 — PO validation auto-fix) + +--- + +## Executor Assignment + +```yaml +executor: "@dev" +quality_gate: "@architect" +quality_gate_tools: + - code-review + - pattern-compliance + - task-integration-review +``` + +--- + +## Story + +**As a** @dev agent, +**I want** code intelligence integrated into my development tasks (IDS G4 automatic, conventions check, duplicate detection), +**so that** I can automatically detect duplication before creating code, follow existing naming conventions, and get blast radius information for refactoring — all with graceful fallback when no provider is available. + +--- + +## Description + +Integrar code intelligence nas tasks de desenvolvimento do @dev para automatizar o IDS Gate G4 (antes de criar codigo) e enriquecer o fluxo de desenvolvimento com visao semantica do codebase. + +### Tasks Impactadas + +| Task | Capabilities Usadas | Integracao | +|------|---------------------|-----------| +| `dev-develop-story.md` | findReferences, getConventions, findDefinition | Antes de cada novo arquivo/funcao, verificar duplicacao e naming | +| `create-service.md` | detectDuplicates, analyzeCodebase | Antes de scaffoldar, verificar se service similar existe | +| `dev-suggest-refactoring.md` | findReferences, assessImpact | Sugestoes baseadas em blast radius real | +| `build-autonomous.md` | detectDuplicates, getConventions | IDS G4 automatico no loop autonomo | + +--- + +## Acceptance Criteria + +### AC1: IDS Gate G4 Automatico +- [ ] **Given** @dev esta no modo YOLO ou Interactive +- [ ] **When** vai criar um novo arquivo ou funcao +- [ ] **Then** `detectDuplicates` e chamado automaticamente, resultado mostrado como "Code Intelligence Suggestion" (se provider disponivel) + +### AC2: Duplicate Detection +- [ ] **Given** @dev vai criar novo modulo/servico +- [ ] **When** `findReferences` detecta entidade similar existente +- [ ] **Then** mostra aviso com link para codigo existente e sugere REUSE ou ADAPT + +### AC3: Refactoring Intelligence +- [ ] **Given** @dev executa `*suggest-refactoring` +- [ ] **When** provider disponivel +- [ ] **Then** sugestoes incluem blast radius (arquivos afetados) e risk level (LOW/MEDIUM/HIGH) + +### AC4: Fallback sem Provider +- [ ] **Given** NENHUM provider disponivel +- [ ] **When** @dev executa qualquer task +- [ ] **Then** tasks funcionam exatamente como antes, sem nenhuma diferenca visivel + +--- + +## Tasks / Subtasks + +- [x] 1. Criar helper `.aios-core/core/code-intel/helpers/dev-helper.js` (AC: #1, #2) + - [x] 1.1 Implementar `checkBeforeWriting(fileName, description)` — chama detectDuplicates + findReferences + - [x] 1.2 Implementar `suggestReuse(symbol)` — chama findReferences + findDefinition, formata sugestao REUSE/ADAPT + - [x] 1.3 Implementar `getConventionsForPath(path)` — chama getConventions, retorna naming patterns + - [x] 1.4 Implementar `assessRefactoringImpact(files)` — chama assessImpact, retorna blast radius + risk level + - [x] 1.5 Todas as funcoes retornam null gracefully se provider indisponivel +- [x] 2. Modificar `dev-develop-story.md` — adicionar checkpoint code intelligence antes de criar arquivo (AC: #1, #4) + - [x] 2.1 Adicionar step "Code Intelligence Check" antes de criar novos arquivos + - [x] 2.2 Importar dev-helper, chamar `checkBeforeWriting()`, exibir resultado como "Code Intelligence Suggestion" + - [x] 2.3 Garantir que step e skipped silenciosamente se `isCodeIntelAvailable()` retorna false +- [x] 3. Modificar `create-service.md` — verificar duplicacao antes de scaffold (AC: #2, #4) + - [x] 3.1 Adicionar step pre-scaffold que chama `checkBeforeWriting()` com nome do service + - [x] 3.2 Se matches encontrados, exibir aviso e sugerir REUSE/ADAPT antes de prosseguir + - [x] 3.3 Garantir fallback graceful (scaffold continua normalmente sem provider) +- [x] 4. Modificar `dev-suggest-refactoring.md` — adicionar blast radius (AC: #3, #4) + - [x] 4.1 Adicionar step que chama `assessRefactoringImpact()` para cada arquivo candidato + - [x] 4.2 Incluir blast radius e risk level (LOW: <5 refs, MEDIUM: 5-15, HIGH: >15) no output + - [x] 4.3 Garantir fallback graceful (sugestoes funcionam sem blast radius se provider indisponivel) +- [x] 5. Modificar `build-autonomous.md` — IDS G4 automatico no loop autonomo (AC: #1, #4) + - [x] 5.1 Adicionar checkpoint code intelligence no loop de criacao de arquivos + - [x] 5.2 Chamar `checkBeforeWriting()` antes de cada write operation + - [x] 5.3 Logar resultado em decision-log se duplicacao detectada +- [x] 6. Escrever testes unitarios para dev-helper.js (AC: #1, #2, #3, #4) + - [x] 6.1 Testes com provider mockado (happy path) + - [x] 6.2 Testes sem provider (fallback graceful — retorna null) + - [x] 6.3 Teste de integracao: checkBeforeWriting com match real vs sem match + +--- + +## Scope + +**IN:** +- Helper `dev-helper.js` com funcoes de code intelligence para @dev +- Modificacao de `dev-develop-story.md` — checkpoint pre-criacao de arquivo +- Modificacao de `create-service.md` — verificacao pre-scaffold +- Modificacao de `dev-suggest-refactoring.md` — blast radius em sugestoes +- Modificacao de `build-autonomous.md` — IDS G4 no loop autonomo +- Testes unitarios para dev-helper.js +- Fallback graceful em todas as integracoes + +**OUT:** +- Outros helpers (qa-helper, planning-helper, story-helper) — stories NOG-4 a NOG-8 +- Modificacao de tasks de outros agentes (@qa, @sm, @po, etc.) +- Novos providers de code intelligence +- UI/Dashboard para code intelligence +- Modificacao do code-intel-client ou enricher (consumo apenas) + +--- + +## Risks + +| Risco | Prob. | Impacto | Mitigacao | +|-------|-------|---------|-----------| +| Modificacao de tasks quebra comportamento existente | Media | Alto | Testes de regressao antes/depois; fallback graceful obrigatorio | +| `checkBeforeWriting()` adiciona latencia ao fluxo de dev | Baixa | Medio | Timeout 5s (herdado do client); skip se provider indisponivel | +| Falsos positivos de duplicacao confundem @dev | Media | Medio | Exibir como "Suggestion" (nao blocker); incluir link para codigo similar | +| Task markdown injection causa efeitos colaterais | Baixa | Medio | Adicionar steps como blocos isolados; testar tasks modificadas manualmente | + +--- + +## Definition of Done + +- [x] `dev-helper.js` criado com 4+ funcoes (checkBeforeWriting, suggestReuse, getConventionsForPath, assessRefactoringImpact) +- [x] Todas as funcoes retornam null gracefully sem provider (0 throws) +- [x] `dev-develop-story.md` tem checkpoint code intelligence funcional +- [x] `create-service.md` verifica duplicacao antes de scaffold +- [x] `dev-suggest-refactoring.md` inclui blast radius quando provider disponivel +- [x] `build-autonomous.md` tem IDS G4 no loop autonomo +- [x] Testes unitarios passando (>80% coverage no dev-helper.js) +- [x] Nenhuma regressao nas 4 tasks modificadas (funcionam identicamente sem provider) +- [x] Entidades registradas no entity-registry.yaml + +--- + +## Dev Notes + +### Source Tree Relevante + +``` +aios-core/ +├── .aios-core/ +│ ├── core/ +│ │ └── code-intel/ +│ │ ├── index.js # Public API (getEnricher, enrichWithCodeIntel, isCodeIntelAvailable) +│ │ ├── code-intel-client.js # 8 primitive capabilities + circuit breaker + cache +│ │ ├── code-intel-enricher.js # 5 composite capabilities (detectDuplicates, assessImpact, etc.) +│ │ ├── providers/ +│ │ │ ├── provider-interface.js # Abstract contract +│ │ │ └── code-graph-provider.js # Code Graph MCP adapter +│ │ └── helpers/ # NOVO — criado nesta story +│ │ └── dev-helper.js # Create — helper para @dev tasks +│ └── development/ +│ └── tasks/ +│ ├── dev-develop-story.md # Modify — adicionar checkpoint code intel +│ ├── create-service.md # Modify — verificar duplicacao pre-scaffold +│ ├── dev-suggest-refactoring.md # Modify — adicionar blast radius +│ └── build-autonomous.md # Modify — IDS G4 no loop autonomo +└── tests/ + └── code-intel/ + ├── code-intel-client.test.js # Existente (NOG-1) + ├── code-intel-enricher.test.js # Existente (NOG-1) + └── dev-helper.test.js # Create — testes do helper +``` + +### Contexto de NOG-1 (Predecessor — Done) + +O modulo `code-intel` esta completo e funcional (66/66 testes): + +**API principal para consumo nesta story:** + +```javascript +// Importar via index.js +const { getEnricher, isCodeIntelAvailable, enrichWithCodeIntel } = require('.aios-core/core/code-intel'); + +// Verificar disponibilidade (OBRIGATORIO antes de chamar) +if (isCodeIntelAvailable()) { + const enricher = getEnricher(); + + // Composite capabilities (usadas no dev-helper) + const dupes = await enricher.detectDuplicates(description, { path: '.' }); + // → { matches: [...], codebaseOverview: {...} } ou null + + const impact = await enricher.assessImpact(['file1.js', 'file2.js']); + // → { references: [...], complexity: {...}, blastRadius: N } ou null + + const conventions = await enricher.getConventions('src/'); + // → { patterns: [...], stats: {...} } ou null +} + +// Ou via enrichWithCodeIntel (fallback automatico) +const result = await enrichWithCodeIntel(baseResult, { + capabilities: ['detectDuplicates', 'assessImpact'], + timeout: 5000, + fallbackBehavior: 'warn-and-continue' +}); +// → { ...baseResult, _codeIntel: { detectDuplicates: {...}, assessImpact: {...} } } +``` + +**Garantias do modulo:** +- Nunca lanca excecao (try/catch em todas as capabilities) +- Circuit breaker: abre apos 3 falhas consecutivas, reseta em 60s +- Session cache: TTL 5min, evita re-queries identicas +- `isCodeIntelAvailable()` retorna false se nenhum provider configurado + +### Contexto Tecnico + +- **CommonJS:** Usar `require()` / `module.exports` (padrao do projeto) +- **Diretorio helpers/:** Nao existe ainda — criar `helpers/` dentro de `.aios-core/core/code-intel/` +- **Pattern de integracao em tasks:** Adicionar steps markdown que instruem o agente a chamar o helper; usar linguagem condicional ("se code intelligence disponivel, executar...") +- **Risk Level mapping:** LOW (<5 refs), MEDIUM (5-15 refs), HIGH (>15 refs) — baseado em blastRadius + +### Testing + +**Framework:** Jest (padrao do projeto) +**Location:** `tests/code-intel/dev-helper.test.js` + +| # | Cenario | Tipo | AC Ref | Esperado | +|---|---------|------|--------|----------| +| T1 | checkBeforeWriting com provider (match encontrado) | Unit | AC1 | Retorna { duplicates, suggestion } | +| T2 | checkBeforeWriting com provider (sem match) | Unit | AC1 | Retorna null ou resultado vazio | +| T3 | checkBeforeWriting sem provider | Unit | AC4 | Retorna null, sem throw | +| T4 | suggestReuse encontra definicao existente | Unit | AC2 | Retorna { file, line, suggestion: 'REUSE' } | +| T5 | suggestReuse sem match | Unit | AC2 | Retorna null | +| T6 | assessRefactoringImpact com blast radius | Unit | AC3 | Retorna { blastRadius, riskLevel } | +| T7 | assessRefactoringImpact sem provider | Unit | AC4 | Retorna null | +| T8 | getConventionsForPath retorna patterns | Unit | AC1 | Retorna { patterns, stats } | +| T9 | Todas as funcoes fallback (provider indisponivel) | Integration | AC4 | 4/4 retornam null | + +**Mocking:** Mock do `getEnricher()` e `isCodeIntelAvailable()` de `.aios-core/core/code-intel/index.js`. + +--- + +## CodeRabbit Integration + +### Story Type Analysis + +**Primary Type:** Code/Features/Logic (helper module + task modifications) +**Secondary Type(s):** Process Integration (task workflow enhancement) +**Complexity:** Medium + +### Specialized Agent Assignment + +**Primary Agents:** +- @dev: Implementation of dev-helper.js, task modifications, and tests + +**Supporting Agents:** +- @architect: Quality gate review (pattern compliance, task integration correctness) + +### Quality Gate Tasks + +- [ ] Pre-Commit (@dev): Run before marking story complete +- [ ] Pre-PR (@devops): Run before creating pull request + +### Self-Healing Configuration + +**Expected Self-Healing:** +- Primary Agent: @dev (light mode) +- Max Iterations: 2 +- Timeout: 15 minutes +- Severity Filter: CRITICAL only + +**Predicted Behavior:** +- CRITICAL issues: auto_fix (2 iterations max) +- HIGH issues: document_as_debt + +### CodeRabbit Focus Areas + +**Primary Focus:** +- Fallback graceful em todas as funcoes do dev-helper (zero throws sem provider) +- Integracao correta com enricher API (parametros, return types) +- Task modifications nao quebram fluxo existente + +**Secondary Focus:** +- Risk level calculation consistency +- Suggestion formatting (REUSE vs ADAPT decision) + +--- + +## File List + +| File | Action | +|------|--------| +| `.aios-core/core/code-intel/helpers/dev-helper.js` | Create | +| `.aios-core/development/tasks/dev-develop-story.md` | Modify | +| `.aios-core/development/tasks/create-service.md` | Modify | +| `.aios-core/development/tasks/dev-suggest-refactoring.md` | Modify | +| `.aios-core/development/tasks/build-autonomous.md` | Modify | +| `tests/code-intel/dev-helper.test.js` | Create | +| `.aios-core/data/entity-registry.yaml` | Modify (add dev-helper entity) | + +--- + +## Dev Agent Record + +_Populated by @dev during implementation._ + +### Agent Model Used +Claude Opus 4.6 + +### Debug Log References +- Nenhum debug necessario — 24/24 testes passaram na primeira execucao + +### Completion Notes List +- `dev-helper.js` criado com 4 funcoes publicas + 2 helpers privados + constantes RISK_THRESHOLDS +- Todas as funcoes implementam fallback graceful (retornam null sem provider, sem throw) +- 4 tasks modificadas com checkpoints code intelligence (todos condicionais/advisory) +- 24 testes unitarios cobrindo cenarios T1-T9 da story + edge cases +- Pattern de integracao: steps markdown condicionais ("se code intelligence disponivel...") +- Risk level mapping: LOW (<=4 refs), MEDIUM (5-15 refs), HIGH (>15 refs) + +### File List (Implementation) +| File | Action | Details | +|------|--------|---------| +| `.aios-core/core/code-intel/helpers/dev-helper.js` | Created | 4 public functions, 2 private helpers, RISK_THRESHOLDS | +| `tests/code-intel/dev-helper.test.js` | Created | 24 tests (T1-T9 + edge cases), all PASS | +| `.aios-core/development/tasks/dev-develop-story.md` | Modified | Added step 2 "Code Intelligence Check (IDS G4)" | +| `.aios-core/development/tasks/create-service.md` | Modified | Added Step 0: Code Intelligence Duplicate Check | +| `.aios-core/development/tasks/dev-suggest-refactoring.md` | Modified | Added step 6 "Code Intelligence Blast Radius" in Analysis Phase | +| `.aios-core/development/tasks/build-autonomous.md` | Modified | Added step 2 "Code Intelligence IDS G4 Check" in Build Loop | +| `.aios-core/data/entity-registry.yaml` | Modified | Added dev-helper entity | + +--- + +## QA Results + +### Review Date: 2026-02-17 + +### Reviewed By: Quinn (Test Architect) + +### Risk Assessment + +- Auth/payment/security files touched: No +- Tests added: Yes (24 tests) +- Diff size: ~350 lines (moderate) +- Previous gate: N/A (first review) +- Acceptance criteria count: 4 (low risk) +- **Risk Level: LOW** — standard review depth applied + +### Code Quality Assessment + +Implementation quality is solid. The `dev-helper.js` module follows established patterns from the code-intel module (NOG-1), uses `'use strict'`, CommonJS, consistent error handling, and proper JSDoc documentation. + +**Strengths:** +- Consistent defensive pattern: every function guards with `isCodeIntelAvailable()` before any provider call +- All provider calls wrapped in try/catch, returning null on error (zero-throw guarantee) +- Clean separation: 4 public functions, 2 private helpers, exported constants +- `RISK_THRESHOLDS` exported as constants for testability and future configuration +- `Promise.all` used for concurrent provider calls in `checkBeforeWriting` and `suggestReuse` + +**Observations (non-blocking):** +- `dev-helper.js:36` — `enricher.findTests ? null : null` is dead code (always evaluates to null regardless of condition). This placeholder adds no value and slightly obscures the `Promise.all` intent. Recommend removing in a future cleanup pass. +- `suggestReuse` threshold for REUSE vs ADAPT is `>2 refs` (hardcoded at line 85). Consider extracting to `RISK_THRESHOLDS` or a named constant for consistency with the blast radius thresholds pattern. + +### Requirements Traceability + +| AC | Test Coverage | Validation | +|----|--------------|------------| +| AC1: IDS Gate G4 Automatico | T1, T2, T3 (checkBeforeWriting) + dev-develop-story.md step 2, build-autonomous.md step 2 | Covered | +| AC2: Duplicate Detection | T4, T5 (suggestReuse) + create-service.md Step 0 | Covered | +| AC3: Refactoring Intelligence | T6, T7 (assessRefactoringImpact) + dev-suggest-refactoring.md step 6 | Covered | +| AC4: Fallback sem Provider | T3, T5, T7, T9 (all 4 functions return null) | Covered | + +All 4 ACs have direct test coverage and task-level integration. + +### Test Architecture Assessment + +- **Test count:** 24 tests across 7 describe blocks +- **Coverage:** All 4 public functions + 2 private helpers covered +- **Mock strategy:** Correct — mocks `isCodeIntelAvailable`, `getEnricher`, `getClient` at module level +- **Edge cases:** Provider errors (rejected promise), null results, empty arrays, boundary values for risk thresholds +- **Boundary testing:** `_calculateRiskLevel` tests cover 0, LOW_MAX, LOW_MAX+1, MEDIUM_MAX, MEDIUM_MAX+1 +- **T9 integration test:** Validates all 4 functions simultaneously with provider unavailable +- **Result:** 24/24 PASS, 116/116 total code-intel tests PASS + +### Compliance Check + +- Coding Standards: PASS — `'use strict'`, CommonJS, kebab-case filename, JSDoc +- Project Structure: PASS — `helpers/` inside `code-intel/`, tests in `tests/code-intel/` +- Testing Strategy: PASS — Unit tests with mocked MCP, boundary coverage, integration scenario (T9) +- All ACs Met: PASS — AC1-AC4 all covered by tests and task modifications + +### Improvements Checklist + +- [x] All 4 public functions implement graceful fallback +- [x] Task modifications use conditional language (non-blocking advisory) +- [x] Entity registered in entity-registry.yaml +- [x] Risk thresholds exported as testable constants +- [x] Remove dead code at `dev-helper.js:36` (`enricher.findTests ? null : null` placeholder) — resolved during review +- [x] Extract REUSE/ADAPT threshold to named constant `REUSE_MIN_REFS` — resolved during review + +### Security Review + +No security concerns. The module only reads from code-intel providers (no writes, no user input, no file system mutations). All external calls are wrapped in try/catch. No credentials or secrets handled. + +### Performance Considerations + +- `checkBeforeWriting` makes 2 concurrent calls via `Promise.all` (detectDuplicates + findReferences) — efficient +- All functions respect the upstream circuit breaker (3 failures = open) and session cache (5min TTL) +- Timeout inherited from code-intel-client (5s default) — acceptable for advisory checks +- No performance concerns identified + +### Files Modified During Review + +| File | Change | Why | +|------|--------|-----| +| `.aios-core/core/code-intel/helpers/dev-helper.js` | Removed dead code placeholder (line 36), extracted `REUSE_MIN_REFS` constant | Dead code cleanup and consistency with `RISK_THRESHOLDS` pattern | + +### Gate Status + +Gate: **PASS** -> docs/qa/gates/nog-3-dev-task-enhancement.yml + +### Recommended Status + +PASS — Ready for Done. All acceptance criteria met, 24/24 tests passing, 116/116 code-intel suite passing, no regressions, graceful fallback verified. Two minor observations identified and resolved during review. + +--- + +## Change Log + +| Date | Author | Change | +|------|--------|--------| +| 2026-02-15 | @devops | Story created (v1.0 — Nogic-specific) | +| 2026-02-15 | @architect | Rewrite v2.0 — provider-agnostic, reduced from 5 to 3 points | +| 2026-02-16 | @po (Pax) | v3.0 — Auto-fix: Executor Assignment, Story format, Scope (IN/OUT), Risks, DoD, Dev Notes (Source Tree, Testing, NOG-1 context), CodeRabbit Integration, build-autonomous.md added to Tasks/File List, Task-AC mapping with subtasks, Dev Agent Record/QA Results placeholders | +| 2026-02-16 | @dev (Dex) | v4.0 — Implementation complete: dev-helper.js (4 functions), 4 task modifications, 24/24 tests passing, all tasks [x] | diff --git a/tests/code-intel/dev-helper.test.js b/tests/code-intel/dev-helper.test.js new file mode 100644 index 000000000..e3f72b501 --- /dev/null +++ b/tests/code-intel/dev-helper.test.js @@ -0,0 +1,376 @@ +'use strict'; + +const { + checkBeforeWriting, + suggestReuse, + getConventionsForPath, + assessRefactoringImpact, + _formatSuggestion, + _calculateRiskLevel, + RISK_THRESHOLDS, +} = require('../../.aios-core/core/code-intel/helpers/dev-helper'); + +// Mock the code-intel module +jest.mock('../../.aios-core/core/code-intel/index', () => ({ + isCodeIntelAvailable: jest.fn(), + getEnricher: jest.fn(), + getClient: jest.fn(), +})); + +const { + isCodeIntelAvailable, + getEnricher, + getClient, +} = require('../../.aios-core/core/code-intel/index'); + +// --- Helper to setup mocks --- + +function setupProviderAvailable() { + isCodeIntelAvailable.mockReturnValue(true); +} + +function setupProviderUnavailable() { + isCodeIntelAvailable.mockReturnValue(false); +} + +function createMockEnricher(overrides = {}) { + const enricher = { + detectDuplicates: jest.fn().mockResolvedValue(null), + assessImpact: jest.fn().mockResolvedValue(null), + getConventions: jest.fn().mockResolvedValue(null), + findTests: jest.fn().mockResolvedValue(null), + describeProject: jest.fn().mockResolvedValue(null), + ...overrides, + }; + getEnricher.mockReturnValue(enricher); + return enricher; +} + +function createMockClient(overrides = {}) { + const client = { + findReferences: jest.fn().mockResolvedValue(null), + findDefinition: jest.fn().mockResolvedValue(null), + findCallers: jest.fn().mockResolvedValue(null), + findCallees: jest.fn().mockResolvedValue(null), + analyzeDependencies: jest.fn().mockResolvedValue(null), + analyzeComplexity: jest.fn().mockResolvedValue(null), + analyzeCodebase: jest.fn().mockResolvedValue(null), + getProjectStats: jest.fn().mockResolvedValue(null), + ...overrides, + }; + getClient.mockReturnValue(client); + return client; +} + +// --- Tests --- + +beforeEach(() => { + jest.clearAllMocks(); +}); + +describe('DevHelper', () => { + // === T1: checkBeforeWriting with provider (match found) === + describe('checkBeforeWriting', () => { + it('should return duplicates and suggestion when matches found (T1)', async () => { + setupProviderAvailable(); + createMockEnricher({ + detectDuplicates: jest.fn().mockResolvedValue({ + matches: [{ file: 'src/utils/helper.js', line: 10, context: 'function helper()' }], + codebaseOverview: {}, + }), + }); + createMockClient({ + findReferences: jest.fn().mockResolvedValue([ + { file: 'src/index.js', line: 5, context: 'require(helper)' }, + ]), + }); + + const result = await checkBeforeWriting('helper.js', 'utility helper function'); + + expect(result).not.toBeNull(); + expect(result.duplicates.matches).toHaveLength(1); + expect(result.references).toHaveLength(1); + expect(result.suggestion).toContain('REUSE'); + expect(result.suggestion).toContain('IDS Article IV-A'); + }); + + // === T2: checkBeforeWriting with provider (no match) === + it('should return null when no matches found (T2)', async () => { + setupProviderAvailable(); + createMockEnricher({ + detectDuplicates: jest.fn().mockResolvedValue({ matches: [], codebaseOverview: {} }), + }); + createMockClient({ + findReferences: jest.fn().mockResolvedValue([]), + }); + + const result = await checkBeforeWriting('brand-new-module.js', 'completely new thing'); + + expect(result).toBeNull(); + }); + + // === T3: checkBeforeWriting without provider === + it('should return null without throw when no provider (T3)', async () => { + setupProviderUnavailable(); + + const result = await checkBeforeWriting('test.js', 'some description'); + + expect(result).toBeNull(); + expect(getEnricher).not.toHaveBeenCalled(); + }); + + it('should return null if enricher throws', async () => { + setupProviderAvailable(); + createMockEnricher({ + detectDuplicates: jest.fn().mockRejectedValue(new Error('provider error')), + }); + createMockClient(); + + const result = await checkBeforeWriting('test.js', 'desc'); + + expect(result).toBeNull(); + }); + }); + + // === T4: suggestReuse finds existing definition === + describe('suggestReuse', () => { + it('should return REUSE suggestion when symbol has many references (T4)', async () => { + setupProviderAvailable(); + createMockClient({ + findDefinition: jest.fn().mockResolvedValue({ + file: 'src/core/parser.js', + line: 42, + column: 0, + context: 'function parseConfig()', + }), + findReferences: jest.fn().mockResolvedValue([ + { file: 'src/a.js', line: 1 }, + { file: 'src/b.js', line: 2 }, + { file: 'src/c.js', line: 3 }, + { file: 'src/d.js', line: 4 }, + ]), + }); + + const result = await suggestReuse('parseConfig'); + + expect(result).not.toBeNull(); + expect(result.file).toBe('src/core/parser.js'); + expect(result.line).toBe(42); + expect(result.references).toBe(4); + expect(result.suggestion).toBe('REUSE'); + }); + + it('should return ADAPT suggestion when symbol has few references', async () => { + setupProviderAvailable(); + createMockClient({ + findDefinition: jest.fn().mockResolvedValue({ + file: 'src/old.js', + line: 10, + }), + findReferences: jest.fn().mockResolvedValue([ + { file: 'src/old.js', line: 10 }, + ]), + }); + + const result = await suggestReuse('oldHelper'); + + expect(result).not.toBeNull(); + expect(result.suggestion).toBe('ADAPT'); + }); + + // === T5: suggestReuse no match === + it('should return null when symbol not found (T5)', async () => { + setupProviderAvailable(); + createMockClient({ + findDefinition: jest.fn().mockResolvedValue(null), + findReferences: jest.fn().mockResolvedValue([]), + }); + + const result = await suggestReuse('nonExistentSymbol'); + + expect(result).toBeNull(); + }); + + it('should return null without throw when no provider', async () => { + setupProviderUnavailable(); + + const result = await suggestReuse('anything'); + + expect(result).toBeNull(); + }); + }); + + // === T6: assessRefactoringImpact with blast radius === + describe('assessRefactoringImpact', () => { + it('should return blast radius and risk level (T6)', async () => { + setupProviderAvailable(); + createMockEnricher({ + assessImpact: jest.fn().mockResolvedValue({ + references: Array.from({ length: 20 }, (_, i) => ({ + file: `src/file${i}.js`, + line: i, + })), + complexity: { average: 5.2, perFile: [] }, + blastRadius: 20, + }), + }); + + const result = await assessRefactoringImpact(['src/target.js']); + + expect(result).not.toBeNull(); + expect(result.blastRadius).toBe(20); + expect(result.riskLevel).toBe('HIGH'); + expect(result.references).toHaveLength(20); + expect(result.complexity).toBeDefined(); + }); + + it('should return LOW risk for small blast radius', async () => { + setupProviderAvailable(); + createMockEnricher({ + assessImpact: jest.fn().mockResolvedValue({ + references: [{ file: 'a.js', line: 1 }], + complexity: { average: 1, perFile: [] }, + blastRadius: 1, + }), + }); + + const result = await assessRefactoringImpact(['src/small.js']); + + expect(result.riskLevel).toBe('LOW'); + }); + + it('should return MEDIUM risk for moderate blast radius', async () => { + setupProviderAvailable(); + createMockEnricher({ + assessImpact: jest.fn().mockResolvedValue({ + references: Array.from({ length: 10 }, () => ({ file: 'a.js', line: 1 })), + complexity: { average: 3, perFile: [] }, + blastRadius: 10, + }), + }); + + const result = await assessRefactoringImpact(['src/mid.js']); + + expect(result.riskLevel).toBe('MEDIUM'); + }); + + // === T7: assessRefactoringImpact without provider === + it('should return null without throw when no provider (T7)', async () => { + setupProviderUnavailable(); + + const result = await assessRefactoringImpact(['any.js']); + + expect(result).toBeNull(); + }); + + it('should return null when assessImpact returns null', async () => { + setupProviderAvailable(); + createMockEnricher({ + assessImpact: jest.fn().mockResolvedValue(null), + }); + + const result = await assessRefactoringImpact(['empty.js']); + + expect(result).toBeNull(); + }); + }); + + // === T8: getConventionsForPath returns patterns === + describe('getConventionsForPath', () => { + it('should return patterns and stats (T8)', async () => { + setupProviderAvailable(); + createMockEnricher({ + getConventions: jest.fn().mockResolvedValue({ + patterns: ['kebab-case files', 'CommonJS modules', 'JSDoc comments'], + stats: { files: 120, languages: ['javascript'] }, + }), + }); + + const result = await getConventionsForPath('src/'); + + expect(result).not.toBeNull(); + expect(result.patterns).toHaveLength(3); + expect(result.stats.files).toBe(120); + }); + + it('should return null without throw when no provider', async () => { + setupProviderUnavailable(); + + const result = await getConventionsForPath('src/'); + + expect(result).toBeNull(); + }); + }); + + // === T9: All functions fallback (provider unavailable) === + describe('All functions fallback (T9)', () => { + beforeEach(() => { + setupProviderUnavailable(); + }); + + it('all 4 functions return null when no provider', async () => { + const results = await Promise.all([ + checkBeforeWriting('file.js', 'desc'), + suggestReuse('symbol'), + getConventionsForPath('src/'), + assessRefactoringImpact(['file.js']), + ]); + + expect(results).toEqual([null, null, null, null]); + }); + }); + + // === Private helpers === + describe('_calculateRiskLevel', () => { + it('should return LOW for 0 refs', () => { + expect(_calculateRiskLevel(0)).toBe('LOW'); + }); + + it('should return LOW for threshold boundary', () => { + expect(_calculateRiskLevel(RISK_THRESHOLDS.LOW_MAX)).toBe('LOW'); + }); + + it('should return MEDIUM for LOW_MAX + 1', () => { + expect(_calculateRiskLevel(RISK_THRESHOLDS.LOW_MAX + 1)).toBe('MEDIUM'); + }); + + it('should return MEDIUM for MEDIUM_MAX boundary', () => { + expect(_calculateRiskLevel(RISK_THRESHOLDS.MEDIUM_MAX)).toBe('MEDIUM'); + }); + + it('should return HIGH for MEDIUM_MAX + 1', () => { + expect(_calculateRiskLevel(RISK_THRESHOLDS.MEDIUM_MAX + 1)).toBe('HIGH'); + }); + }); + + describe('_formatSuggestion', () => { + it('should format with both duplicates and refs', () => { + const msg = _formatSuggestion( + { matches: [{ file: 'a.js', line: 1 }] }, + [{ file: 'b.js', line: 2 }] + ); + + expect(msg).toContain('1 similar match'); + expect(msg).toContain('a.js:1'); + expect(msg).toContain('1 location'); + expect(msg).toContain('IDS Article IV-A'); + }); + + it('should format with only duplicates', () => { + const msg = _formatSuggestion( + { matches: [{ file: 'a.js' }] }, + null + ); + + expect(msg).toContain('1 similar match'); + expect(msg).toContain('IDS Article IV-A'); + }); + + it('should format with only refs', () => { + const msg = _formatSuggestion(null, [{ file: 'b.js', line: 5 }]); + + expect(msg).toContain('1 location'); + expect(msg).toContain('b.js:5'); + }); + }); +}); From 755df6fb14ad13ab5b21e99ab2e6cc5b83132d67 Mon Sep 17 00:00:00 2001 From: Pedro Valerio Date: Tue, 17 Feb 2026 12:35:48 -0300 Subject: [PATCH 2/4] fix(code-intel): address CodeRabbit review feedback [Story NOG-3] - Add input validation guards on all 4 public API methods - Fix _calculateRiskLevel for non-numeric inputs (NaN/undefined) - Fix ESLint indentation on RISK_THRESHOLDS comment - Add 7 new tests for input validation (31 total, 123 suite) Co-Authored-By: Claude Opus 4.6 --- .../core/code-intel/helpers/dev-helper.js | 19 +++++-- .aios-core/install-manifest.yaml | 10 ++-- tests/code-intel/dev-helper.test.js | 53 +++++++++++++++++++ 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/.aios-core/core/code-intel/helpers/dev-helper.js b/.aios-core/core/code-intel/helpers/dev-helper.js index cc2c1c24b..4959d0f58 100644 --- a/.aios-core/core/code-intel/helpers/dev-helper.js +++ b/.aios-core/core/code-intel/helpers/dev-helper.js @@ -6,7 +6,7 @@ const { getEnricher, getClient, isCodeIntelAvailable } = require('../index'); const RISK_THRESHOLDS = { LOW_MAX: 4, // 0-4 refs = LOW MEDIUM_MAX: 15, // 5-15 refs = MEDIUM - // >15 refs = HIGH + // >15 refs = HIGH }; // Minimum references to suggest REUSE (>threshold = REUSE, <=threshold = ADAPT) @@ -28,6 +28,9 @@ const REUSE_MIN_REFS = 2; * @returns {Promise<{duplicates: Object, references: Array, suggestion: string}|null>} */ async function checkBeforeWriting(fileName, description) { + if (!fileName || !description) { + return null; + } if (!isCodeIntelAvailable()) { return null; } @@ -65,6 +68,9 @@ async function checkBeforeWriting(fileName, description) { * @returns {Promise<{file: string, line: number, references: number, suggestion: string}|null>} */ async function suggestReuse(symbol) { + if (!symbol) { + return null; + } if (!isCodeIntelAvailable()) { return null; } @@ -103,6 +109,9 @@ async function suggestReuse(symbol) { * @returns {Promise<{patterns: Array, stats: Object}|null>} */ async function getConventionsForPath(targetPath) { + if (!targetPath) { + return null; + } if (!isCodeIntelAvailable()) { return null; } @@ -123,6 +132,9 @@ async function getConventionsForPath(targetPath) { * @returns {Promise<{blastRadius: number, riskLevel: string, references: Array, complexity: Object}|null>} */ async function assessRefactoringImpact(files) { + if (!Array.isArray(files) || files.length === 0) { + return null; + } if (!isCodeIntelAvailable()) { return null; } @@ -184,10 +196,11 @@ function _formatSuggestion(dupes, nameRefs) { * @private */ function _calculateRiskLevel(blastRadius) { - if (blastRadius <= RISK_THRESHOLDS.LOW_MAX) { + const radius = typeof blastRadius === 'number' && !Number.isNaN(blastRadius) ? blastRadius : 0; + if (radius <= RISK_THRESHOLDS.LOW_MAX) { return 'LOW'; } - if (blastRadius <= RISK_THRESHOLDS.MEDIUM_MAX) { + if (radius <= RISK_THRESHOLDS.MEDIUM_MAX) { return 'MEDIUM'; } return 'HIGH'; diff --git a/.aios-core/install-manifest.yaml b/.aios-core/install-manifest.yaml index c9471a5d1..6925f0d94 100644 --- a/.aios-core/install-manifest.yaml +++ b/.aios-core/install-manifest.yaml @@ -8,7 +8,7 @@ # - File types for categorization # version: 4.2.13 -generated_at: "2026-02-17T12:48:43.195Z" +generated_at: "2026-02-17T15:35:48.720Z" generator: scripts/generate-install-manifest.js file_count: 1007 files: @@ -189,9 +189,9 @@ files: type: core size: 4320 - path: core/code-intel/helpers/dev-helper.js - hash: sha256:2418a5f541003c73cc284e88a6b0cb666896a47ffd5ed4c08648269d281efc4c + hash: sha256:0c38edbf0572a2e2ddb5c2f904b6b12472f78c2cda1af14e14ca36b05005683d type: core - size: 5770 + size: 6049 - path: core/code-intel/index.js hash: sha256:ca8c54c2decbf64183d890ab42dc8ca2deafa675d4433492cb6ce423a284ad4d type: core @@ -1045,9 +1045,9 @@ files: type: data size: 34251 - path: data/entity-registry.yaml - hash: sha256:9cbf837d0b2151304c3ce8d28e6ac8efa1ef4b35a9dc4074bdbfaa9fd4afc77f + hash: sha256:3e6bc6548c6dcca4e9928c0d8e8ae66b4478df0f4807637a19a87ace7f314550 type: data - size: 291887 + size: 291647 - path: data/learned-patterns.yaml hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc type: data diff --git a/tests/code-intel/dev-helper.test.js b/tests/code-intel/dev-helper.test.js index e3f72b501..09014df01 100644 --- a/tests/code-intel/dev-helper.test.js +++ b/tests/code-intel/dev-helper.test.js @@ -8,6 +8,7 @@ const { _formatSuggestion, _calculateRiskLevel, RISK_THRESHOLDS, + REUSE_MIN_REFS, } = require('../../.aios-core/core/code-intel/helpers/dev-helper'); // Mock the code-intel module @@ -119,6 +120,24 @@ describe('DevHelper', () => { expect(getEnricher).not.toHaveBeenCalled(); }); + it('should return null for null/undefined fileName', async () => { + const result1 = await checkBeforeWriting(null, 'desc'); + const result2 = await checkBeforeWriting(undefined, 'desc'); + const result3 = await checkBeforeWriting('', 'desc'); + expect(result1).toBeNull(); + expect(result2).toBeNull(); + expect(result3).toBeNull(); + }); + + it('should return null for null/undefined description', async () => { + const result1 = await checkBeforeWriting('file.js', null); + const result2 = await checkBeforeWriting('file.js', undefined); + const result3 = await checkBeforeWriting('file.js', ''); + expect(result1).toBeNull(); + expect(result2).toBeNull(); + expect(result3).toBeNull(); + }); + it('should return null if enricher throws', async () => { setupProviderAvailable(); createMockEnricher({ @@ -198,6 +217,12 @@ describe('DevHelper', () => { expect(result).toBeNull(); }); + + it('should return null for null/undefined/empty symbol', async () => { + expect(await suggestReuse(null)).toBeNull(); + expect(await suggestReuse(undefined)).toBeNull(); + expect(await suggestReuse('')).toBeNull(); + }); }); // === T6: assessRefactoringImpact with blast radius === @@ -254,6 +279,13 @@ describe('DevHelper', () => { expect(result.riskLevel).toBe('MEDIUM'); }); + it('should return null for non-array or empty files input', async () => { + expect(await assessRefactoringImpact(null)).toBeNull(); + expect(await assessRefactoringImpact(undefined)).toBeNull(); + expect(await assessRefactoringImpact('not-array')).toBeNull(); + expect(await assessRefactoringImpact([])).toBeNull(); + }); + // === T7: assessRefactoringImpact without provider === it('should return null without throw when no provider (T7)', async () => { setupProviderUnavailable(); @@ -300,6 +332,12 @@ describe('DevHelper', () => { expect(result).toBeNull(); }); + + it('should return null for null/undefined/empty targetPath', async () => { + expect(await getConventionsForPath(null)).toBeNull(); + expect(await getConventionsForPath(undefined)).toBeNull(); + expect(await getConventionsForPath('')).toBeNull(); + }); }); // === T9: All functions fallback (provider unavailable) === @@ -341,6 +379,21 @@ describe('DevHelper', () => { it('should return HIGH for MEDIUM_MAX + 1', () => { expect(_calculateRiskLevel(RISK_THRESHOLDS.MEDIUM_MAX + 1)).toBe('HIGH'); }); + + it('should default to LOW for undefined/null/NaN input', () => { + expect(_calculateRiskLevel(undefined)).toBe('LOW'); + expect(_calculateRiskLevel(null)).toBe('LOW'); + expect(_calculateRiskLevel(NaN)).toBe('LOW'); + expect(_calculateRiskLevel('not-a-number')).toBe('LOW'); + }); + }); + + describe('REUSE_MIN_REFS constant', () => { + it('should be exported and be a positive number', () => { + expect(REUSE_MIN_REFS).toBeDefined(); + expect(typeof REUSE_MIN_REFS).toBe('number'); + expect(REUSE_MIN_REFS).toBeGreaterThan(0); + }); }); describe('_formatSuggestion', () => { From 5156f614326877b38c72f8768596c1a7c0d267be Mon Sep 17 00:00:00 2001 From: Pedro Valerio Date: Tue, 17 Feb 2026 12:45:02 -0300 Subject: [PATCH 3/4] fix(ci): regenerate install manifest for clean CI validation Co-Authored-By: Claude Opus 4.6 --- .aios-core/install-manifest.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.aios-core/install-manifest.yaml b/.aios-core/install-manifest.yaml index 6925f0d94..7d7a7cf9c 100644 --- a/.aios-core/install-manifest.yaml +++ b/.aios-core/install-manifest.yaml @@ -8,7 +8,7 @@ # - File types for categorization # version: 4.2.13 -generated_at: "2026-02-17T15:35:48.720Z" +generated_at: "2026-02-17T15:44:47.932Z" generator: scripts/generate-install-manifest.js file_count: 1007 files: @@ -1045,9 +1045,9 @@ files: type: data size: 34251 - path: data/entity-registry.yaml - hash: sha256:3e6bc6548c6dcca4e9928c0d8e8ae66b4478df0f4807637a19a87ace7f314550 + hash: sha256:9cbf837d0b2151304c3ce8d28e6ac8efa1ef4b35a9dc4074bdbfaa9fd4afc77f type: data - size: 291647 + size: 291887 - path: data/learned-patterns.yaml hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc type: data @@ -1405,9 +1405,9 @@ files: type: script size: 18196 - path: development/scripts/unified-activation-pipeline.js - hash: sha256:f822840facd618447032b71aefbde464dd2bce4aba630e5b4ec5241435761919 + hash: sha256:dd1ad8050ac6ea04ff634434be9b97f67239ee0a7342d669bc5618eb2b7a7f5b type: script - size: 29786 + size: 29211 - path: development/scripts/usage-tracker.js hash: sha256:b3079713787de7c6ac38a742255861f04e8359ef1b227836040920a64b7e8aac type: script From d261eebc3dd716ee66d3e27bb7f51e75a3159f32 Mon Sep 17 00:00:00 2001 From: Pedro Valerio Date: Fri, 20 Feb 2026 22:49:43 -0300 Subject: [PATCH 4/4] feat(github): implement issue management system [Story GHIM-001] Complete GitHub issue management with 3 phases: - Phase 1: Label taxonomy (44 labels with prefixes), 3 YAML issue forms, config.yml - Phase 2: GitHub Actions (issue-labeler, stale, welcome), labeler configs - Phase 3: Triage task, checklist, batch script, 31 issues triaged Includes research documentation and QA-reviewed corrections. Co-Authored-By: Claude Opus 4.6 --- .../checklists/issue-triage-checklist.md | 35 +++ .../development/scripts/issue-triage.js | 171 +++++++++++ .../development/tasks/github-issue-triage.md | 118 ++++++++ .aios-core/install-manifest.yaml | 24 +- .github/ISSUE_TEMPLATE/1-bug-report.yml | 123 ++++++++ .github/ISSUE_TEMPLATE/2-feature-request.yml | 114 +++++++ .github/ISSUE_TEMPLATE/3-test-coverage.yml | 73 +++++ .github/ISSUE_TEMPLATE/bug_report.md | 86 ------ .github/ISSUE_TEMPLATE/config.yml | 8 + .github/ISSUE_TEMPLATE/feature_request.md | 100 ------- .github/issue-labeler.yml | 30 ++ .github/labeler.yml | 135 +++------ .github/workflows/issue-labeler.yml | 25 ++ .github/workflows/stale.yml | 48 +++ .github/workflows/welcome.yml | 48 +-- .../00-query-original.md | 28 ++ .../01-deep-research-prompt.md | 31 ++ .../02-research-report.md | 277 ++++++++++++++++++ .../03-recommendations.md | 153 ++++++++++ .../README.md | 27 ++ docs/stories/active/GHIM-001.story.md | 237 +++++++++++++++ 21 files changed, 1573 insertions(+), 318 deletions(-) create mode 100644 .aios-core/development/checklists/issue-triage-checklist.md create mode 100644 .aios-core/development/scripts/issue-triage.js create mode 100644 .aios-core/development/tasks/github-issue-triage.md create mode 100644 .github/ISSUE_TEMPLATE/1-bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/2-feature-request.yml create mode 100644 .github/ISSUE_TEMPLATE/3-test-coverage.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/issue-labeler.yml create mode 100644 .github/workflows/issue-labeler.yml create mode 100644 .github/workflows/stale.yml create mode 100644 docs/research/2026-02-20-github-issue-management/00-query-original.md create mode 100644 docs/research/2026-02-20-github-issue-management/01-deep-research-prompt.md create mode 100644 docs/research/2026-02-20-github-issue-management/02-research-report.md create mode 100644 docs/research/2026-02-20-github-issue-management/03-recommendations.md create mode 100644 docs/research/2026-02-20-github-issue-management/README.md create mode 100644 docs/stories/active/GHIM-001.story.md diff --git a/.aios-core/development/checklists/issue-triage-checklist.md b/.aios-core/development/checklists/issue-triage-checklist.md new file mode 100644 index 000000000..aa1d3cd29 --- /dev/null +++ b/.aios-core/development/checklists/issue-triage-checklist.md @@ -0,0 +1,35 @@ +# Issue Triage Checklist + +## Per-Issue Checklist + +For each issue being triaged, verify: + +### Classification +- [ ] Issue has been read and understood +- [ ] ONE `type:` label applied (bug/feature/enhancement/docs/test/chore) +- [ ] ONE `priority:` label applied (P1/P2/P3/P4) +- [ ] At least ONE `area:` label applied +- [ ] `status: needs-triage` removed + +### Status Resolution +- [ ] Status set to `status: confirmed` OR `status: needs-info` +- [ ] If `status: needs-info` — comment posted asking for specific details +- [ ] If duplicate — labeled `duplicate`, closed with reference to original issue + +### Community +- [ ] Assessed for `community: good first issue` (clear scope, isolated, well-documented) +- [ ] Assessed for `community: help wanted` (valid but team lacks bandwidth) + +### Quality +- [ ] Issue has sufficient information to act on (or `status: needs-info` applied) +- [ ] Related issues cross-referenced if applicable +- [ ] No sensitive information in issue (API keys, credentials) + +## Session Checklist + +After completing a triage session: + +- [ ] All `status: needs-triage` issues reviewed +- [ ] Triage report generated +- [ ] Story GHIM-001 updated with triage count +- [ ] High-priority issues (P1/P2) flagged for immediate attention diff --git a/.aios-core/development/scripts/issue-triage.js b/.aios-core/development/scripts/issue-triage.js new file mode 100644 index 000000000..c5e84a19a --- /dev/null +++ b/.aios-core/development/scripts/issue-triage.js @@ -0,0 +1,171 @@ +#!/usr/bin/env node + +/** + * Issue Triage Script + * Batch triage tool for @devops to manage GitHub issues. + * + * Usage: + * node issue-triage.js --list # List untriaged issues + * node issue-triage.js --apply 174 --type bug --priority P2 --area installer + * node issue-triage.js --report # Generate triage summary + * + * Story: GHIM-001 + */ + +const { execSync } = require('child_process'); + +const VALID_TYPES = ['bug', 'feature', 'enhancement', 'docs', 'test', 'chore']; +const VALID_PRIORITIES = ['P1', 'P2', 'P3', 'P4']; +const VALID_AREAS = ['core', 'installer', 'synapse', 'cli', 'pro', 'health-check', 'docs', 'devops', 'agents', 'workflows']; + +function gh(cmd) { + try { + return execSync(`gh ${cmd}`, { encoding: 'utf8', timeout: 60000 }); + } catch (err) { + console.error(`gh command failed: ${err.message}`); + process.exit(1); + } +} + +function listUntriaged() { + const raw = gh('issue list --label "status: needs-triage" --json number,title,labels,createdAt,author --limit 100'); + const issues = JSON.parse(raw); + + if (issues.length === 0) { + console.log('No untriaged issues found.'); + return; + } + + console.log(`\n=== ${issues.length} Untriaged Issues ===\n`); + for (const issue of issues) { + const labels = issue.labels.map(l => l.name).join(', '); + const date = issue.createdAt.split('T')[0]; + console.log(` #${issue.number} [${date}] ${issue.title}`); + console.log(` Author: ${issue.author.login} | Labels: ${labels}`); + console.log(); + } +} + +function applyLabels(number, type, priority, areas, extra) { + if (!VALID_TYPES.includes(type)) { + console.error(`Invalid type: ${type}. Valid: ${VALID_TYPES.join(', ')}`); + process.exit(1); + } + if (!VALID_PRIORITIES.includes(priority)) { + console.error(`Invalid priority: ${priority}. Valid: ${VALID_PRIORITIES.join(', ')}`); + process.exit(1); + } + + const addLabels = [`type: ${type}`, `priority: ${priority}`, 'status: confirmed']; + for (const area of areas) { + if (!VALID_AREAS.includes(area)) { + console.error(`Invalid area: ${area}. Valid: ${VALID_AREAS.join(', ')}`); + process.exit(1); + } + addLabels.push(`area: ${area}`); + } + if (extra) { + addLabels.push(...extra); + } + + const addStr = addLabels.map(l => `"${l}"`).join(','); + console.log(`Applying to #${number}: ${addLabels.join(', ')}`); + gh(`issue edit ${number} --add-label ${addStr} --remove-label "status: needs-triage"`); + console.log(` Done.`); +} + +function generateReport() { + const raw = gh('issue list --state open --json number,title,labels --limit 200'); + const issues = JSON.parse(raw); + + const stats = { + total: issues.length, + untriaged: 0, + byType: {}, + byPriority: {}, + byArea: {}, + byStatus: {} + }; + + for (const issue of issues) { + const labels = issue.labels.map(l => l.name); + + if (labels.includes('status: needs-triage')) stats.untriaged++; + + for (const label of labels) { + if (label.startsWith('type: ')) { + const val = label.replace('type: ', ''); + stats.byType[val] = (stats.byType[val] || 0) + 1; + } + if (label.startsWith('priority: ')) { + const val = label.replace('priority: ', ''); + stats.byPriority[val] = (stats.byPriority[val] || 0) + 1; + } + if (label.startsWith('area: ')) { + const val = label.replace('area: ', ''); + stats.byArea[val] = (stats.byArea[val] || 0) + 1; + } + if (label.startsWith('status: ')) { + const val = label.replace('status: ', ''); + stats.byStatus[val] = (stats.byStatus[val] || 0) + 1; + } + } + } + + console.log('\n=== Issue Triage Report ===\n'); + console.log(`Total open issues: ${stats.total}`); + console.log(`Untriaged: ${stats.untriaged}`); + console.log(`\nBy Type:`); + for (const [k, v] of Object.entries(stats.byType).sort((a, b) => b[1] - a[1])) { + console.log(` ${k}: ${v}`); + } + console.log(`\nBy Priority:`); + for (const [k, v] of Object.entries(stats.byPriority).sort()) { + console.log(` ${k}: ${v}`); + } + console.log(`\nBy Area:`); + for (const [k, v] of Object.entries(stats.byArea).sort((a, b) => b[1] - a[1])) { + console.log(` ${k}: ${v}`); + } + console.log(`\nBy Status:`); + for (const [k, v] of Object.entries(stats.byStatus).sort((a, b) => b[1] - a[1])) { + console.log(` ${k}: ${v}`); + } +} + +// CLI argument parsing +const args = process.argv.slice(2); + +if (args.includes('--list')) { + listUntriaged(); +} else if (args.includes('--apply')) { + const idx = args.indexOf('--apply'); + const number = parseInt(args[idx + 1]); + const typeIdx = args.indexOf('--type'); + const prioIdx = args.indexOf('--priority'); + const areaIdx = args.indexOf('--area'); + const extraIdx = args.indexOf('--extra'); + + if (!number || typeIdx === -1 || prioIdx === -1 || areaIdx === -1) { + console.error('Usage: --apply --type --priority --area [--extra "label1,label2"]'); + process.exit(1); + } + + const type = args[typeIdx + 1]; + const priority = args[prioIdx + 1]; + const areas = args[areaIdx + 1].split(','); + const extra = extraIdx !== -1 ? args[extraIdx + 1].split(',') : []; + + applyLabels(number, type, priority, areas, extra); +} else if (args.includes('--report')) { + generateReport(); +} else { + console.log('Issue Triage Tool (GHIM-001)\n'); + console.log('Usage:'); + console.log(' --list List untriaged issues'); + console.log(' --apply <#> --type --priority

--area Apply labels'); + console.log(' --report Generate triage summary'); + console.log('\nTypes:', VALID_TYPES.join(', ')); + console.log('Priorities:', VALID_PRIORITIES.join(', ')); + console.log('Areas:', VALID_AREAS.join(', ')); +} diff --git a/.aios-core/development/tasks/github-issue-triage.md b/.aios-core/development/tasks/github-issue-triage.md new file mode 100644 index 000000000..f09d9170f --- /dev/null +++ b/.aios-core/development/tasks/github-issue-triage.md @@ -0,0 +1,118 @@ +# GitHub Issue Triage + +## Task Metadata + +```yaml +id: github-issue-triage +name: GitHub Issue Triage +agent: devops +elicit: true +category: repository-management +story: GHIM-001 +``` + +## Description + +Systematic triage of GitHub issues for the aios-core repository. This task guides @devops through the process of reviewing, classifying, and labeling open issues. + +## Prerequisites + +- GitHub CLI authenticated (`gh auth status`) +- Label taxonomy deployed (see GHIM-001 Phase 1) +- Access to repository issue list + +## Workflow + +### Step 1: List Untriaged Issues + +```bash +gh issue list --label "status: needs-triage" --json number,title,labels,createdAt,author --limit 50 +``` + +### Step 2: Per-Issue Triage (Interactive) + +For each issue, apply the triage checklist: + +1. **Read the issue** — Open and understand the content +2. **Classify type** — Apply ONE `type:` label: + - `type: bug` — Something isn't working + - `type: feature` — New feature request + - `type: enhancement` — Improvement to existing feature + - `type: docs` — Documentation issue + - `type: test` — Test coverage + - `type: chore` — Maintenance/cleanup +3. **Assess priority** — Apply ONE `priority:` label: + - `priority: P1` — Critical, blocks users (SLA: 24h response) + - `priority: P2` — High, affects most users (SLA: 3 days) + - `priority: P3` — Medium, affects some users (SLA: 1 week) + - `priority: P4` — Low, edge cases (backlog) +4. **Assign area** — Apply ONE or more `area:` labels: + - `area: core`, `area: installer`, `area: synapse`, `area: cli` + - `area: pro`, `area: health-check`, `area: docs`, `area: devops` +5. **Update status** — Replace `status: needs-triage` with appropriate status: + - `status: confirmed` — Valid issue, ready for work + - `status: needs-info` — Need more details from reporter +6. **Check for duplicates** — If duplicate, label `duplicate` and close with reference +7. **Community labels** — If appropriate, add `community: good first issue` or `community: help wanted` + +### Step 3: Apply Labels + +```bash +gh issue edit {number} --add-label "type: bug,priority: P2,area: installer,status: confirmed" --remove-label "status: needs-triage" +``` + +### Step 4: Batch Triage (Optional) + +For bulk operations, use the triage script: + +```bash +node .aios-core/development/scripts/issue-triage.js --list +node .aios-core/development/scripts/issue-triage.js --apply {number} --type bug --priority P2 --area installer +``` + +### Step 5: Report + +After triage session, generate summary: + +```bash +node .aios-core/development/scripts/issue-triage.js --report +``` + +## Triage Decision Tree + +``` +Issue received + ├── Is it a duplicate? → Label "duplicate", close with reference + ├── Is it spam/invalid? → Label "status: invalid", close + ├── Needs more info? → Label "status: needs-info", comment asking for details + └── Valid issue + ├── Bug → "type: bug" + priority + area + ├── Feature → "type: feature" + priority + area + ├── Enhancement → "type: enhancement" + priority + area + ├── Docs → "type: docs" + priority: P3/P4 + └── Tests → "type: test" + area +``` + +## Priority Guidelines + +| Signal | Priority | +|--------|----------| +| Blocks installation/usage for all users | P1 | +| Breaks core functionality, no workaround | P1 | +| Significant bug with workaround | P2 | +| Feature highly requested by community | P2 | +| Minor bug, edge case | P3 | +| Nice-to-have improvement | P3 | +| Cosmetic, low impact | P4 | + +## Command Integration + +This task is invocable via @devops: +- `*triage` — Start interactive triage session +- `*triage --batch` — Run batch triage with script + +## Output + +- All issues labeled with `type:`, `priority:`, `area:` labels +- `status: needs-triage` removed from all triaged issues +- Triage report with summary of actions taken diff --git a/.aios-core/install-manifest.yaml b/.aios-core/install-manifest.yaml index 7d7a7cf9c..e9901b9c8 100644 --- a/.aios-core/install-manifest.yaml +++ b/.aios-core/install-manifest.yaml @@ -8,9 +8,9 @@ # - File types for categorization # version: 4.2.13 -generated_at: "2026-02-17T15:44:47.932Z" +generated_at: "2026-02-21T01:49:43.857Z" generator: scripts/generate-install-manifest.js -file_count: 1007 +file_count: 1010 files: - path: cli/commands/config/index.js hash: sha256:ebcad2ce3807eda29dcddff76d7a95ddc9b7fa160df21fd608f94b802237e862 @@ -1045,9 +1045,9 @@ files: type: data size: 34251 - path: data/entity-registry.yaml - hash: sha256:9cbf837d0b2151304c3ce8d28e6ac8efa1ef4b35a9dc4074bdbfaa9fd4afc77f + hash: sha256:b1c345289ed14eda700026481fe42a0b53734a7610f078f9e67a320a7ddb509d type: data - size: 291887 + size: 291647 - path: data/learned-patterns.yaml hash: sha256:24ac0b160615583a0ff783d3da8af80b7f94191575d6db2054ec8e10a3f945dc type: data @@ -1148,6 +1148,10 @@ files: hash: sha256:d07b1f9e2fcb78f62188ef05a6e6f75a94821b6bb297ea67f2e782e260d27f49 type: checklist size: 3335 + - path: development/checklists/issue-triage-checklist.md + hash: sha256:c6dbaae38c0e3030dbffebcbcf95e5e766e0294a7a678531531cbd7ad6e54e2b + type: checklist + size: 1245 - path: development/checklists/self-critique-checklist.md hash: sha256:869fbc8fbc333ac8eea4eca3ea4ab9ca79917fa5e53735b70d634c85ac6420c8 type: checklist @@ -1280,6 +1284,10 @@ files: hash: sha256:8155920904d4d8b9e9c5eac09732ad86639b0303e077725f2692e90c28715492 type: script size: 5166 + - path: development/scripts/issue-triage.js + hash: sha256:a9f9741b1426732f19803bf9f292b15d8eed0fb875cf02df70735f48512f2310 + type: script + size: 5777 - path: development/scripts/manifest-preview.js hash: sha256:caccc28155efee736533622e3bc62c67abb9721e1f4e9bf761ef02f8d8a37026 type: script @@ -1405,9 +1413,9 @@ files: type: script size: 18196 - path: development/scripts/unified-activation-pipeline.js - hash: sha256:dd1ad8050ac6ea04ff634434be9b97f67239ee0a7342d669bc5618eb2b7a7f5b + hash: sha256:f822840facd618447032b71aefbde464dd2bce4aba630e5b4ec5241435761919 type: script - size: 29211 + size: 29786 - path: development/scripts/usage-tracker.js hash: sha256:b3079713787de7c6ac38a742255861f04e8359ef1b227836040920a64b7e8aac type: script @@ -1808,6 +1816,10 @@ files: hash: sha256:823916f01d2242591cd5a4b607e96f130ceaf040015f510b24847752861bcc0c type: task size: 11737 + - path: development/tasks/github-issue-triage.md + hash: sha256:a76192c203ff0e709ba52dfa595f2d81351e4c52180407b9d05b99dbea8de709 + type: task + size: 3884 - path: development/tasks/gotcha.md hash: sha256:c6f621ada5233e0f4181b8e052181017a040246eec604749c970786b7cf9f837 type: task diff --git a/.github/ISSUE_TEMPLATE/1-bug-report.yml b/.github/ISSUE_TEMPLATE/1-bug-report.yml new file mode 100644 index 000000000..33b79a6c3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bug-report.yml @@ -0,0 +1,123 @@ +name: Bug Report +description: Report a bug in aios-core +title: "[Bug]: " +labels: ["type: bug", "status: needs-triage"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Please fill out the information below to help us investigate. + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is. + placeholder: Describe the bug... + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: Walk through the issue step-by-step. + value: | + 1. + 2. + 3. + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What you expected to happen. + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened. + validations: + required: true + + - type: textarea + id: error-output + attributes: + label: Error Output + description: Paste any error messages or stack traces. + render: bash + + - type: dropdown + id: area + attributes: + label: Affected Area + options: + - "Core Framework (.aios-core/core/)" + - "Installer (packages/installer/)" + - "CLI (bin/, packages/aios-pro-cli/)" + - "SYNAPSE Context Engine" + - "Health Check System" + - "Pro Features" + - "Documentation" + - "CI/CD / GitHub Actions" + - "Other" + validations: + required: true + + - type: input + id: version + attributes: + label: AIOS Version + description: "Run `npx aios-core info` to find your version." + placeholder: "e.g., 4.2.13" + validations: + required: true + + - type: dropdown + id: os + attributes: + label: Operating System + options: + - "Windows 11" + - "Windows 10" + - "macOS (Apple Silicon)" + - "macOS (Intel)" + - "Ubuntu / Debian" + - "Other Linux" + validations: + required: true + + - type: input + id: node-version + attributes: + label: Node.js Version + placeholder: "e.g., 22.21.0" + + - type: dropdown + id: priority + attributes: + label: Priority + description: How critical is this bug for your use case? + options: + - "Critical - Blocking production use" + - "High - Significant impact on functionality" + - "Medium - Minor impact, workaround available" + - "Low - Enhancement or nice-to-have fix" + default: 2 + validations: + required: true + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: "I have searched existing issues to avoid duplicates" + required: true + - label: "I have tested with the latest version" + - label: "I can consistently reproduce this issue" diff --git a/.github/ISSUE_TEMPLATE/2-feature-request.yml b/.github/ISSUE_TEMPLATE/2-feature-request.yml new file mode 100644 index 000000000..4b1d9f67d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-feature-request.yml @@ -0,0 +1,114 @@ +name: Feature Request +description: Suggest a new feature or improvement for aios-core +title: "[Feature]: " +labels: ["type: feature", "status: needs-triage"] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a feature! Please describe your idea clearly so we can evaluate it. + + - type: textarea + id: summary + attributes: + label: Summary + description: A clear and concise description of the feature. + placeholder: Describe the feature... + validations: + required: true + + - type: textarea + id: problem + attributes: + label: Problem Statement + description: What problem does this solve? What use case does this enable? + placeholder: "Is your feature request related to a problem? Describe it..." + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: How should this feature work? What API or interface would you expect? + validations: + required: true + + - type: dropdown + id: area + attributes: + label: Package / Area + description: Which part of aios-core should this feature belong to? + options: + - "Core Framework (.aios-core/core/)" + - "Installer (packages/installer/)" + - "CLI (bin/, packages/aios-pro-cli/)" + - "SYNAPSE Context Engine" + - "Health Check System" + - "Agent System (.aios-core/development/agents/)" + - "Task System (.aios-core/development/tasks/)" + - "Memory / Knowledge Base" + - "Pro Features" + - "Documentation" + - "New package / module" + validations: + required: true + + - type: textarea + id: code-example + attributes: + label: Code Example (Optional) + description: What would the API look like? + render: javascript + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Other approaches you've considered or existing workarounds. + + - type: dropdown + id: impact + attributes: + label: Impact Assessment + options: + - "New functionality - backward compatible" + - "Enhancement to existing feature" + - "Performance improvement" + - "Developer experience improvement" + - "Breaking change - requires major version bump" + validations: + required: true + + - type: dropdown + id: priority + attributes: + label: Priority + description: How important is this feature to you? + options: + - "Critical - Blocking my use case" + - "High - Would significantly improve my workflow" + - "Medium - Nice to have" + - "Low - Minor improvement" + default: 2 + validations: + required: true + + - type: checkboxes + id: contribution + attributes: + label: Community Contribution + options: + - label: "I would be willing to contribute to implementing this" + - label: "I can help with documentation" + - label: "I can help with testing" + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: "I have searched existing issues and feature requests" + required: true + - label: "I have provided a clear use case for this feature" + required: true diff --git a/.github/ISSUE_TEMPLATE/3-test-coverage.yml b/.github/ISSUE_TEMPLATE/3-test-coverage.yml new file mode 100644 index 000000000..33b93ee0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-test-coverage.yml @@ -0,0 +1,73 @@ +name: Test Coverage +description: Propose new test coverage for existing modules +title: "[Test]: " +labels: ["type: test", "status: needs-triage"] +body: + - type: markdown + attributes: + value: | + Use this template to propose test coverage for aios-core modules. + Related to [Issue #52](https://github.com/SynkraAI/aios-core/issues/52) (global test coverage improvement). + + - type: textarea + id: modules + attributes: + label: Modules to Test + description: List the modules/files that need test coverage. + placeholder: | + - `.aios-core/core/orchestration/agent-invoker.js` + - `.aios-core/core/orchestration/gate-evaluator.js` + validations: + required: true + + - type: textarea + id: test-scope + attributes: + label: Test Scope + description: What types of tests are needed? (unit, integration, e2e) + placeholder: | + - Unit tests for public API methods + - Edge cases for error handling + - Integration with dependent modules + validations: + required: true + + - type: input + id: test-count + attributes: + label: Estimated Test Count + placeholder: "e.g., 4 test files, ~50 tests" + + - type: dropdown + id: area + attributes: + label: Area + options: + - "Core (.aios-core/core/)" + - "Health Check (.aios-core/core/health-check/)" + - "Orchestration (.aios-core/core/orchestration/)" + - "Config (.aios-core/core/config/)" + - "SYNAPSE" + - "CLI / Installer" + - "Infrastructure" + - "Other" + validations: + required: true + + - type: input + id: related-issue + attributes: + label: Related Issue + description: Link to the parent issue if applicable. + placeholder: "#52" + + - type: checkboxes + id: checklist + attributes: + label: Checklist + options: + - label: "I have verified these modules lack test coverage" + required: true + - label: "Tests will use Jest (project standard)" + required: true + - label: "I can contribute the implementation" diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 8ee8a7990..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve AIOS-FullStack -title: '[BUG] ' -labels: ['bug', 'needs-triage'] -assignees: '' - ---- - -## 🐛 Bug Description -A clear and concise description of what the bug is. - -## 📦 Package Information -Which AIOS-FullStack package is affected? -- [ ] @synkra/aios-core/workspace -- [ ] @synkra/aios-core/core -- [ ] @synkra/aios-core/memory -- [ ] @synkra/aios-core/security -- [ ] @synkra/aios-core/performance -- [ ] @synkra/aios-core/telemetry - -**Version:** (e.g., 4.31.0) - -## 🔄 Steps to Reproduce -Steps to reproduce the behavior: -1. Install package '...' -2. Run command '...' -3. Call function '...' -4. See error - -## 💥 Expected Behavior -A clear and concise description of what you expected to happen. - -## 📱 Actual Behavior -A clear and concise description of what actually happened. - -## 📋 Code Example -```javascript -// Minimal code example that reproduces the issue -const { AIOS } = require('@synkra/aios-core/workspace'); - -const aios = new AIOS(); -// ... rest of your code -``` - -## 📄 Error Output -``` -Paste any error messages or stack traces here -``` - -## 🖥️ Environment -**System Information:** -- OS: [e.g., Windows 11, Ubuntu 22.04, macOS 14] -- Node.js version: [e.g., 20.11.0] -- NPM version: [e.g., 10.2.4] -- Package manager: [npm/yarn/pnpm] - -**AIOS Configuration:** -```javascript -// Your AIOS configuration (remove sensitive data) -const config = { - // ... -}; -``` - -## 📊 Health Check Output -If possible, run `aios.healthCheck()` and paste the output: -```javascript -// Health check results -``` - -## 🔍 Additional Context -Add any other context about the problem here. - -## 🎯 Priority -How critical is this bug for your use case? -- [ ] Critical - Blocking production use -- [ ] High - Significant impact on functionality -- [ ] Medium - Minor impact, workaround available -- [ ] Low - Enhancement or nice-to-have fix - -## ✅ Checklist -- [ ] I have searched existing issues to avoid duplicates -- [ ] I have provided all requested information -- [ ] I have tested with the latest version -- [ ] I can consistently reproduce this issue diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..6aef3e8ee --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Documentation + url: https://github.com/SynkraAI/aios-core/tree/main/docs + about: Check our documentation before opening an issue + - name: Discussions + url: https://github.com/SynkraAI/aios-core/discussions + about: Ask questions and share ideas in Discussions diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 46073af8a..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for AIOS-FullStack -title: '[FEATURE] ' -labels: ['enhancement', 'needs-triage'] -assignees: '' - ---- - -## 🚀 Feature Request - -### 📋 Summary -A clear and concise description of the feature you'd like to see added. - -### 🎯 Problem Statement -Is your feature request related to a problem? Please describe: -- What problem does this solve? -- What use case does this enable? - -### 💡 Proposed Solution -Describe the solution you'd like: -- How should this feature work? -- What API or interface would you expect? - -### 📦 Package Scope -Which AIOS-FullStack package should this feature belong to? -- [ ] @synkra/aios-core/workspace (overall framework) -- [ ] @synkra/aios-core/core (meta-agent, task management) -- [ ] @synkra/aios-core/memory (vector storage, semantic search) -- [ ] @synkra/aios-core/security (sanitization, vulnerability scanning) -- [ ] @synkra/aios-core/performance (monitoring, profiling, optimization) -- [ ] @synkra/aios-core/telemetry (analytics, error reporting, metrics) -- [ ] New package: ________________ - -### 📋 Code Example -What would the API look like? Provide a code example: - -```javascript -// Example of how this feature would be used -const { AIOS } = require('@synkra/aios-core/workspace'); - -const aios = new AIOS(); -// Your proposed feature usage here -``` - -### 🔄 Alternatives Considered -Describe alternatives you've considered: -- Other approaches to solve this problem -- Existing workarounds you're using -- Similar features in other frameworks - -### 🎨 Implementation Ideas -If you have ideas on how this could be implemented: -- Architecture considerations -- Dependencies that might be needed -- Potential challenges - -### 📊 Impact Assessment -How would this feature impact AIOS-FullStack? -- [ ] Breaking change - requires major version bump -- [ ] New functionality - backward compatible -- [ ] Enhancement to existing feature -- [ ] Performance improvement -- [ ] Developer experience improvement - -### 🔧 Technical Requirements -- **Performance**: Any performance considerations? -- **Security**: Any security implications? -- **Dependencies**: Would this require new dependencies? -- **Testing**: How should this be tested? - -### 📖 Documentation -What documentation would be needed? -- [ ] API documentation -- [ ] Usage examples -- [ ] Tutorial/guide -- [ ] Migration guide (if breaking change) - -### 🌟 Priority -How important is this feature to you? -- [ ] Critical - Blocking my use case -- [ ] High - Would significantly improve my workflow -- [ ] Medium - Nice to have -- [ ] Low - Minor improvement - -### 👥 Community Interest -- [ ] I would be willing to contribute to implementing this -- [ ] I can help with documentation -- [ ] I can help with testing -- [ ] I would be interested in reviewing the implementation - -### 🔗 Related Issues -- Link to any related issues or discussions -- Reference similar features in other projects - -### ✅ Checklist -- [ ] I have searched existing issues and feature requests -- [ ] I have provided a clear use case for this feature -- [ ] I have considered the impact on existing functionality -- [ ] I have provided enough detail for evaluation diff --git a/.github/issue-labeler.yml b/.github/issue-labeler.yml new file mode 100644 index 000000000..99a2c3254 --- /dev/null +++ b/.github/issue-labeler.yml @@ -0,0 +1,30 @@ +# Issue Labeler configuration (regex-based) +# Used by .github/workflows/issue-labeler.yml +# Matches regex patterns against issue body/title content +# +# Story: GHIM-001 - GitHub Issue Management +# Reference: https://github.com/github/issue-labeler + +# Type labels (matched against issue body) +"type: bug": + - '(\[Bug\]|bug report|something.*(isn.t|not) working|broken|crash|regression)' +"type: feature": + - '(\[Feature\]|feature request|propose|proposal|new feature|add support|add native)' +"type: docs": + - '(documentation|readme|typo in doc|missing doc|english readme)' +"type: test": + - '(\[Test\]|test coverage|unit test|add.*tests|missing.*tests)' + +# Area labels +"area: installer": + - '(npx aios-core|aios-core install|installer|wizard|onboarding|packages.installer)' +"area: core": + - '(\.aios-core.core|orchestration|config.*loader|core framework)' +"area: synapse": + - '(synapse|context engine|domain.*loader|hook.*engine)' +"area: cli": + - '(aios-core info|aios-core update|aios-core doctor|bin/|\.aios-core.cli)' +"area: pro": + - '(pro feature|license|aios-pro|pro/|pro submodule)' +"area: health-check": + - '(health.?check|doctor|diagnostic)' diff --git a/.github/labeler.yml b/.github/labeler.yml index ef6e4fc8e..28087b26d 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,141 +1,90 @@ # Labeler configuration for GitHub Actions -# Automatically labels PRs based on files changed -# Used by .github/workflows/pr-labeling.yml +# Used by: .github/workflows/pr-labeling.yml (PR file-based labeling via actions/labeler) +# NOTE: Issue body regex matching uses a SEPARATE file: .github/issue-labeler.yml # -# Reference: https://github.com/actions/labeler -# Story: OSR-4 - GitHub Community Setup +# Story: GHIM-001 - GitHub Issue Management +# Updated: 2026-02-20 # ============================================ -# CORE FRAMEWORK LABELS +# PR FILE-BASED LABELS (actions/labeler) +# Applied when PR changes files in these paths # ============================================ -core: +"area: core": - changed-files: - any-glob-to-any-file: - - '.aios-core/**/*' - - 'aios-core/**/*' - - 'src/core/**/*' + - '.aios-core/core/**/*' -agents: +"area: agents": - changed-files: - any-glob-to-any-file: - - '.aios-core/agents/**/*' - - '**/*.agent.md' + - '.aios-core/development/agents/**/*' - '.claude/commands/**/*' -templates: +"area: workflows": - changed-files: - any-glob-to-any-file: - - '.aios-core/**/templates/**/*' - - '**/*-tmpl.yaml' - - '**/*-tmpl.md' + - '.aios-core/development/workflows/**/*' -workflows: +"area: installer": - changed-files: - any-glob-to-any-file: - - '.aios-core/workflows/**/*' - - '**/*.workflow.yaml' - -# ============================================ -# SQUAD LABELS -# ============================================ - -squad: - - changed-files: - - any-glob-to-any-file: - - 'aios-squads/**/*' - - 'squads/**/*' + - 'packages/installer/**/*' + - 'bin/**/*' -'squad: etl': +"area: cli": - changed-files: - any-glob-to-any-file: - - 'aios-squads/etl-squad/**/*' - - 'squads/etl/**/*' + - 'packages/aios-pro-cli/**/*' + - 'bin/*.js' -'squad: creator': +"area: synapse": - changed-files: - any-glob-to-any-file: - - 'aios-squads/creator-squad/**/*' - - 'squads/creator/**/*' + - '.claude/hooks/**/*' + - '.claude/synapse/**/*' -# ============================================ -# MCP ECOSYSTEM LABELS -# ============================================ - -mcp: +"area: pro": - changed-files: - any-glob-to-any-file: - - 'mcp-ecosystem/**/*' - - '.aios-core/tools/mcp/**/*' - - '**/*mcp*.yaml' - - '**/*mcp*.json' + - 'pro/**/*' -docker-mcp: +"area: health-check": - changed-files: - any-glob-to-any-file: - - '.docker/mcp/**/*' - - '**/docker-mcp*.yml' - - '**/gateway-service.yml' + - '.aios-core/core/health-check/**/*' -preset: +"area: docs": - changed-files: - any-glob-to-any-file: - - 'mcp-ecosystem/presets/**/*' - - '**/*preset*.yaml' - - '**/*preset*.json' - -# ============================================ -# INFRASTRUCTURE LABELS -# ============================================ + - 'docs/**/*' + - '**/*.md' + - '!node_modules/**/*' + - '!.github/ISSUE_TEMPLATE/**/*' -ci/cd: +"area: devops": - changed-files: - any-glob-to-any-file: - '.github/**/*' - - '.github/workflows/**/*' - 'Dockerfile' - 'docker-compose*.yml' - - '.docker/**/*' -installer: +"type: test": - changed-files: - any-glob-to-any-file: - - 'tools/installer/**/*' - - 'bin/**/*' - - 'install*.js' - - 'setup*.js' - -# ============================================ -# DOCUMENTATION LABELS -# ============================================ - -documentation: - - changed-files: - - any-glob-to-any-file: - - 'docs/**/*' - - '**/*.md' - - '!node_modules/**/*' - - '!.github/ISSUE_TEMPLATE/**/*' - -# ============================================ -# DEVELOPMENT TOOLS LABELS -# ============================================ + - 'tests/**/*' + - '**/*.test.js' + - '**/*.spec.js' + - 'jest.config.*' -tools: +squad: - changed-files: - any-glob-to-any-file: - - 'tools/**/*' - - 'bin/**/*' - - 'scripts/**/*' - -# ============================================ -# TESTING LABELS -# ============================================ + - 'squads/**/*' -tests: +mcp: - changed-files: - any-glob-to-any-file: - - 'tests/**/*' - - '**/*.test.js' - - '**/*.spec.js' - - 'jest.config.*' + - '.aios-core/tools/mcp/**/*' + - '**/*mcp*.yaml' + - '**/*mcp*.json' diff --git a/.github/workflows/issue-labeler.yml b/.github/workflows/issue-labeler.yml new file mode 100644 index 000000000..fb9d4d9c1 --- /dev/null +++ b/.github/workflows/issue-labeler.yml @@ -0,0 +1,25 @@ +# Issue Labeler Workflow +# Auto-labels issues based on body content regex matching +# +# Story: GHIM-001 - GitHub Issue Management +# Reference: https://github.com/github/issue-labeler + +name: Issue Labeler + +on: + issues: + types: [opened, edited] + +permissions: + issues: write + contents: read + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: github/issue-labeler@v3.4 + with: + configuration-path: .github/issue-labeler.yml + enable-versioned-regex: 0 + repo-token: ${{ github.token }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..fe2d51f03 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,48 @@ +name: Manage Stale Issues + +on: + schedule: + - cron: '30 1 * * *' + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + # Issue configuration + days-before-issue-stale: 30 + days-before-issue-close: 7 + stale-issue-label: 'status: stale' + stale-issue-message: | + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed in 7 days if no further activity occurs. + + If this issue is still relevant, please leave a comment to keep it open. + close-issue-message: | + This issue has been automatically closed due to inactivity. + If you believe this is still relevant, please reopen it with additional context. + close-issue-reason: 'not_planned' + + # PR configuration + days-before-pr-stale: 45 + days-before-pr-close: -1 + stale-pr-label: 'status: stale' + stale-pr-message: | + This pull request has been automatically marked as stale because it has not had + recent activity. Please update it or it may be closed. + + # Exemptions + exempt-issue-labels: 'priority: P1,priority: P2,status: in-progress,status: confirmed' + exempt-pr-labels: 'priority: P1,priority: P2,status: in-progress' + exempt-all-assignees: true + exempt-draft-pr: true + + # Behavior + remove-stale-when-updated: true + operations-per-run: 30 diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml index dd4e08d52..e8d9f075a 100644 --- a/.github/workflows/welcome.yml +++ b/.github/workflows/welcome.yml @@ -2,14 +2,14 @@ # Automatically welcomes first-time contributors to AIOS # # Reference: https://github.com/actions/first-interaction -# Story: OSR-4 - GitHub Community Setup +# Story: GHIM-001 - GitHub Issue Management name: Welcome New Contributors on: issues: types: [opened] - pull_request: + pull_request_target: types: [opened] permissions: @@ -25,51 +25,33 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} issue-message: | - 👋 **Welcome to AIOS!** - - Thanks for opening your first issue! We're excited to have you here. + Welcome to **aios-core**! Thanks for opening your first issue. **What happens next?** - - A maintainer will review your issue and add appropriate labels + - A maintainer will triage this and add appropriate labels - We'll respond as soon as possible - - Feel free to join the discussion in our [Community Discussions](https://github.com/SynkraAI/aios-core/discussions) + - Feel free to join [Community Discussions](https://github.com/SynkraAI/aios-core/discussions) **Helpful Resources:** - - 📖 [Contributing Guide](CONTRIBUTING.md) - - 💬 [Community Discussions](https://github.com/SynkraAI/aios-core/discussions) - - 📚 [Documentation](docs/) - - **Labels Guide:** - - `good-first-issue` - Great for newcomers - - `help-wanted` - We need community help - - `bug` - Something isn't working - - `enhancement` - Feature requests + - [Contributing Guide](https://github.com/SynkraAI/aios-core/blob/main/CONTRIBUTING.md) + - [Documentation](https://github.com/SynkraAI/aios-core/tree/main/docs) - Thanks for helping make AIOS better! 🚀 + **Looking to contribute?** Check issues labeled `community: good first issue`. pr-message: | - 🎉 **Welcome to AIOS!** - - Thanks for submitting your first pull request! We're thrilled to have you contribute. + Welcome to **aios-core**! Thanks for your first pull request. **What happens next?** 1. Automated checks will run on your PR 2. A maintainer will review your changes - 3. We may suggest improvements or ask questions - 4. Once approved, we'll merge your contribution! + 3. Once approved, we'll merge your contribution! **PR Checklist:** - - [ ] Tests pass locally (`npm test`) + - [ ] Tests pass (`npm test`) - [ ] Linting passes (`npm run lint`) - - [ ] Documentation updated (if applicable) - - [ ] Commit messages follow [conventional commits](https://www.conventionalcommits.org/) - - **Helpful Resources:** - - 📖 [Contributing Guide](CONTRIBUTING.md) - - 📜 [Code of Conduct](CODE_OF_CONDUCT.md) - - 🏗️ [Coding Standards](docs/architecture/coding-standards.md) + - [ ] Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/) - Thanks for contributing to AIOS! 🚀 + Thanks for contributing! - name: Add triage label to new issues if: github.event_name == 'issues' @@ -83,7 +65,7 @@ jobs: }); const hasTriageLabel = labels.data.some(label => - label.name === 'needs-triage' + label.name === 'status: needs-triage' ); if (!hasTriageLabel) { @@ -91,6 +73,6 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, - labels: ['needs-triage'] + labels: ['status: needs-triage'] }); } diff --git a/docs/research/2026-02-20-github-issue-management/00-query-original.md b/docs/research/2026-02-20-github-issue-management/00-query-original.md new file mode 100644 index 000000000..d81f27adc --- /dev/null +++ b/docs/research/2026-02-20-github-issue-management/00-query-original.md @@ -0,0 +1,28 @@ +# Query Original + +## User Query + +"GitHub issue management best practices 2025 2026 - automation, triage workflows, labeling strategies, issue templates, GitHub Actions for issue management, community issue handling for open source projects" + +## Inferred Context + +```yaml +focus: technical +temporal: recent (2025-2026) +domain: + - GitHub + - GitHub Actions + - Open Source + - CI/CD + - Community Management +skip_clarification: true +``` + +## Motivation + +Investigar melhores praticas para gerenciar issues do GitHub no repositorio aios-core, com foco em: +1. Automacao de triage de issues +2. Templates estruturados para bug reports e feature requests +3. Estrategia de labeling consistente +4. GitHub Actions para automacao +5. Gestao de comunidade open source diff --git a/docs/research/2026-02-20-github-issue-management/01-deep-research-prompt.md b/docs/research/2026-02-20-github-issue-management/01-deep-research-prompt.md new file mode 100644 index 000000000..ed62fe27c --- /dev/null +++ b/docs/research/2026-02-20-github-issue-management/01-deep-research-prompt.md @@ -0,0 +1,31 @@ +# Deep Research Prompt + +## Decomposition Strategy + +5 sub-queries ortogonais cobrindo angulos complementares: + +### Sub-query 1: Triage Automation +"GitHub issue triage automation best practices 2025 2026 - auto-labeling, stale issue bots, triage workflows" + +### Sub-query 2: Issue Templates & Forms +"GitHub issue templates and issue forms YAML best practices 2025 - bug report, feature request, structured forms" + +### Sub-query 3: GitHub Actions Workflows +"GitHub Actions for issue management - auto-label, auto-close stale, auto-assign, welcome bot, first-time contributor workflows 2025" + +### Sub-query 4: Labeling Strategy +"GitHub issue labeling strategy taxonomy for open source projects - priority labels, type labels, status labels, area labels, best label systems 2025" + +### Sub-query 5: Community Management +"open source community issue management - contributor experience, issue SLA response times, triage process documentation, CODEOWNERS for issue routing, GitHub Projects for issue tracking 2025" + +## Search Results Summary + +| Worker | Sources Found | High Credibility | Code Examples | +|--------|--------------|-------------------|---------------| +| Triage Automation | 3 | 3 | 6 | +| Issue Templates | 3 | 3 | 5 | +| GitHub Actions | 3 | 2 | 3 | +| Labeling Strategy | 5 | 4 | 2 | +| Community Mgmt | 3 | 2 | 2 | +| **Total** | **17** | **14** | **18** | diff --git a/docs/research/2026-02-20-github-issue-management/02-research-report.md b/docs/research/2026-02-20-github-issue-management/02-research-report.md new file mode 100644 index 000000000..21a8d2fad --- /dev/null +++ b/docs/research/2026-02-20-github-issue-management/02-research-report.md @@ -0,0 +1,277 @@ +# GitHub Issue Management — Research Report + +## 1. Issue Templates & Forms (Structured Input) + +### Key Findings + +GitHub Issue Forms substituem templates `.md` com formularios YAML estruturados em `.github/ISSUE_TEMPLATE/`: + +- **5 tipos de elementos:** `textarea`, `input`, `dropdown`, `checkboxes`, `markdown` (display-only) +- **Keys obrigatorias:** `name`, `description`, `body` (array de fields) +- **Automacao integrada:** `labels`, `assignees`, `projects`, `title` no top-level do YAML +- **Validacao:** `required: true` funciona APENAS em repos publicos +- **Ordenacao:** prefixo numerico nos nomes: `1-bug.yml`, `2-feature-request.yml` +- **config.yml:** controla o template chooser, pode impedir issues sem template + +### Exemplo: Bug Report Form + +```yaml +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug", "needs-triage"] +assignees: + - octocat +body: + - type: markdown + attributes: + value: "Thanks for taking the time!" + - type: textarea + id: what-happened + attributes: + label: What happened? + placeholder: Describe the issue + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: Steps to Reproduce + value: | + 1. + 2. + 3. + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + options: + - "4.2.13 (Latest)" + - "4.2.12" + - "4.1.x" + default: 0 + validations: + required: true + - type: textarea + attributes: + label: Error Output + render: bash + - type: checkboxes + id: agreements + attributes: + label: Acknowledgments + options: + - label: "I searched for existing issues" + required: true +``` + +--- + +## 2. Labeling Strategy (Taxonomy) + +### Key Findings + +Projetos maduros usam **taxonomia com prefixos** para labels: + +| Categoria | Prefixo | Cor | Exemplos | +|-----------|---------|-----|----------| +| Type | `type:` | Verde claro (#90EE90) | `type: bug`, `type: feature`, `type: docs` | +| Priority | `priority:` | Vermelho-amarelo gradient | `priority: P1` (critical) a `priority: P4` (low) | +| Status | `status:` | Cinza (#D3D3D3) | `status: needs-triage`, `status: needs-info`, `status: stale` | +| Area | `area:` | Azul claro (#ADD8E6) | `area: installer`, `area: core`, `area: synapse` | +| Community | (sem prefixo) | Roxo | `good first issue`, `help wanted` | + +### Regras + +- **Uma label por categoria** por issue (1 type, 1 priority, 1 status) +- **Default labels do GitHub** como base: bug, enhancement, documentation, question +- `good first issue` e `help wanted` populam paginas de contribuicao automaticamente +- freeCodeCamp e Kubernetes citados como implementacoes de referencia + +### Priority Scale (P1-P4) + +| Level | Descricao | SLA Target | +|-------|-----------|------------| +| P1 | Critical — bloqueia usuarios | 24h response | +| P2 | High — afeta maioria | 3 dias | +| P3 | Medium — afeta parte dos usuarios | 1 semana | +| P4 | Low — edge cases | Backlog | + +--- + +## 3. Triage Automation + +### Key Findings + +Tres abordagens complementares: + +#### A) GitHub Agentic Workflows (2026 — Novo) +- AI agents analisam issues sem labels, pesquisam contexto no codebase, aplicam labels e postam comentarios +- Configuracao via YAML frontmatter com permissions grants e output constraints +- Requer `lockdown: false` para repos publicos +- Reducao de 60-70% em triage manual reportada + +```yaml +--- +timeout-minutes: 5 +on: + issue: + types: [opened, reopened] +permissions: + issues: read +tools: + github: + toolsets: [issues, labels] +safe-outputs: + add-labels: + allowed: [bug, feature, enhancement, documentation, + question, help-wanted, good-first-issue] + add-comment: {} +--- +``` + +#### B) github/issue-labeler v3.4 (Regex-based) +- Auto-label baseado em regex matching no body/title do issue +- Suporta versioned regex para evolucao de templates +- Label `broken-template` para issues que nao seguem o template + +```yaml +name: Issue Labeler +on: + issues: + types: [opened, edited] +permissions: + issues: write + contents: read +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: github/issue-labeler@v3.4 + with: + configuration-path: .github/labeler.yml + enable-versioned-regex: 1 + repo-token: ${{ github.token }} +``` + +#### C) Hybrid (Recomendado) +- Issue Labeler para classificacao rapida via regex +- Agentic Workflows para analise semantica profunda +- Human review para decisoes finais + +--- + +## 4. Stale Issue Management + +### Key Findings + +`actions/stale` v10 e o padrao da industria: + +- **Dois estagios:** Stage 1 aplica label "stale" apos N dias; Stage 2 fecha apos M dias adicionais +- **Rate limiting:** `operations-per-run: 30` previne quota exhaustion +- **Exemptions:** por label, milestone, assignee, draft PRs +- **Auto-removal:** label stale removida automaticamente quando ha nova atividade +- **Close reason:** `not_planned` ou `completed` + +```yaml +name: Close stale issues and PRs +on: + schedule: + - cron: '30 1 * * *' +jobs: + stale: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v10 + with: + days-before-issue-stale: 30 + days-before-pr-stale: 45 + days-before-issue-close: 7 + days-before-pr-close: -1 + stale-issue-label: 'status: stale' + stale-issue-message: | + This issue has been automatically marked as stale due to 30 days of inactivity. + It will be closed in 7 days if no further activity occurs. + If this is still relevant, please comment to keep it open. + exempt-issue-labels: 'priority: P1,priority: P2,status: in-progress' + remove-stale-when-updated: true + operations-per-run: 30 + close-issue-reason: 'not_planned' +``` + +--- + +## 5. Community & Contributor Experience + +### Kubernetes Model (Reference) + +| Metric | Threshold | Action | +|--------|-----------|--------| +| No SIG action | 30 days | Follow-up outreach | +| No reporter response | 20 days | Auto-close | +| Stale marker | 90 days | Auto-close via bot | + +### Five-Step Triage Process (Kubernetes) + +1. **Review** — Processar issues novos +2. **Categorize** — Tipo (support/bug/feature/duplicate) +3. **Prioritize** — Nivel P1-P4 +4. **Route** — Atribuir a SIG/team via labels +5. **Follow-up** — Protocolos de acompanhamento + +### CODEOWNERS para Routing + +``` +# Default owners +* @oalanicolas + +# Specific paths +/.aios-core/core/ @oalanicolas +/packages/installer/ @oalanicolas +/docs/ @oalanicolas +/.github/ @oalanicolas + +# Patterns +*.test.js @oalanicolas +``` + +### Tooling + +- **CODEOWNERS:** Routing de PRs automatico, requer write access +- **GitHub Projects:** Kanban boards para tracking por area/sprint +- **Triage Party (Kubernetes):** Queries avancadas (regex, reactions, conversation direction) +- **Weekly triage meetings:** Entrada de baixa barreira para novos contribuidores + +--- + +## 6. Decision Matrix + +| Necessidade | Ferramenta | Complexidade | Impacto | +|-------------|-----------|--------------|---------| +| Issues estruturados | Issue Forms YAML | Baixa | Alto | +| Auto-labeling por conteudo | github/issue-labeler | Baixa | Medio | +| AI triage semantico | Agentic Workflows | Media | Alto | +| Gestao de stale issues | actions/stale | Baixa | Alto | +| Routing por area | CODEOWNERS + labels | Baixa | Medio | +| Welcome first-timers | welcome bot Action | Baixa | Medio | +| Label taxonomy | Prefixed labels setup | Baixa | Alto | + +--- + +## Sources + +1. GitHub Docs — Issue Forms Syntax (HIGH) +2. GitHub Docs — Form Schema Syntax (HIGH) +3. GitHub Agentic Workflows — Issue Triage (HIGH) +4. github/issue-labeler v3.4 (HIGH) +5. actions/stale v10 (HIGH) +6. Kubernetes Issue Triage Guidelines (HIGH) +7. GitHub Docs — CODEOWNERS (HIGH) +8. Rewind Blog — Best Practices for GitHub Issues (HIGH) +9. Dave Lunny — Sane GitHub Labels (HIGH) +10. CICube — Automating Stale Issues (HIGH) diff --git a/docs/research/2026-02-20-github-issue-management/03-recommendations.md b/docs/research/2026-02-20-github-issue-management/03-recommendations.md new file mode 100644 index 000000000..3c016047b --- /dev/null +++ b/docs/research/2026-02-20-github-issue-management/03-recommendations.md @@ -0,0 +1,153 @@ +# Recommendations for aios-core + +## Context + +O repositorio aios-core tem atualmente 27 issues abertos, todos com label `needs-triage`, sem templates estruturados, sem automacao de triage, e sem estrategia de labeling definida. + +--- + +## Recommended Implementation Plan + +### Phase 1: Foundation (Labels + Templates) + +#### 1.1 Label Taxonomy + +Criar taxonomia completa com prefixos: + +``` +type: bug (#d73a4a, vermelho) +type: feature (#a2eeef, azul claro) +type: enhancement (#a2eeef, azul claro) +type: docs (#0075ca, azul) +type: test (#ededed, cinza) +type: chore (#ededed, cinza) + +priority: P1 (#b60205, vermelho escuro) +priority: P2 (#d93f0b, laranja) +priority: P3 (#fbca04, amarelo) +priority: P4 (#0e8a16, verde) + +status: needs-triage (#ededed, cinza) +status: needs-info (#d876e3, roxo) +status: confirmed (#0e8a16, verde) +status: in-progress (#1d76db, azul) +status: stale (#ffffff, branco) + +area: core (#006b75, teal) +area: installer (#006b75, teal) +area: synapse (#006b75, teal) +area: cli (#006b75, teal) +area: pro (#006b75, teal) +area: docs (#006b75, teal) +area: health-check (#006b75, teal) +area: devops (#006b75, teal) + +community: good first issue (#7057ff, roxo) +community: help wanted (#008672, verde escuro) + +governance (#006b75, teal) +duplicate (#cfd3d7, cinza) +wontfix (#ffffff, branco) +``` + +#### 1.2 Issue Forms + +Criar 4 templates em `.github/ISSUE_TEMPLATE/`: + +1. `1-bug-report.yml` — Bug report com steps to reproduce, versao, error output +2. `2-feature-request.yml` — Feature request com problem statement, proposed solution, package scope +3. `3-test-coverage.yml` — Test coverage PR (para issues de teste recorrentes) +4. `config.yml` — Impedir issues sem template, link para Discussions + +#### 1.3 CODEOWNERS + +``` +# .github/CODEOWNERS +* @oalanicolas +/.aios-core/core/ @oalanicolas +/packages/ @oalanicolas +/docs/ @oalanicolas +/.github/ @oalanicolas +``` + +### Phase 2: Automation (GitHub Actions) + +#### 2.1 Auto-Label on Issue Open + +```yaml +# .github/workflows/issue-labeler.yml +name: Issue Labeler +on: + issues: + types: [opened, edited] +``` + +Usar `github/issue-labeler@v3.4` com regex matching. + +#### 2.2 Stale Issue Management + +```yaml +# .github/workflows/stale.yml +name: Manage Stale Issues +on: + schedule: + - cron: '30 1 * * *' +``` + +Usar `actions/stale@v10` com 30 dias stale, 7 dias close, exempt P1/P2. + +#### 2.3 Welcome First-Time Contributors + +Workflow que posta mensagem de boas-vindas no primeiro issue/PR de novos contribuidores. + +### Phase 3: Triage Process + +#### 3.1 Script de Triage Batch + +Script Node.js para @devops executar triage em batch: +- Lista issues `needs-triage` +- Apresenta cada issue para classificacao +- Aplica labels via GitHub API +- Gera relatorio de triage + +#### 3.2 Task de Triage para @devops + +Nova task `.aios-core/development/tasks/github-issue-triage.md` com: +- Checklist de triage por issue +- Criterios de classificacao +- Workflow de resposta + +#### 3.3 Checklist de Triage + +Nova checklist `.aios-core/development/checklists/issue-triage-checklist.md` + +--- + +## Mapping to Existing Tasks + +| Existing Task | Relationship | +|--------------|-------------| +| `github-devops-repository-cleanup.md` | Complementar — cleanup inclui issues stale | +| `github-devops-github-pr-automation.md` | Paralelo — PR automation + Issue automation | +| `github-devops-pre-push-quality-gate.md` | Independente | +| `setup-github.md` | Extend — adicionar issue templates ao setup | + +--- + +## Priority Order + +1. **Label taxonomy** — fundacao para tudo mais +2. **Issue forms** — melhora qualidade de input imediatamente +3. **Stale management** — resolve backlog automaticamente +4. **Auto-labeler** — reduz trabalho manual de triage +5. **Triage task/script** — formaliza processo para @devops +6. **Welcome bot** — nice-to-have para contributor experience + +--- + +## Next Steps + +- `@pm` deve priorizar esta story no roadmap +- `@devops` deve implementar Labels + Templates + Actions +- `@dev` pode implementar script de triage batch +- Considerar epic dedicado se escopo crescer diff --git a/docs/research/2026-02-20-github-issue-management/README.md b/docs/research/2026-02-20-github-issue-management/README.md new file mode 100644 index 000000000..0ac89c448 --- /dev/null +++ b/docs/research/2026-02-20-github-issue-management/README.md @@ -0,0 +1,27 @@ +# GitHub Issue Management Best Practices — Research + +**Date:** 2026-02-20 +**Query:** GitHub issue management best practices - automation, triage workflows, labeling strategies, issue templates, GitHub Actions, community handling +**Coverage Score:** 85/100 +**Workers:** 5/5 successful + +## TL;DR + +GitHub issue management moderno combina **issue forms YAML** para coleta estruturada, **GitHub Actions** para automacao de triage/stale/labeling, e **taxonomia de labels com prefixos** para organizacao. Projetos maduros como Kubernetes usam SLAs de 30 dias, bots de triage, e roteamento via labels/CODEOWNERS. Em 2026, GitHub Agentic Workflows permitem AI-driven triage com analise semantica. + +## Files + +| File | Content | +|------|---------| +| [00-query-original.md](./00-query-original.md) | Query original + contexto inferido | +| [01-deep-research-prompt.md](./01-deep-research-prompt.md) | Sub-queries decompostas | +| [02-research-report.md](./02-research-report.md) | Findings completos | +| [03-recommendations.md](./03-recommendations.md) | Recomendacoes para aios-core | + +## Sources (Top) + +- GitHub Docs: Issue Forms Syntax +- GitHub Agentic Workflows (2026) +- actions/stale v10, github/issue-labeler v3.4 +- Kubernetes Issue Triage Guidelines +- GitHub CODEOWNERS Documentation diff --git a/docs/stories/active/GHIM-001.story.md b/docs/stories/active/GHIM-001.story.md new file mode 100644 index 000000000..1c71dca26 --- /dev/null +++ b/docs/stories/active/GHIM-001.story.md @@ -0,0 +1,237 @@ +# GHIM-001: GitHub Issue Management — Automation & Triage System + +**Story ID:** GHIM-001 +**Epic:** Standalone — Repository Governance +**Status:** Ready +**Priority:** High +**Created:** 2026-02-20 +**Owner:** @devops (Gage) +**Research:** `docs/research/2026-02-20-github-issue-management/` + +--- + +## Description + +Implementar um sistema completo de gestao de issues do GitHub para o repositorio aios-core, incluindo templates estruturados (issue forms), taxonomia de labels com prefixos, automacao via GitHub Actions (auto-labeling, stale management, welcome bot), e uma task formal de triage para @devops. + +### Problem Statement + +O repositorio aios-core possui 27 issues abertos, todos com label generico `needs-triage`, sem templates estruturados para coleta de informacao, sem automacao de triage, e sem estrategia de labeling consistente. Isso resulta em: +- Issues com informacao incompleta +- Classificacao manual demorada +- Nenhum SLA de resposta +- Contribuidores sem feedback automatico +- Backlog de issues stale sem gestao + +### Research Basis + +Pesquisa completa em `docs/research/2026-02-20-github-issue-management/` cobrindo: +- GitHub Issue Forms YAML (GitHub Docs) +- GitHub Agentic Workflows (2026) +- actions/stale v10, github/issue-labeler v3.4 +- Kubernetes Issue Triage Guidelines +- Label taxonomy best practices (freeCodeCamp, Dave Lunny) +- CODEOWNERS para routing + +--- + +## Acceptance Criteria + +### Phase 1: Foundation + +- [x] Label taxonomy implementada no repositorio com prefixos (`type:`, `priority:`, `status:`, `area:`, `community:`) +- [x] Labels existentes migradas para nova taxonomia +- [x] Issue form: Bug Report (`1-bug-report.yml`) criado e funcional +- [x] Issue form: Feature Request (`2-feature-request.yml`) criado e funcional +- [x] Issue form: Test Coverage (`3-test-coverage.yml`) criado e funcional +- [x] `config.yml` configurado para template chooser +- [x] CODEOWNERS verificado — ja existente e bem estruturado em `.github/CODEOWNERS` + +### Phase 2: Automation + +- [x] GitHub Action: `issue-labeler.yml` — auto-label baseado em regex do body/title +- [x] GitHub Action: `stale.yml` — marca stale 30d, fecha 7d, exempt P1/P2 +- [x] GitHub Action: `welcome.yml` — atualizada com labels novos + `pull_request_target` +- [x] Configuracao: `.github/issue-labeler.yml` regex para issues + `.github/labeler.yml` atualizado para PRs +- [ ] Cada Action executou pelo menos 1 vez com sucesso em issue de teste + +### Phase 3: Triage Process + +- [x] Task criada: `.aios-core/development/tasks/github-issue-triage.md` +- [x] Checklist criada: `.aios-core/development/checklists/issue-triage-checklist.md` +- [x] Script de triage batch: `.aios-core/development/scripts/issue-triage.js` +- [x] 31 issues existentes triados com novas labels aplicadas (0 untriaged remaining) +- [x] Documentacao de processo de triage no script/task + +--- + +## Scope + +### IN Scope + +- Label taxonomy com prefixos e cores +- 3 issue form templates YAML +- config.yml para template chooser +- CODEOWNERS file +- 3 GitHub Actions workflows (labeler, stale, welcome) +- Task de triage para @devops +- Checklist de triage +- Script de triage batch +- Triage dos 27 issues existentes + +### Risks + +- Labels com `:` no nome podem causar problemas no GitHub CLI — testar `gh issue edit --add-label "type: bug"` antes do rollout +- `config.yml` bloqueando issues sem template pode frustrar contribuidores que nao encontram template adequado — manter link para "Open a blank issue" como fallback +- `actions/stale` pode fechar issues legitimamente ativos se exemptions mal configuradas — validar lista de exempt labels antes de ativar +- Migracao de labels existentes pode desconectar issues de filtros salvos por contribuidores — comunicar mudanca via issue/discussion + +### OUT of Scope + +- GitHub Projects board setup (future story) +- GitHub Agentic Workflows / AI triage (requires GitHub Enterprise, future epic) +- Issue metrics/analytics dashboard +- SLA enforcement automation +- Slack/Discord notifications para issues + +--- + +## Dependencies + +### Existing Tasks (Related) + +| Task | Relationship | +|------|-------------| +| `github-devops-repository-cleanup.md` | Complementar — stale issues | +| `github-devops-github-pr-automation.md` | Paralelo — PR + Issue automation | +| `setup-github.md` | Extend — adicionar templates ao setup | + +### New Artifacts to Create + +| Type | Path | Description | +|------|------|-------------| +| Task | `.aios-core/development/tasks/github-issue-triage.md` | Processo formal de triage | +| Checklist | `.aios-core/development/checklists/issue-triage-checklist.md` | Checklist por issue | +| Script | `.aios-core/development/scripts/issue-triage.js` | Triage batch via `gh` CLI | +| Template | `.github/ISSUE_TEMPLATE/1-bug-report.yml` | Bug report form | +| Template | `.github/ISSUE_TEMPLATE/2-feature-request.yml` | Feature request form | +| Template | `.github/ISSUE_TEMPLATE/3-test-coverage.yml` | Test coverage PR | +| Config | `.github/ISSUE_TEMPLATE/config.yml` | Template chooser config | +| Config | `.github/labeler.yml` | Regex rules para auto-labeling | +| Action | `.github/workflows/issue-labeler.yml` | Auto-label on issue open | +| Action | `.github/workflows/stale.yml` | Stale issue management | +| Action | `.github/workflows/welcome.yml` | Welcome first-timers | +| Config | `.github/CODEOWNERS` | Code ownership routing | + +--- + +## Technical Notes + +### Label Taxonomy + +``` +type: bug (#d73a4a) type: feature (#a2eeef) +type: enhancement (#a2eeef) type: docs (#0075ca) +type: test (#ededed) type: chore (#ededed) + +priority: P1 (#b60205) priority: P2 (#d93f0b) +priority: P3 (#fbca04) priority: P4 (#0e8a16) + +status: needs-triage (#ededed) status: needs-info (#d876e3) +status: confirmed (#0e8a16) status: in-progress (#1d76db) +status: stale (#ffffff) + +area: core (#006b75) area: installer (#006b75) +area: synapse (#006b75) area: cli (#006b75) +area: pro (#006b75) area: health-check (#006b75) + +community: good first issue (#7057ff) +community: help wanted (#008672) +governance (#006b75) duplicate (#cfd3d7) wontfix (#ffffff) +``` + +### Stale Policy + +- Issues: stale after 30 days, close after 7 more days +- PRs: stale after 45 days, never auto-close (`days-before-pr-close: -1`) +- Exempt: `priority: P1`, `priority: P2`, `status: in-progress` +- Schedule: daily at 01:30 UTC + +### Key Actions + +- `github/issue-labeler@v3.4` — regex-based auto-labeling +- `actions/stale@v9` — stale issue lifecycle +- Custom welcome workflow — first-time contributor greeting + +--- + +## Definition of Done + +- [ ] Todas as labels criadas e visiveis no repositorio (`gh label list` retorna taxonomia completa) +- [ ] Issue forms renderizam corretamente no GitHub (testar criando issue de teste) +- [ ] GitHub Actions executam sem erros no primeiro run (check Actions tab) +- [ ] 27 issues existentes re-triados com novas labels aplicadas +- [ ] Task de triage documentada e disponivel via `*help` do @devops +- [ ] Labels existentes (`needs-triage`, `enhancement`, `bug`, etc.) migradas ou removidas +- [ ] Nenhum issue sem pelo menos 1 label de `type:` e 1 de `priority:` apos triage + +--- + +## Complexity + +| Dimension | Score (1-5) | Notes | +|-----------|------------|-------| +| Scope | 3 | 12 novos arquivos, label setup | +| Integration | 2 | GitHub API, Actions | +| Infrastructure | 2 | CI workflows | +| Knowledge | 2 | GitHub Issue Forms, Actions | +| Risk | 1 | Nao-destrutivo, incremental | +| **Total** | **10** | STANDARD complexity | + +--- + +## Estimation + +- **Phase 1 (Foundation):** 1-2 horas +- **Phase 2 (Automation):** 1-2 horas +- **Phase 3 (Triage):** 2-3 horas +- **Total:** ~5-7 horas + +--- + +## File List + +_Updated as implementation progresses._ + +| File | Action | Status | +|------|--------|--------| +| `docs/stories/active/GHIM-001.story.md` | Create | Done | +| `docs/research/2026-02-20-github-issue-management/` | Create | Done | +| `.github/ISSUE_TEMPLATE/1-bug-report.yml` | Create | Done | +| `.github/ISSUE_TEMPLATE/2-feature-request.yml` | Create | Done | +| `.github/ISSUE_TEMPLATE/3-test-coverage.yml` | Create | Done | +| `.github/ISSUE_TEMPLATE/config.yml` | Create | Done | +| `.github/ISSUE_TEMPLATE/bug_report.md` | Delete | Done | +| `.github/ISSUE_TEMPLATE/feature_request.md` | Delete | Done | +| GitHub Labels (44 total) | Migrate/Create | Done | +| `.github/workflows/issue-labeler.yml` | Create | Done | +| `.github/workflows/stale.yml` | Create | Done | +| `.github/workflows/welcome.yml` | Update | Done | +| `.github/issue-labeler.yml` | Create | Done | +| `.github/labeler.yml` | Update | Done | +| `.github/issue-labeler.yml` | Create | Done | +| `.aios-core/development/tasks/github-issue-triage.md` | Create | Done | +| `.aios-core/development/checklists/issue-triage-checklist.md` | Create | Done | +| `.aios-core/development/scripts/issue-triage.js` | Create | Done | + +--- + +## Change Log + +| Date | Author | Change | +|------|--------|--------| +| 2026-02-20 | @devops (Gage) | Story created with research basis | +| 2026-02-20 | @po (Pax) | Validated: GO CONDICIONAL (7/10). Applied fixes: Risks section, DoD section, epic alignment, AC refinement. Status Draft → Ready | +| 2026-02-20 | @devops (Gage) | Phase 1 complete: 13 labels renamed, 12 labels created, 6 obsolete deleted. 3 issue forms YAML + config.yml created. Old .md templates removed. | +| 2026-02-20 | @devops (Gage) | Phase 2 complete: 3 workflows created/updated (issue-labeler, stale, welcome). issue-labeler.yml config with regex rules. labeler.yml updated for PR file-based labeling with new label names. | +| 2026-02-20 | @devops (Gage) | Phase 3 complete: Task, checklist, script created. 31 issues triaged (5 bugs, 17 tests, 4 features, 3 chores, 1 docs, 1 governance). 0 untriaged remaining. |