{"id":"a0184d13-f341-42b5-ad99-396a907066fe","shortId":"yWLFW9","kind":"skill","title":"add-feature","tagline":">-","description":"!../principles/SKILL_BODY.md\n\n!../tool-gitnexus/SKILL_BODY.md\n\n---\n\n# New Feature / Module Workflow\n\n## Core Principle\n\nWhen adding new features, **integrate into the existing architecture like a native, not an outsider who starts from scratch**. New code should be fully consistent with existing code in style, structure, and interaction patterns.\n\n---\n\n## Complete Execution Workflow\n\n> **Progress tracking:** At the start of each step, output an updated progress block. For Lightweight tasks show only Steps 3–4; for Medium/Large tasks show all steps.\n>\n> ```\n> Add Feature Progress\n> ✓ Step 1: Architecture Research     — <one-line finding>\n> → Step 2: Solution Design + Confirm — in progress\n> ○ Step 2.5: TDD Contract Tests      — (Large/Medium only)\n> ○ Step 3: Implement\n> ○ Step 4: Architecture Audit\n> ```\n>\n> Replace `○` with `→` for the current step, and `✓` once complete.\n\n---\n\n### Step 1: Understand the Existing Architecture\n\nBefore starting, you must be able to answer the following questions:\n\n**Architecture awareness:**\n- What architectural pattern does the project use? (MVC / MVVM / Clean Architecture / Component-based / Microservices…)\n- How are similar existing features implemented? (Find the best reference)\n- What is the logic behind the project's directory structure? (By layer, by feature, by domain?)\n\n**Positioning analysis:**\n- Which layer does the new feature belong to? Where is its entry point?\n- Which existing modules does the new feature need to depend on?\n- Are there already extendable abstraction points (e.g., existing strategy interfaces, factory registries, event buses), or do new ones need to be created?\n\n**Reference module:**\n- Find **the most similar existing module** to the new feature as an implementation reference\n- Observe its file structure, naming conventions, dependency injection approach, error handling patterns, and test organization\n- The new module should follow the same patterns as closely as possible\n\n🔗 When GitNexus is available, use `query` / `context` MCP tools for architecture exploration.\n\n```\n─── Pre-Implementation Research Checklist ───────────\n[ ] Understand the project architecture pattern and directory organization\n[ ] Found the most similar reference module\n[ ] Determined which layer the new feature belongs to\n[ ] Determined the new feature's dependencies\n[ ] Confirmed whether there are extendable abstraction points\n[ ] Confirmed no overlap with responsibilities of existing modules\n─────────────────────────────────────────────────────\n```\n\n### Step 2: Design the Solution\n\nBefore writing code, clarify the design:\n\n**Location decision:**\n- Place it at the same directory level as similar features\n- If it's an entirely new domain, create a parallel structure referencing existing module directory structure\n\n**Integration approach (priority order, high to low):**\n```\n─── Integration Strategy Priority ───────────────────\n1. Registry-based: Register with existing factory/registry/routing table → zero changes to existing code\n2. Extension-point-based: Implement existing abstraction/strategy interface → add only, don't modify\n3. Event-driven: Publish/subscribe via event bus → decoupled from existing modules\n4. Config-driven: Enable new feature through config files → main flow is unaware\n5. Invasive: Modify existing module code to integrate new feature → last resort\n─────────────────────────────────────────────────────\n```\n\n**For large tasks, inform the user of:**\n- Which integration approach is being used\n- The responsibility boundary of the new module\n- How it interacts with existing modules\n- Expected file structure\n\n### Confirmation Gate (between Step 2 and Step 3)\n\nFor **Medium and Large tasks**, after presenting the design, use the confirmation gate with:\n\n- **question**: A concise Implementation Plan (see format below)\n- **options**:\n  - `\"Yes, proceed with implementation\"`\n  - `\"No — let's adjust the design\"`\n\n**Implementation Plan format:**\n```\nIntegration strategy : <which priority level from the Integration Strategy list>\nNew module location  : <file/directory path>\nPublic interfaces    : <what is exposed>\nExisting code touched: <files modified, or \"none — pure addition\">\nDependencies         : <what this module depends on>\n```\n\n**Decision rules by task scale:**\n\n| Scale | Behavior |\n|-------|----------|\n| **Large** | Always use the confirmation gate. Do not create any file until user selects \"Yes\". |\n| **Medium** | Always use the confirmation gate. Do not create any file until user selects \"Yes\". |\n| **Lightweight** | Skip — proceed directly to Step 3. |\n\n**If user selects \"No\":** ask *\"What would you like to change about the design?\"*, revise the Implementation Plan, and use the confirmation gate again before proceeding.\n\n---\n\n### Step 2.5: TDD Mode — Write Contract Tests First (Medium / Large Tasks Only)\n\n> **Skip this step for Lightweight tasks.** Only activate when the task scale is Medium or Large (per §3.2).\n\n> **§P config check:** read `.sextant.yaml` before prompting.\n> - `tdd: enforce` → skip the prompt; TDD is mandatory for all tasks\n> - `tdd: default_on` → treat both Large and Medium as default Y\n> - `tdd: off` or absent → use the scale-based defaults below\n\nTDD mode: write contract tests first?\n  **Large task → default Y** (opt out explicitly if not applicable)\n  **Medium task → default n** (opt in if you want contract-first coverage)\n\n**If Y:**\n- Write **complete, runnable tests** for each new public interface: all three of Arrange, Act, and Assert — no `TODO` placeholders\n- The Act calls the not-yet-implemented function or method directly; the test will fail because the implementation is absent or returns wrong output\n- Valid red-light failure: `NameError` / `ImportError` / assertion on wrong return value\n- Invalid \"failure\": syntax error, placeholder comment, test that cannot run at all — these are not TDD red tests\n- Cover: 1 happy path, 1 null/boundary case, 1 error path\n- These tests must fail **because the contract is not yet fulfilled** — that is the correct red state in red-green-refactor\n- For full test writing guidance, link `sextant:write-tests`.\n\n**If N (or Lightweight task):** Proceed directly to Step 3.\n\n### Step 3: Implement — Follow Architecture Conventions\n\n**Naming:** Fully consistent with the project's existing naming style (camelCase/snake_case, prefix/suffix conventions, abbreviation habits)\n\n**Dependency direction:** Only upper layers depend on lower layers; reverse dependencies are not allowed. New modules must not introduce reverse dependencies.\n\n**Interface protocol:** Interaction with existing modules must be consistent — if existing modules communicate through dependency injection, the new module uses dependency injection; if through event bus, use event bus.\n\n**Extend, don't modify:** Prioritize OCP-compatible integration; avoid changing existing stable modules.\n\n**Internal module structure:**\n- Internal classes/functions are private by default; only expose necessary public interfaces\n- Public interfaces must have explicit type declarations and parameter validation\n- If the module needs to share data structures with other modules, place them in a dedicated shared layer\n\n**Hollywood Principle:** New modules only declare dependencies (constructor injection / config registration) and do not proactively pull them.\n\n```python\n# ✅ Correct dependency approach for new module\nclass NewFeatureService:\n    def __init__(self, repo: FeatureRepository, bus: EventBus):\n        self._repo = repo\n        self._bus = bus\n\n# ❌ Incorrect dependency approach for new module\nclass NewFeatureService:\n    def __init__(self):\n        self._repo = MySQLFeatureRepository(\"localhost\")  # Self-construct\n        self._bus = EventBus.get_instance()                # Proactively pull\n```\n\n### Step 4: Architecture Compliance Audit (Required)\n\nAfter completing the new module, run through an architecture audit:\n\n```\n─── New Module Architecture Audit Checklist ─────────\n[ ] Is the layering correct? No layer-crossing calls?\n[ ] Has any circular dependency been introduced?\n[ ] Has any existing module's boundary been violated? (No direct references to other modules' internal implementations)\n[ ] Does the new module's responsibility overlap with existing modules?\n[ ] Is the external interface consistent with project style? (Naming, parameter style, error handling)\n[ ] Has any new global state or side effects been introduced?\n[ ] Is the dependency direction compliant? Any reverse dependencies?\n[ ] Does it follow the Hollywood Principle? (Dependencies injected, not pulled)\n[ ] Does documentation / comments / type definitions / routing config need to be updated?\n[ ] Does it need to be registered with existing factories / registries / config files?\n─────────────────────────────────────────────────────\n```\n\nAudit results must be clearly communicated to the user: **Passed ✅** or **Issues found ⚠️ (with specific details)**.\n\n---\n\n## Common Pitfalls\n\n| Pitfall | Description | Correct Approach |\n|---------|-------------|-----------------|\n| Responsibility overlap | New module implements functionality already covered by existing modules | Search for existing implementations first; prefer reusing or extending |\n| Style break | New code is inconsistent with existing project style | Strictly reference the most similar existing module |\n| Over-abstraction | New module only has one implementation yet introduces an abstraction layer | Follow YAGNI; abstract only when there's a second implementation |\n| Implicit coupling | New module interacts with other modules through global variables or implicit conventions | All interactions through public interfaces or event bus |\n| Missing registration | New module implemented but forgot to register with factory/routing/config | Audit checklist includes registration check |\n| Reverse dependency | For \"convenience,\" lower-layer module references higher-layer module | Strictly follow dependency direction rules |\n\n---\n\n## Sprint State Integration\n\nIf `.sextant/state.json` exists in the project root and the current task matches a sprint task:\n\n- **On start:** offer to update the task's `status` from `pending` → `in_progress`. Ask: *\"Update sprint state to mark Task N as in_progress?\"*\n- **On completion** (acceptance condition met): offer to update `status` to `done`. Ask: *\"Update sprint state to mark Task N as done?\"*\n- **On blocker** (test failure, missing dependency, unresolvable ambiguity that halts progress): surface the issue, then ask: *\"Mark Task N as blocked and record the reason in flags?\"* If confirmed, set `status: \"blocked\"` and append `{\"task\": N, \"reason\": \"<one-sentence blocker description>\"}` to the top-level `flags` array. Do not proceed to the next task while a task is blocked.\n\nDo not write the file without explicit user confirmation. If the user declines, continue without state updates.\n\n---\n\n## Reply Format\n\nEnd every new-feature response with this block (omit a field only if it genuinely has nothing to report):\n\nFeature Summary:\n\n| # | Item | Detail |\n|---|------|--------|\n| [1] | Conclusion | <one sentence: feature name + integration strategy used + outcome> |\n| [2] | Changes | <new files created; existing files modified; registrations added> |\n| [3] | Risks / Assumptions | <architectural assumptions; items not yet tested or integrated> |\n| [4] | Verification | <Step 4 architecture audit result: Passed ✅ / Issues ⚠️ (details)> |\n| [5] | Needs your input | <design decisions to confirm; manual registrations the user must handle> |","tags":["add","feature","sextant","hellotern","agent-skills","claude-code","skill-md"],"capabilities":["skill","source-hellotern","skill-add-feature","topic-agent-skills","topic-claude-code","topic-skill-md"],"categories":["Sextant"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/hellotern/Sextant/add-feature","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add hellotern/Sextant","source_repo":"https://github.com/hellotern/Sextant","install_from":"skills.sh"}},"qualityScore":"0.457","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 14 github stars · SKILL.md body (11,538 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T19:06:44.319Z","embedding":null,"createdAt":"2026-04-18T23:07:26.207Z","updatedAt":"2026-04-22T19:06:44.319Z","lastSeenAt":"2026-04-22T19:06:44.319Z","tsv":"'/principles/skill_body.md':4 '/tool-gitnexus/skill_body.md':5 '1':80,114,373,777,780,783,1441 '2':84,325,387,472,1451 '2.5':91,602 '3':68,98,401,475,574,827,829,1461 '3.2':630 '4':69,101,413,1015,1472,1475 '5':427,1482 'abbrevi':847 'abl':124 'absent':663,741 'abstract':203,314,1201,1211,1215 'abstraction/strategy':394 'accept':1323 'act':715,722 'activ':620 'ad':13,1460 'add':2,76,396 'add-featur':1 'addit':529 'adjust':506 'allow':862 'alreadi':201,1168 'alway':539,554 'ambigu':1349 'analysi':174 'answer':126 'append':1375 'applic':686 'approach':245,364,448,975,994,1161 'architectur':20,81,102,118,130,133,142,274,284,832,1016,1028,1032,1464,1476 'arrang':714 'array':1385 'ask':579,1310,1332,1357 'assert':717,753 'assumpt':1463,1465 'audit':103,1018,1029,1033,1140,1256,1477 'avail':267 'avoid':908 'awar':131 'base':145,376,391,668 'behavior':537 'behind':161 'belong':181,301 'best':155 'block':61,1362,1373,1397,1425 'blocker':1343 'boundari':454,1055 'break':1183 'bus':408,895,898,986,991,1244 'buse':212 'call':723,1043 'camelcase/snake_case':844 'cannot':766 'case':782 'chang':383,585,909,1452 'check':633,1260 'checklist':280,1034,1257 'circular':1046 'clarifi':332 'class':979,998 'classes/functions':917 'clean':141 'clear':1144 'close':261 'code':32,39,331,386,432,522,1185 'comment':763,1119 'common':1156 'communic':882,1145 'compat':906 'complet':46,112,703,1021,1322 'complianc':1017 'compliant':1103 'compon':144 'component-bas':143 'concis':492 'conclus':1442 'condit':1324 'config':415,421,632,964,1123,1138 'config-driven':414 'confirm':87,309,316,468,487,542,557,596,1370,1406,1489 'consist':36,836,878,1080 'construct':1008 'constructor':962 'context':270 'continu':1411 'contract':93,606,674,697,792 'contract-first':696 'conveni':1264 'convent':242,833,846,1236 'core':10 'correct':800,973,1038,1160 'coupl':1224 'cover':776,1169 'coverag':699 'creat':220,354,546,561,1455 'cross':1042 'current':108,1291 'data':943 'decis':336,531,1487 'declar':933,960 'declin':1410 'decoupl':409 'dedic':952 'def':981,1000 'default':650,658,669,679,689,921 'definit':1121 'depend':197,243,308,530,849,854,859,869,884,890,961,974,993,1047,1101,1106,1113,1262,1276,1347 'descript':1159 'design':86,326,334,484,508,588,1486 'detail':1155,1440,1481 'determin':295,303 'direct':571,732,824,850,1059,1102,1277 'directori':165,287,342,361 'document':1118 'domain':172,353 'done':1331,1341 'driven':404,416 'e.g':205 'effect':1096 'enabl':417 'end':1417 'enforc':639 'entir':351 'entri':186 'error':246,761,784,1087 'event':211,403,407,894,897,1243 'event-driven':402 'eventbus':987 'eventbus.get':1010 'everi':1418 'execut':47 'exist':19,38,117,150,189,206,227,322,359,379,385,393,411,430,463,521,841,874,880,910,1052,1074,1135,1171,1175,1189,1197,1284,1456 'expect':465 'explicit':683,931,1404 'explor':275 'expos':923 'extend':202,313,899,1181 'extens':389 'extension-point-bas':388 'extern':1078 'factori':209,1136 'factory/registry/routing':380 'factory/routing/config':1255 'fail':736,789 'failur':750,759,1345 'featur':3,7,15,77,151,170,180,194,232,300,306,346,419,436,1421,1437,1445 'featurerepositori':985 'field':1428 'file':239,422,466,524,548,563,1139,1402,1454,1457 'file/directory':517 'find':153,223 'first':608,676,698,1177 'flag':1368,1384 'flow':424 'follow':128,256,831,1109,1213,1275 'forgot':1251 'format':496,511,1416 'found':289,1152 'fulfil':796 'full':809 'fulli':35,835 'function':729,1167 'gate':469,488,543,558,597 'genuin':1432 'gitnexus':265 'global':1092,1232 'green':806 'guidanc':812 'habit':848 'halt':1351 'handl':247,1088,1495 'happi':778 'high':367 'higher':1271 'higher-lay':1270 'hollywood':955,1111 'implement':99,152,235,278,392,493,502,509,591,728,739,830,1065,1166,1176,1207,1222,1249 'implicit':1223,1235 'importerror':752 'includ':1258 'inconsist':1187 'incorrect':992 'inform':442 'init':982,1001 'inject':244,885,891,963,1114 'input':1485 'instanc':1011 'integr':16,363,370,434,447,512,907,1281,1447,1471 'interact':44,461,872,1227,1238 'interfac':208,395,520,710,870,926,928,1079,1241 'intern':913,916,1064 'introduc':867,1049,1098,1209 'invalid':758 'invas':428 'issu':1151,1355,1480 'item':1439,1466 'larg':440,479,538,610,628,654,677 'large/medium':95 'last':437 'layer':168,176,297,853,857,954,1037,1041,1212,1267,1272 'layer-cross':1040 'let':504 'level':343,1383 'light':749 'lightweight':63,568,617,821 'like':21,583 'link':813 'localhost':1005 'locat':335,516 'logic':160 'low':369 'lower':856,1266 'lower-lay':1265 'main':423 'mandatori':645 'manual':1490 'mark':1315,1337,1358 'match':1293 'mcp':271 'medium':477,553,609,626,656,687 'medium/large':71 'met':1325 'method':731 'microservic':146 'miss':1245,1346 'mode':604,672 'modifi':400,429,525,902,1458 'modul':8,190,222,228,254,294,323,360,412,431,458,464,515,864,875,881,888,912,914,939,947,958,978,997,1024,1031,1053,1063,1069,1075,1165,1172,1198,1203,1226,1230,1248,1268,1273 'must':122,788,865,876,929,1142,1494 'mvc':139 'mvvm':140 'mysqlfeaturerepositori':1004 'n':690,819,1317,1339,1360,1377 'name':241,834,842,1084,1446 'nameerror':751 'nativ':23 'necessari':924 'need':195,217,940,1124,1130,1483 'new':6,14,31,179,193,215,231,253,299,305,352,418,435,457,514,708,863,887,957,977,996,1023,1030,1068,1091,1164,1184,1202,1225,1247,1420,1453 'new-featur':1419 'newfeatureservic':980,999 'next':1391 'none':527 'not-yet-impl':725 'noth':1434 'null/boundary':781 'observ':237 'ocp':905 'ocp-compat':904 'offer':1299,1326 'omit':1426 'one':216,1206,1443 'opt':681,691 'option':498 'order':366 'organ':251,288 'outcom':1450 'output':57,745 'outsid':26 'over-abstract':1199 'overlap':318,1072,1163 'p':631 'parallel':356 'paramet':935,1085 'pass':1149,1479 'path':518,779,785 'pattern':45,134,248,259,285 'pend':1307 'per':629 'pitfal':1157,1158 'place':337,948 'placehold':720,762 'plan':494,510,592 'point':187,204,315,390 'posit':173 'possibl':263 'pre':277 'pre-implement':276 'prefer':1178 'prefix/suffix':845 'present':482 'principl':11,956,1112 'priorit':903 'prioriti':365,372 'privat':919 'proactiv':969,1012 'proceed':500,570,600,823,1388 'progress':49,60,78,89,1309,1320,1352 'project':137,163,283,839,1082,1190,1287 'prompt':637,642 'protocol':871 'public':519,709,925,927,1240 'publish/subscribe':405 'pull':970,1013,1116 'pure':528 'python':972 'queri':269 'question':129,490 'read':634 'reason':1366,1378 'record':1364 'red':748,774,801,805 'red-green-refactor':804 'red-light':747 'refactor':807 'refer':156,221,236,293,1060,1193,1269 'referenc':358 'regist':377,1133,1253 'registr':965,1246,1259,1459,1491 'registri':210,375,1137 'registry-bas':374 'replac':104 'repli':1415 'repo':984,989 'report':1436 'requir':1019 'research':82,279 'resort':438 'respons':320,453,1071,1162,1422 'result':1141,1478 'return':743,756 'reus':1179 'revers':858,868,1105,1261 'revis':589 'risk':1462 'root':1288 'rout':1122 'rule':532,1278 'run':767,1025 'runnabl':704 'scale':535,536,624,667 'scale-bas':666 'scratch':30 'search':1173 'second':1221 'see':495 'select':551,566,577 'self':983,1002,1007 'self-construct':1006 'self._bus':990,1009 'self._repo':988,1003 'sentenc':1444 'set':1371 'sextant':814 'sextant.yaml':635 'sextant/state.json':1283 'share':942,953 'show':65,73 'side':1095 'similar':149,226,292,345,1196 'skill' 'skill-add-feature' 'skip':569,613,640 'solut':85,328 'source-hellotern' 'specif':1154 'sprint':1279,1295,1312,1334 'stabl':911 'start':28,53,120,1298 'state':802,1093,1280,1313,1335,1413 'status':1305,1329,1372 'step':56,67,75,79,83,90,97,100,109,113,324,471,474,573,601,615,826,828,1014,1474 'strategi':207,371,513,1448 'strict':1192,1274 'structur':42,166,240,357,362,467,915,944 'style':41,843,1083,1086,1182,1191 'summari':1438 'surfac':1353 'syntax':760 'tabl':381 'task':64,72,441,480,534,611,618,623,648,678,688,822,1292,1296,1303,1316,1338,1359,1376,1392,1395 'tdd':92,603,638,643,649,660,671,773 'test':94,250,607,675,705,734,764,775,787,810,817,1344,1469 'three':712 'todo':719 'tool':272 'top':1382 'top-level':1381 'topic-agent-skills' 'topic-claude-code' 'topic-skill-md' 'touch':523 'track':50 'treat':652 'type':932,1120 'unawar':426 'understand':115,281 'unresolv':1348 'updat':59,1127,1301,1311,1328,1333,1414 'upper':852 'use':138,268,451,485,540,555,594,664,889,896,1449 'user':444,550,565,576,1148,1405,1409,1493 'valid':746,936 'valu':757 'variabl':1233 'verif':1473 'via':406 'violat':1057 'want':695 'whether':310 'without':1403,1412 'workflow':9,48 'would':581 'write':330,605,673,702,811,816,1400 'write-test':815 'wrong':744,755 'y':659,680,701 'yagni':1214 'yes':499,552,567 'yet':727,795,1208,1468 'zero':382","prices":[{"id":"a424098d-0523-4c38-bfe1-f8a2e6ff0b3b","listingId":"a0184d13-f341-42b5-ad99-396a907066fe","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"hellotern","category":"Sextant","install_from":"skills.sh"},"createdAt":"2026-04-18T23:07:26.207Z"}],"sources":[{"listingId":"a0184d13-f341-42b5-ad99-396a907066fe","source":"github","sourceId":"hellotern/Sextant/add-feature","sourceUrl":"https://github.com/hellotern/Sextant/tree/main/skills/add-feature","isPrimary":false,"firstSeenAt":"2026-04-18T23:07:26.207Z","lastSeenAt":"2026-04-22T19:06:44.319Z"}],"details":{"listingId":"a0184d13-f341-42b5-ad99-396a907066fe","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"hellotern","slug":"add-feature","github":{"repo":"hellotern/Sextant","stars":14,"topics":["agent-skills","claude-code","skill-md"],"license":"mit","html_url":"https://github.com/hellotern/Sextant","pushed_at":"2026-04-07T00:57:27Z","description":"init","skill_md_sha":"3dd98f99fb2ee5b8629c0e8c42748cb040762bef","skill_md_path":"skills/add-feature/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/hellotern/Sextant/tree/main/skills/add-feature"},"layout":"multi","source":"github","category":"Sextant","frontmatter":{"description":">-"},"skills_sh_url":"https://skills.sh/hellotern/Sextant/add-feature"},"updatedAt":"2026-04-22T19:06:44.319Z"}}