@godv61/dsh-task-engine 0.29.3 → 0.29.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.adaptive-test.mjs +302 -149
  2. package/.codex-project-test.mjs +18 -18
  3. package/.evidence-test.mjs +16 -3
  4. package/.hook-test.mjs +19 -19
  5. package/.resource-test.mjs +19 -2
  6. package/.roundtrip-test.mjs +8 -3
  7. package/.sonar-credential-test.mjs +38 -0
  8. package/.sonarlint-local-test.mjs +65 -0
  9. package/.workflow-test.mjs +29 -12
  10. package/README.md +22 -22
  11. package/docs/CHANGELOG.md +33 -19
  12. package/docs/README.md +6 -6
  13. package/docs/adaptive-workflows.md +85 -73
  14. package/docs/configuration.md +4 -4
  15. package/docs/faq.md +24 -18
  16. package/docs/getting-started.md +9 -9
  17. package/docs/manual-legacy.html +1 -1
  18. package/docs/manual.html +124 -117
  19. package/docs/roadmap.md +7 -7
  20. package/hooks/commit-msg +1 -1
  21. package/lib/adaptive.js +1 -1
  22. package/lib/adaptive.js.map +1 -1
  23. package/lib/client.js +289 -17
  24. package/lib/client.js.map +2 -2
  25. package/lib/controller.d.ts +35 -0
  26. package/lib/controller.js +68 -0
  27. package/lib/controller.js.map +1 -1
  28. package/lib/dev-task.d.ts +2 -0
  29. package/lib/dev-task.js +261 -31
  30. package/lib/dev-task.js.map +1 -1
  31. package/lib/engine.d.ts +1 -1
  32. package/lib/hook.js +3 -3
  33. package/lib/hook.js.map +1 -1
  34. package/lib/project-init.d.ts +4 -0
  35. package/lib/project-init.js +21 -2
  36. package/lib/project-init.js.map +1 -1
  37. package/lib/skill-audit.js +9 -1
  38. package/lib/skill-audit.js.map +1 -1
  39. package/lib/sonar-credential.d.ts +17 -0
  40. package/lib/sonar-credential.js +17 -0
  41. package/lib/sonar-credential.js.map +1 -0
  42. package/lib/sonar-report.d.ts +4 -0
  43. package/lib/sonar-report.js +40 -0
  44. package/lib/sonar-report.js.map +1 -0
  45. package/lib/sonar.d.ts +23 -2
  46. package/lib/sonar.js +55 -4
  47. package/lib/sonar.js.map +1 -1
  48. package/lib/sonarlint-local.d.ts +15 -0
  49. package/lib/sonarlint-local.js +307 -0
  50. package/lib/sonarlint-local.js.map +1 -0
  51. package/package.json +9 -7
  52. package/preset/enable.mjs +2 -2
  53. package/preset/persona.md +4 -4
  54. package/scripts/verify-dsh-compat.mjs +14 -14
  55. package/scripts/verify-package.mjs +7 -7
  56. package/skills/architecture-design/SKILL.md +11 -11
  57. package/skills/code-development/SKILL.md +11 -11
  58. package/skills/code-review/SKILL.md +11 -11
  59. package/skills/eng-delivery/SKILL.md +6 -4
  60. package/skills/requirements-analysis/SKILL.md +11 -11
  61. package/skills/task-orchestration/SKILL.md +11 -11
  62. package/skills/test-validation/SKILL.md +11 -11
package/lib/client.js CHANGED
@@ -38,7 +38,7 @@ __export(index_exports, {
38
38
  });
39
39
  module.exports = __toCommonJS(index_exports);
40
40
 
41
- // ../../dsharness/task-en/node_modules/zod/v3/external.js
41
+ // node_modules/zod/v3/external.js
42
42
  var external_exports = {};
43
43
  __export(external_exports, {
44
44
  BRAND: () => BRAND,
@@ -150,7 +150,7 @@ __export(external_exports, {
150
150
  void: () => voidType
151
151
  });
152
152
 
153
- // ../../dsharness/task-en/node_modules/zod/v3/helpers/util.js
153
+ // node_modules/zod/v3/helpers/util.js
154
154
  var util;
155
155
  (function(util2) {
156
156
  util2.assertEqual = (_) => {
@@ -284,7 +284,7 @@ var getParsedType = (data) => {
284
284
  }
285
285
  };
286
286
 
287
- // ../../dsharness/task-en/node_modules/zod/v3/ZodError.js
287
+ // node_modules/zod/v3/ZodError.js
288
288
  var ZodIssueCode = util.arrayToEnum([
289
289
  "invalid_type",
290
290
  "invalid_literal",
@@ -402,7 +402,7 @@ ZodError.create = (issues) => {
402
402
  return error;
403
403
  };
404
404
 
405
- // ../../dsharness/task-en/node_modules/zod/v3/locales/en.js
405
+ // node_modules/zod/v3/locales/en.js
406
406
  var errorMap = (issue, _ctx) => {
407
407
  let message;
408
408
  switch (issue.code) {
@@ -505,7 +505,7 @@ var errorMap = (issue, _ctx) => {
505
505
  };
506
506
  var en_default = errorMap;
507
507
 
508
- // ../../dsharness/task-en/node_modules/zod/v3/errors.js
508
+ // node_modules/zod/v3/errors.js
509
509
  var overrideErrorMap = en_default;
510
510
  function setErrorMap(map) {
511
511
  overrideErrorMap = map;
@@ -514,7 +514,7 @@ function getErrorMap() {
514
514
  return overrideErrorMap;
515
515
  }
516
516
 
517
- // ../../dsharness/task-en/node_modules/zod/v3/helpers/parseUtil.js
517
+ // node_modules/zod/v3/helpers/parseUtil.js
518
518
  var makeIssue = (params) => {
519
519
  const { data, path, errorMaps, issueData } = params;
520
520
  const fullPath = [...path, ...issueData.path || []];
@@ -624,14 +624,14 @@ var isDirty = (x) => x.status === "dirty";
624
624
  var isValid = (x) => x.status === "valid";
625
625
  var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
626
626
 
627
- // ../../dsharness/task-en/node_modules/zod/v3/helpers/errorUtil.js
627
+ // node_modules/zod/v3/helpers/errorUtil.js
628
628
  var errorUtil;
629
629
  (function(errorUtil2) {
630
630
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
631
631
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
632
632
  })(errorUtil || (errorUtil = {}));
633
633
 
634
- // ../../dsharness/task-en/node_modules/zod/v3/types.js
634
+ // node_modules/zod/v3/types.js
635
635
  var ParseInputLazyPath = class {
636
636
  constructor(parent, value, path, key) {
637
637
  this._cachedPath = [];
@@ -4248,6 +4248,26 @@ var taskLedgerViewSchema = external_exports.object({
4248
4248
  updated_at: external_exports.string().optional(),
4249
4249
  verification_passed: external_exports.boolean().optional(),
4250
4250
  review_outcome: external_exports.string().optional(),
4251
+ sonar: external_exports.object({
4252
+ source: external_exports.string(),
4253
+ audit: external_exports.object({
4254
+ gate: external_exports.string(),
4255
+ checked_at: external_exports.string(),
4256
+ target: external_exports.string(),
4257
+ blocking_count: external_exports.number(),
4258
+ uncovered_files: external_exports.array(external_exports.string()),
4259
+ report_path: external_exports.string().optional(),
4260
+ scanned_files: external_exports.array(external_exports.string()).optional(),
4261
+ findings: external_exports.array(external_exports.object({
4262
+ key: external_exports.string(),
4263
+ rule: external_exports.string(),
4264
+ message: external_exports.string(),
4265
+ severity: external_exports.string(),
4266
+ file: external_exports.string(),
4267
+ line: external_exports.number().optional()
4268
+ }))
4269
+ }).optional()
4270
+ }).optional(),
4251
4271
  task_id: external_exports.string(),
4252
4272
  title: external_exports.string(),
4253
4273
  stage: external_exports.string(),
@@ -4298,7 +4318,11 @@ var adaptiveConfigSchema = external_exports.object({
4298
4318
  host_url: external_exports.string().optional(),
4299
4319
  project_key: external_exports.string().optional(),
4300
4320
  mode: external_exports.enum(["branch", "pull-request"]).optional(),
4301
- token_env: external_exports.string().optional()
4321
+ token_env: external_exports.string().optional(),
4322
+ source: external_exports.enum(["ci", "local", "ide-local"]).optional(),
4323
+ reference_branch: external_exports.string().optional(),
4324
+ scan_command: external_exports.string().optional(),
4325
+ include_paths: external_exports.array(external_exports.string()).optional()
4302
4326
  }).optional()
4303
4327
  });
4304
4328
  var adaptiveViewSchema = external_exports.object({
@@ -4310,6 +4334,8 @@ var adaptiveViewSchema = external_exports.object({
4310
4334
  grades: external_exports.array(external_exports.object({ id: external_exports.string(), label: external_exports.string(), guidance: external_exports.string(), stages: external_exports.array(external_exports.string()) }))
4311
4335
  });
4312
4336
  var adaptiveWriteRequestSchema = external_exports.object({ path: external_exports.string(), config: adaptiveConfigSchema, expected_hash: external_exports.string() });
4337
+ var sonarTokenInfoSchema = external_exports.object({ configured: external_exports.boolean(), source: external_exports.string().optional(), writable: external_exports.boolean() });
4338
+ var sonarTokenWriteSchema = external_exports.object({ path: external_exports.string(), token: external_exports.string().min(1) });
4313
4339
  var projectSkillProfileRequestSchema = external_exports.object({ path: external_exports.string(), name: external_exports.string() });
4314
4340
  var projectSkillProfileWriteRequestSchema = projectSkillProfileRequestSchema.extend({
4315
4341
  profile: skillProfileSchema,
@@ -4348,6 +4374,48 @@ var TYPERT_REMOTE = {
4348
4374
  }],
4349
4375
  result: { mode: "strict", typeSymbol: `${PACKAGE}/types#AdaptiveConfigView`, create: () => adaptiveViewSchema, schema: adaptiveViewSchema }
4350
4376
  },
4377
+ {
4378
+ id: `${PACKAGE}#task-engine/describeSonarToken`,
4379
+ service: "taskEngineController",
4380
+ namespace: "task-engine",
4381
+ method: "describeSonarToken",
4382
+ invocation: { kind: "direct" },
4383
+ parameters: [{
4384
+ name: "path",
4385
+ wire: "path",
4386
+ source: "json",
4387
+ codec: { mode: "strict", typeSymbol: "string", create: () => external_exports.string(), schema: external_exports.string() }
4388
+ }],
4389
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#SonarTokenInfo`, create: () => sonarTokenInfoSchema, schema: sonarTokenInfoSchema }
4390
+ },
4391
+ {
4392
+ id: `${PACKAGE}#task-engine/setSonarToken`,
4393
+ service: "taskEngineController",
4394
+ namespace: "task-engine",
4395
+ method: "setSonarToken",
4396
+ invocation: { kind: "direct" },
4397
+ parameters: [{
4398
+ name: "request",
4399
+ wire: "request",
4400
+ source: "json",
4401
+ codec: { mode: "strict", typeSymbol: `${PACKAGE}/types#SonarTokenWrite`, create: () => sonarTokenWriteSchema, schema: sonarTokenWriteSchema }
4402
+ }],
4403
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#SonarTokenInfo`, create: () => sonarTokenInfoSchema, schema: sonarTokenInfoSchema }
4404
+ },
4405
+ {
4406
+ id: `${PACKAGE}#task-engine/unsetSonarToken`,
4407
+ service: "taskEngineController",
4408
+ namespace: "task-engine",
4409
+ method: "unsetSonarToken",
4410
+ invocation: { kind: "direct" },
4411
+ parameters: [{
4412
+ name: "path",
4413
+ wire: "path",
4414
+ source: "json",
4415
+ codec: { mode: "strict", typeSymbol: "string", create: () => external_exports.string(), schema: external_exports.string() }
4416
+ }],
4417
+ result: { mode: "strict", typeSymbol: `${PACKAGE}/types#SonarTokenInfo`, create: () => sonarTokenInfoSchema, schema: sonarTokenInfoSchema }
4418
+ },
4351
4419
  {
4352
4420
  id: `${PACKAGE}#task-engine/readProjectSkillProfile`,
4353
4421
  service: "taskEngineController",
@@ -5258,9 +5326,18 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5258
5326
  const [saving, setSaving] = (0, import_react3.useState)(false);
5259
5327
  const [dirty, setDirty] = (0, import_react3.useState)(false);
5260
5328
  const [message, setMessage] = (0, import_react3.useState)("");
5329
+ const [sonarToken, setSonarToken] = (0, import_react3.useState)("");
5330
+ const [tokenInfo, setTokenInfo] = (0, import_react3.useState)(null);
5331
+ const [tokenBusy, setTokenBusy] = (0, import_react3.useState)(false);
5261
5332
  const refresh = (0, import_react3.useCallback)(() => {
5262
5333
  setLoading(true);
5263
5334
  setMessage("");
5335
+ setSonarToken("");
5336
+ setTokenInfo(null);
5337
+ void remote.describeSonarToken(workspace).then((result) => {
5338
+ if (result.ok) setTokenInfo(result.value);
5339
+ }, () => {
5340
+ });
5264
5341
  void Promise.all([remote.readAdaptive(workspace), remote.listSkills(workspace), remote.listRules(workspace)]).then(([config, catalog, ruleCatalog]) => {
5265
5342
  setLoading(false);
5266
5343
  if (!config.ok) {
@@ -5397,6 +5474,39 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5397
5474
  setMessage("\u4FDD\u5B58\u5931\u8D25\uFF1A" + describeError(error));
5398
5475
  });
5399
5476
  };
5477
+ const saveToken = () => {
5478
+ if (!sonarToken.trim()) return;
5479
+ setTokenBusy(true);
5480
+ void remote.setSonarToken({ path: workspace, token: sonarToken }).then((result) => {
5481
+ setTokenBusy(false);
5482
+ if (!result.ok) {
5483
+ setMessage("\u4FDD\u5B58 SonarQube Token \u5931\u8D25\uFF1A" + describeError(result.error));
5484
+ return;
5485
+ }
5486
+ setSonarToken("");
5487
+ setTokenInfo(result.value);
5488
+ setMessage("\u5F53\u524D\u9879\u76EE\u7684 SonarQube Token \u5DF2\u4FDD\u5B58\u5230\u672C\u673A DSH \u51ED\u636E\u5B58\u50A8\uFF0C\u53EF\u7ACB\u5373\u4F7F\u7528\u3002");
5489
+ }, (error) => {
5490
+ setTokenBusy(false);
5491
+ setMessage("\u4FDD\u5B58 SonarQube Token \u5931\u8D25\uFF1A" + describeError(error));
5492
+ });
5493
+ };
5494
+ const clearToken = () => {
5495
+ setTokenBusy(true);
5496
+ void remote.unsetSonarToken(workspace).then((result) => {
5497
+ setTokenBusy(false);
5498
+ if (!result.ok) {
5499
+ setMessage("\u79FB\u9664 SonarQube Token \u5931\u8D25\uFF1A" + describeError(result.error));
5500
+ return;
5501
+ }
5502
+ setSonarToken("");
5503
+ setTokenInfo(result.value);
5504
+ setMessage("\u5DF2\u79FB\u9664\u5F53\u524D\u9879\u76EE\u4FDD\u5B58\u5728\u672C\u673A\u7684 SonarQube Token\u3002");
5505
+ }, (error) => {
5506
+ setTokenBusy(false);
5507
+ setMessage("\u79FB\u9664 SonarQube Token \u5931\u8D25\uFF1A" + describeError(error));
5508
+ });
5509
+ };
5400
5510
  const candidates = [...new Set(skills.map((skill) => skill.name))].filter((name) => name !== "eng-delivery" && !(name in META_STAGES)).sort();
5401
5511
  const sonar = draft.sonar ?? {};
5402
5512
  return (0, import_react3.createElement)(
@@ -5484,14 +5594,34 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5484
5594
  "\u542F\u7528\uFF08\u4EC5\u4EE3\u7801\u5BA1\u6838\u9636\u6BB5\uFF09"
5485
5595
  )
5486
5596
  ),
5487
- (0, import_react3.createElement)("span", { style: label }, "\u590D\u7528 CI \u626B\u63CF\u7684 ceTaskId\uFF1B\u8D28\u91CF\u95E8\u7981\u6216\u65B0\u4EE3\u7801\u4E2D\u9AD8\u7B49\u7EA7\u95EE\u9898\u672A\u901A\u8FC7\u65F6\u963B\u6B62\u5BA1\u6838\u3002Token \u4EC5\u4ECE\u670D\u52A1\u8FDB\u7A0B\u73AF\u5883\u53D8\u91CF\u8BFB\u53D6\uFF0C\u4E0D\u5199\u5165\u4ED3\u5E93\u3002"),
5597
+ (0, import_react3.createElement)("span", { style: label }, "\u53EF\u590D\u7528 CI \u626B\u63CF\uFF0C\u6216\u5728\u672C\u673A\u6309\u670D\u52A1\u7AEF\u89C4\u5219\u5BA1\u6838\u65B0\u4EE3\u7801\u3002Token \u6309\u5F53\u524D\u9879\u76EE\u4FDD\u5B58\u5728\u672C\u673A DSH \u51ED\u636E\u5B58\u50A8\uFF0C\u4E0D\u5199\u5165\u4EE3\u7801\u4ED3\u5E93\uFF1B\u4ECD\u517C\u5BB9\u5DF2\u6709\u7684\u73AF\u5883\u53D8\u91CF\u3002"),
5488
5598
  sonar.enabled === true ? (0, import_react3.createElement)(
5489
5599
  "div",
5490
5600
  { style: grid },
5601
+ (0, import_react3.createElement)(
5602
+ "label",
5603
+ { style: { display: "flex", flexDirection: "column", gap: 4 } },
5604
+ (0, import_react3.createElement)("span", { style: label }, "\u626B\u63CF\u6765\u6E90"),
5605
+ (0, import_react3.createElement)(
5606
+ "select",
5607
+ {
5608
+ style: input,
5609
+ value: sonar.source ?? "ci",
5610
+ onChange: (event) => updateSonar({
5611
+ source: event.target.value,
5612
+ ...event.target.value !== "ci" ? { mode: "branch" } : {},
5613
+ ...event.target.value !== "ide-local" ? { include_paths: [] } : {}
5614
+ })
5615
+ },
5616
+ (0, import_react3.createElement)("option", { value: "ci" }, "CI \u5DF2\u6709\u7ED3\u679C"),
5617
+ (0, import_react3.createElement)("option", { value: "ide-local" }, "\u672C\u5730\u89C4\u5219\u5BA1\u6838\uFF08\u65E0\u9700\u63D0\u4EA4\u6216\u63A8\u9001\uFF09"),
5618
+ (0, import_react3.createElement)("option", { value: "local" }, "\u672C\u673A\u626B\u63CF\u5E76\u4E0A\u4F20\uFF08\u9700 Developer Edition\uFF09")
5619
+ )
5620
+ ),
5491
5621
  ...[
5492
5622
  ["host_url", "\u670D\u52A1\u5730\u5740", "https://sonar.example"],
5493
5623
  ["project_key", "\u9879\u76EE Key", "my-project"],
5494
- ["token_env", "Token \u73AF\u5883\u53D8\u91CF\u540D", "SONAR_TOKEN"]
5624
+ ["token_env", "Token \u73AF\u5883\u53D8\u91CF\u540D\uFF08\u53EF\u9009\u540E\u5907\uFF09", "SONAR_TOKEN"]
5495
5625
  ].map(([key, title, placeholder]) => (0, import_react3.createElement)(
5496
5626
  "label",
5497
5627
  { key, style: { display: "flex", flexDirection: "column", gap: 4 } },
@@ -5512,11 +5642,86 @@ function AdaptivePanel({ workspace, remote, onOpenInit }) {
5512
5642
  {
5513
5643
  style: input,
5514
5644
  value: sonar.mode ?? "branch",
5645
+ disabled: sonar.source === "local" || sonar.source === "ide-local",
5515
5646
  onChange: (event) => updateSonar({ mode: event.target.value })
5516
5647
  },
5517
5648
  (0, import_react3.createElement)("option", { value: "branch" }, "\u5206\u652F"),
5518
5649
  (0, import_react3.createElement)("option", { value: "pull-request" }, "\u5408\u5E76\u8BF7\u6C42")
5519
5650
  )
5651
+ ),
5652
+ sonar.source === "local" || sonar.source === "ide-local" ? (0, import_react3.createElement)(
5653
+ "label",
5654
+ { style: { display: "flex", flexDirection: "column", gap: 4 } },
5655
+ (0, import_react3.createElement)("span", { style: label }, sonar.source === "local" ? "\u65B0\u4EE3\u7801\u53C2\u8003\u5206\u652F\uFF08\u987B\u5DF2\u6709 Sonar \u5206\u6790\uFF09" : "\u65B0\u4EE3\u7801\u53C2\u8003\u5206\u652F\uFF08\u672C\u673A Git \u5206\u652F\uFF09"),
5656
+ (0, import_react3.createElement)("input", {
5657
+ style: input,
5658
+ value: sonar.reference_branch ?? "",
5659
+ placeholder: "\u4F8B\u5982 qdm_sit",
5660
+ onChange: (event) => updateSonar({ reference_branch: event.target.value })
5661
+ })
5662
+ ) : null,
5663
+ sonar.source === "local" ? (0, import_react3.createElement)(
5664
+ "label",
5665
+ { style: { display: "flex", flexDirection: "column", gap: 4 } },
5666
+ (0, import_react3.createElement)("span", { style: label }, "\u672C\u673A\u626B\u63CF\u547D\u4EE4\uFF08\u53EF\u9009\uFF1B\u4E0D\u586B\u5219\u81EA\u52A8\u9009\u62E9 Maven / sonar-scanner\uFF09"),
5667
+ (0, import_react3.createElement)("input", {
5668
+ style: input,
5669
+ value: sonar.scan_command ?? "",
5670
+ placeholder: "mvn org.sonarsource.scanner.maven:sonar-maven-plugin:5.5.0.6356:sonar",
5671
+ onChange: (event) => updateSonar({ scan_command: event.target.value })
5672
+ })
5673
+ ) : null,
5674
+ sonar.source === "local" ? (0, import_react3.createElement)(
5675
+ "span",
5676
+ { style: label },
5677
+ "\u672C\u673A\u5206\u652F\u626B\u63CF\u9700\u8981 SonarQube Developer Edition \u6216\u66F4\u9AD8\u7248\u672C\u3001\u5DF2\u6709\u5206\u6790\u7684\u53C2\u8003\u5206\u652F\u53CA\u672C\u673A\u626B\u63CF\u5668/JDK\uFF1BCommunity Build \u4F1A\u5728\u4E0A\u4F20\u524D\u62D2\u7EDD\u3002"
5678
+ ) : null,
5679
+ sonar.source === "ide-local" ? (0, import_react3.createElement)(
5680
+ "label",
5681
+ { style: { display: "flex", flexDirection: "column", gap: 4 } },
5682
+ (0, import_react3.createElement)("span", { style: label }, "\u672C\u5730\u5BA1\u6838\u8303\u56F4\uFF08\u6BCF\u884C\u4E00\u4E2A\u9879\u76EE\u76F8\u5BF9\u76EE\u5F55\u6216\u6587\u4EF6\uFF1B\u7559\u7A7A\u4E3A\u4EFB\u52A1\u5168\u90E8\u4EE3\u7801\uFF09"),
5683
+ (0, import_react3.createElement)("textarea", {
5684
+ style: { ...input, minHeight: 76 },
5685
+ value: (sonar.include_paths ?? []).join("\n"),
5686
+ placeholder: "\u4F8B\u5982 fp-bussiness\nfp-ruoyi\nfp-ruoyi-spring-boot\npom.xml",
5687
+ onChange: (event) => updateSonar({
5688
+ include_paths: event.target.value.split(/\r?\n|,/u).map((path) => path.trim()).filter(Boolean)
5689
+ })
5690
+ })
5691
+ ) : null,
5692
+ sonar.source === "ide-local" ? (0, import_react3.createElement)(
5693
+ "span",
5694
+ { style: label },
5695
+ "\u672C\u5730\u89C4\u5219\u5BA1\u6838\u4ECE SonarQube \u540C\u6B65\u9879\u76EE\u89C4\u5219\uFF0C\u6309\u4E0A\u65B9\u8303\u56F4\u7B5B\u9009\u4EFB\u52A1\u65B0\u589E\u4EE3\u7801\uFF0C\u4E0D\u4E0A\u4F20\u7ED3\u679C\u3002\u626B\u63CF\u8303\u56F4\u7531 CI \u6784\u5EFA\u4E0E\u9879\u76EE\u914D\u7F6E\u51B3\u5B9A\uFF0CQuality Profile \u672C\u8EAB\u4E0D\u51B3\u5B9A\u626B\u63CF\u54EA\u4E9B\u76EE\u5F55\u3002\u5176\u4ED6\u8BED\u8A00\u4EC5\u5728\u8BE5\u9879\u76EE\u5B58\u5728\u751F\u6548\u89C4\u5219\u800C\u672C\u5730\u65E0\u6CD5\u5206\u6790\u65F6\u5217\u4E3A\u672A\u8986\u76D6\u3002\u9700\u5B89\u88C5 SonarLint \u540E\u53F0\u7EC4\u4EF6\u5E76\u914D\u7F6E DSH_SONARLINT_JAVA\u3001DSH_SONARLINT_LIB\u3001DSH_SONARLINT_PLUGINS\u3002"
5696
+ ) : null,
5697
+ (0, import_react3.createElement)(
5698
+ "div",
5699
+ { style: { display: "flex", flexDirection: "column", gap: 5 } },
5700
+ (0, import_react3.createElement)("span", { style: label }, `\u5F53\u524D\u9879\u76EE Token\uFF1A${tokenInfo === null ? "\u72B6\u6001\u4E0D\u53EF\u7528" : tokenInfo.configured ? "\u5DF2\u914D\u7F6E" : "\u672A\u914D\u7F6E"}`),
5701
+ (0, import_react3.createElement)("input", {
5702
+ type: "password",
5703
+ autoComplete: "new-password",
5704
+ style: input,
5705
+ value: sonarToken,
5706
+ placeholder: "\u8F93\u5165\u7528\u6237\u4EE4\u724C\uFF08\u4FDD\u5B58\u540E\u4E0D\u56DE\u663E\uFF09",
5707
+ onChange: (event) => setSonarToken(event.target.value)
5708
+ }),
5709
+ (0, import_react3.createElement)(
5710
+ "div",
5711
+ { style: row },
5712
+ (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5713
+ variant: "outline",
5714
+ size: "sm",
5715
+ disabled: tokenBusy || !sonarToken.trim() || tokenInfo?.writable === false,
5716
+ onClick: saveToken
5717
+ }, tokenBusy ? "\u5904\u7406\u4E2D\u2026" : "\u4FDD\u5B58 Token"),
5718
+ tokenInfo?.configured ? (0, import_react3.createElement)(import_dsh_client_ui_primitives2.Button, {
5719
+ variant: "outline",
5720
+ size: "sm",
5721
+ disabled: tokenBusy || tokenInfo.writable === false,
5722
+ onClick: clearToken
5723
+ }, "\u79FB\u9664 Token") : null
5724
+ )
5520
5725
  )
5521
5726
  ) : null
5522
5727
  ),
@@ -5559,7 +5764,7 @@ var card2 = {
5559
5764
  borderRadius: 8,
5560
5765
  padding: "12px 14px"
5561
5766
  };
5562
- var projectInitPrompt = (workspace) => `\u8BF7\u5728\u5F53\u524D\u9879\u76EE\u6839\u5DE5\u4F5C\u533A ${workspace} \u4F7F\u7528\u5DE5\u7A0B\u5316\u5F00\u53D1\u5F15\u64CE\u521D\u59CB\u5316\u9879\u76EE Skill \u548C Rule\u3002\u5148\u8C03\u7528 dev_task init_project\uFF08phase=inspect\uFF09\uFF0C\u7ED3\u5408\u4EE3\u8868\u6027\u6E90\u7801\u3001\u6784\u5EFA\u6587\u4EF6\u3001\u6D4B\u8BD5\u548C\u5DF2\u6709\u89C4\u8303\u6838\u5B9E\u626B\u63CF\u7ED3\u679C\u3002\u6309\u9879\u76EE\u5B9E\u9645\u60C5\u51B5\u62DF\u5B9A\u9879\u76EE\u7ED3\u6784\u5730\u56FE\u3001\u6280\u672F\u6808\u3001\u7F16\u7801\u65B9\u6CD5\u7B49 Skill \u548C\u5FC5\u8981\u7684 Rule\uFF0C\u5E76\u6807\u660E\u9002\u7528\u7684\u5143\u6280\u80FD\u3002\u8C03\u7528 phase=propose \u5C55\u793A\u62DF\u521B\u5EFA\u7684\u6587\u4EF6\u3001\u5185\u5BB9\u548C\u6302\u8F7D\u5173\u7CFB\uFF1B\u7B49\u6211\u5BA1\u9605\u786E\u8BA4\u540E\u518D\u8C03\u7528 phase=apply\u3002\u4E0D\u8981\u8986\u76D6\u540C\u540D\u8D44\u6E90\uFF0C\u4E5F\u4E0D\u8981\u628A\u5076\u53D1\u4EE3\u7801\u5199\u6CD5\u5F53\u6210\u56E2\u961F\u89C4\u8303\u3002`;
5767
+ var projectInitPrompt = (workspace) => `\u8BF7\u5728\u5F53\u524D\u9879\u76EE\u6839\u5DE5\u4F5C\u533A ${workspace} \u4F7F\u7528\u5DE5\u7A0B\u5316\u5F00\u53D1\u5F15\u64CE\u521D\u59CB\u5316\u9879\u76EE Skill \u548C Rule\u3002\u5148\u8C03\u7528 dev_task init_project\uFF08phase=inspect\uFF09\uFF0C\u7ED3\u5408\u4EE3\u8868\u6027\u6E90\u7801\u3001\u6784\u5EFA\u6587\u4EF6\u3001\u6D4B\u8BD5\u548C\u5DF2\u6709\u89C4\u8303\u6838\u5B9E\u626B\u63CF\u7ED3\u679C\u3002\u6309\u9879\u76EE\u5B9E\u9645\u60C5\u51B5\u62DF\u5B9A\u9879\u76EE\u7ED3\u6784\u5730\u56FE\u3001\u6280\u672F\u6808\u3001\u7F16\u7801\u65B9\u6CD5\u7B49 Skill \u548C\u5FC5\u8981\u7684 Rule\uFF0C\u5E76\u6807\u660E\u9002\u7528\u7684\u5143\u6280\u80FD\u3002\u9879\u76EE\u5730\u56FE\u5FC5\u987B\u603B\u7ED3\u6574\u4E2A\u4ED3\u5E93\u7684\u6A21\u5757\u804C\u8D23\u3001\u4F9D\u8D56\u548C\u901A\u7528\u4EE3\u7801\u5165\u53E3\uFF0C\u80FD\u591F\u4F9B\u4E0D\u540C\u9700\u6C42\u590D\u7528\uFF1B\u4E0D\u8981\u628A\u5F53\u524D\u4F1A\u8BDD\u7684\u9700\u6C42\u3001\u4E13\u5C5E\u8C03\u7528\u94FE\u6216\u5B9E\u73B0\u65B9\u6848\u5199\u6210\u9879\u76EE\u5730\u56FE\uFF0C\u76F8\u5173\u5185\u5BB9\u5E94\u8FDB\u5165\u8BE5\u4EFB\u52A1\u4EA7\u7269\u6216\u5355\u72EC\u7684\u9886\u57DF Skill\u3002\u8C03\u7528 phase=propose \u5C55\u793A\u62DF\u521B\u5EFA\u7684\u6587\u4EF6\u3001\u5185\u5BB9\u548C\u6302\u8F7D\u5173\u7CFB\uFF1B\u7B49\u6211\u5BA1\u9605\u786E\u8BA4\u540E\u518D\u8C03\u7528 phase=apply\u3002\u4E0D\u8981\u8986\u76D6\u540C\u540D\u8D44\u6E90\uFF0C\u4E5F\u4E0D\u8981\u628A\u5076\u53D1\u4EE3\u7801\u5199\u6CD5\u5F53\u6210\u56E2\u961F\u89C4\u8303\u3002`;
5563
5768
  function InitPanel({ workspace, remote }) {
5564
5769
  const [view, setView] = (0, import_react4.useState)(null);
5565
5770
  const [generating, setGenerating] = (0, import_react4.useState)(false);
@@ -5642,7 +5847,12 @@ function InitPanel({ workspace, remote }) {
5642
5847
  (0, import_react4.createElement)(
5643
5848
  "p",
5644
5849
  { style: styles.muted },
5645
- "\u626B\u63CF\u4EE3\u7801\u5E93\u5E76\u62DF\u5B9A\u9879\u76EE\u5730\u56FE\u3001\u6280\u672F\u6808\u3001\u7F16\u7801 Skill \u548C Rule\u3002\u5148\u9884\u89C8\u751F\u6210\u5185\u5BB9\uFF0C\u786E\u8BA4\u540E\u624D\u5199\u5165\u9879\u76EE\uFF1B\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u4E0D\u4F1A\u88AB\u8986\u76D6\u3002"
5850
+ "\u626B\u63CF\u53EA\u8FD4\u56DE\u9879\u76EE\u8BC1\u636E\u4E0E\u5EFA\u8BAE\u540D\u79F0\uFF1B\u4F1A\u8BDD\u6A21\u578B\u636E\u6B64\u62DF\u5B9A\u8986\u76D6\u6574\u4E2A\u4ED3\u5E93\u7684\u9879\u76EE\u5730\u56FE\u3001\u6280\u672F\u6808\u3001\u7F16\u7801 Skill \u548C Rule\u3002\u5F53\u524D\u9700\u6C42\u7684\u4E13\u5C5E\u4FE1\u606F\u5E94\u5199\u5165\u4EFB\u52A1\u4EA7\u7269\u3002\u5148\u9884\u89C8\u751F\u6210\u5185\u5BB9\uFF0C\u786E\u8BA4\u540E\u624D\u5199\u5165\u9879\u76EE\uFF1B\u5DF2\u6709\u540C\u540D\u8D44\u6E90\u4E0D\u4F1A\u88AB\u8986\u76D6\u3002"
5851
+ ),
5852
+ (0, import_react4.createElement)(
5853
+ "p",
5854
+ { style: styles.muted },
5855
+ "\u56E2\u961F\u5171\u4EAB\u65F6\uFF0C\u8BF7\u5C06\u751F\u6210\u7684 .dsh/skills\u3001.dsh/rules \u548C .dsh/meta.json \u7EB3\u5165 Git\uFF1B\u5BA1\u6838\u62A5\u544A\u53EF\u4FDD\u7559\u5728\u672C\u5730\u3002"
5646
5856
  ),
5647
5857
  (0, import_react4.createElement)(
5648
5858
  "p",
@@ -6489,7 +6699,7 @@ function itemAudit(item) {
6489
6699
  lines.push((0, import_react8.createElement)(
6490
6700
  "div",
6491
6701
  { key: "dispatch", style: metaLine },
6492
- (0, import_react8.createElement)("span", { style: badge }, "\u5DF2\u6D3E\u53D1"),
6702
+ (0, import_react8.createElement)("span", { style: badge }, "\u5DF2\u5F00\u59CB"),
6493
6703
  (0, import_react8.createElement)("span", null, item.dispatch.description === "" ? "\uFF08\u65E0\u63CF\u8FF0\uFF09" : item.dispatch.description),
6494
6704
  (0, import_react8.createElement)("span", { style: badge }, timeText(item.dispatch.at))
6495
6705
  ));
@@ -6516,10 +6726,65 @@ function itemAudit(item) {
6516
6726
  }
6517
6727
  }
6518
6728
  if (lines.length === 0) {
6519
- lines.push((0, import_react8.createElement)("div", { key: "none", style: metaLine }, (0, import_react8.createElement)("span", { style: badge }, "\u672A\u6D3E\u53D1 / \u672A\u5BA1\u67E5")));
6729
+ const status = item.status === "done" ? "\u5DF2\u6807\u8BB0\u5B8C\u6210\uFF0C\u7F3A\u5C11\u5B9E\u65BD\u9879\u5BA1\u67E5\u8BB0\u5F55" : item.status === "doing" ? "\u5B9E\u65BD\u4E2D\uFF0C\u5F85\u5BA1\u67E5" : "\u5F85\u5F00\u59CB";
6730
+ lines.push((0, import_react8.createElement)("div", { key: "none", style: metaLine }, (0, import_react8.createElement)("span", { style: badge }, status)));
6520
6731
  }
6521
6732
  return (0, import_react8.createElement)("div", { style: { display: "flex", flexDirection: "column", gap: 4 } }, ...lines);
6522
6733
  }
6734
+ function sonarAudit(task) {
6735
+ if (!task.sonar) return null;
6736
+ const audit = task.sonar.audit;
6737
+ if (!audit) return (0, import_react8.createElement)("div", { style: metaLine }, "SonarQube \u5DF2\u542F\u7528\uFF0C\u5C1A\u672A\u8FD0\u884C\u4EE3\u7801\u5BA1\u6838\u3002");
6738
+ const source = { "ide-local": "\u672C\u5730\u89C4\u5219\u5BA1\u6838", local: "\u672C\u673A\u4E0A\u4F20\u626B\u63CF", ci: "CI \u626B\u63CF" }[task.sonar.source] ?? task.sonar.source;
6739
+ const outcome = audit.gate === "OK" ? "\u901A\u8FC7" : "\u672A\u901A\u8FC7";
6740
+ return (0, import_react8.createElement)(
6741
+ "details",
6742
+ { style: { borderTop: "1px solid var(--dsw-alias-border-l2)", paddingTop: 8 } },
6743
+ (0, import_react8.createElement)(
6744
+ "summary",
6745
+ { style: { cursor: "pointer", fontSize: 13 } },
6746
+ `\u6700\u8FD1\u4E00\u6B21 SonarQube \u5BA1\u6838\uFF1A${outcome} \xB7 \u963B\u65AD ${audit.blocking_count} \u6761 \xB7 \u5168\u90E8 ${audit.findings.length} \u6761 \xB7 ${timeText(audit.checked_at)}`
6747
+ ),
6748
+ (0, import_react8.createElement)(
6749
+ "p",
6750
+ { style: metaLine },
6751
+ `\u6765\u6E90\uFF1A${source}\uFF1B\u5206\u6790\u76EE\u6807\uFF1A${audit.target}\u3002\u8FD9\u662F\u8BE5\u6B21\u5BA1\u6838\u8BB0\u5F55\uFF1B\u4EE3\u7801\u6216\u89C4\u5219\u53D8\u66F4\u540E\u9700\u91CD\u65B0\u6D4B\u8BD5\u5E76\u5BA1\u6838\u3002`
6752
+ ),
6753
+ audit.report_path ? (0, import_react8.createElement)("p", { style: metaLine }, `\u5BA1\u6838\u6587\u4EF6\uFF1A${audit.report_path}`) : null,
6754
+ audit.scanned_files?.length ? (0, import_react8.createElement)(
6755
+ "details",
6756
+ null,
6757
+ (0, import_react8.createElement)("summary", { style: { cursor: "pointer", fontSize: 12 } }, `\u672C\u6B21\u5206\u6790\u6587\u4EF6\uFF08${audit.scanned_files.length}\uFF09`),
6758
+ ...audit.scanned_files.map((file) => (0, import_react8.createElement)("div", { key: file, style: metaLine }, file))
6759
+ ) : null,
6760
+ ...audit.uncovered_files.map((file) => (0, import_react8.createElement)(
6761
+ "div",
6762
+ { key: `uncovered-${file}`, style: metaLine },
6763
+ `\u672A\u8986\u76D6\uFF1A${file}`
6764
+ )),
6765
+ audit.findings.length === 0 ? (0, import_react8.createElement)("p", { style: metaLine }, "\u6CA1\u6709\u65B0\u589E\u4EE3\u7801\u95EE\u9898\u3002") : (0, import_react8.createElement)(
6766
+ "div",
6767
+ { style: { display: "flex", flexDirection: "column", gap: 6 } },
6768
+ ...audit.findings.map((finding) => (0, import_react8.createElement)(
6769
+ "div",
6770
+ { key: finding.key, style: {
6771
+ ...itemRow,
6772
+ padding: "6px 0",
6773
+ fontSize: 12,
6774
+ overflowWrap: "anywhere"
6775
+ } },
6776
+ (0, import_react8.createElement)(
6777
+ "div",
6778
+ { style: headerRow },
6779
+ (0, import_react8.createElement)("strong", null, finding.severity),
6780
+ (0, import_react8.createElement)("code", null, finding.rule),
6781
+ (0, import_react8.createElement)("span", null, `${finding.file}${finding.line === void 0 ? "" : `:${finding.line}`}`)
6782
+ ),
6783
+ (0, import_react8.createElement)("span", null, finding.message)
6784
+ ))
6785
+ )
6786
+ );
6787
+ }
6523
6788
  function TaskLedger({ workspace, remote }) {
6524
6789
  const [tasks, setTasks] = (0, import_react8.useState)([]);
6525
6790
  const [error, setError] = (0, import_react8.useState)("");
@@ -6531,13 +6796,19 @@ function TaskLedger({ workspace, remote }) {
6531
6796
  if (workspace === "") return;
6532
6797
  setError("");
6533
6798
  setLoading(true);
6534
- void remote.readTasks(workspace).then((result) => {
6799
+ let timer;
6800
+ const timeout = new Promise((_, reject) => {
6801
+ timer = setTimeout(() => reject(new Error("\u8BFB\u53D6\u8D85\u65F6\uFF0C\u8BF7\u5237\u65B0\u9875\u9762\u6216\u91CD\u65B0\u767B\u5F55\u540E\u91CD\u8BD5")), 15e3);
6802
+ });
6803
+ void Promise.race([remote.readTasks(workspace), timeout]).then((result) => {
6535
6804
  setLoading(false);
6536
6805
  if (result.ok) setTasks(result.value.tasks);
6537
6806
  else setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(result.error));
6538
6807
  }, (reason) => {
6539
6808
  setLoading(false);
6540
6809
  setError("\u8BFB\u53D6\u53F0\u8D26\u5931\u8D25\uFF1A" + describeError(reason));
6810
+ }).finally(() => {
6811
+ if (timer !== void 0) clearTimeout(timer);
6541
6812
  });
6542
6813
  }, [remote, workspace]);
6543
6814
  (0, import_react8.useEffect)(() => {
@@ -6561,7 +6832,7 @@ function TaskLedger({ workspace, remote }) {
6561
6832
  (0, import_react8.createElement)("span", { style: styles.sourceBadge }, "\u53EA\u8BFB \xB7 \u6765\u81EA .dsh/task-*.json"),
6562
6833
  (0, import_react8.createElement)(import_dsh_client_ui_primitives5.Button, { variant: "outline", size: "sm", disabled: loading, onClick: refresh }, loading ? "\u8BFB\u53D6\u4E2D\u2026" : "\u5237\u65B0")
6563
6834
  ),
6564
- loading ? (0, import_react8.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react8.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react8.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u6D3E\u53D1\u4E0E\u5BA1\u67E5\u7559\u75D5\u3002") : visible.length === 0 ? (0, import_react8.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react8.createElement)(
6835
+ loading ? (0, import_react8.createElement)("p", { role: "status" }, "\u6B63\u5728\u8BFB\u53D6\u4EFB\u52A1\u2026") : error !== "" ? (0, import_react8.createElement)("p", { style: styles.status }, error) : tasks.length === 0 ? (0, import_react8.createElement)("p", { style: styles.muted }, "\u5F53\u524D\u5DE5\u4F5C\u533A\u8FD8\u6CA1\u6709\u4EFB\u52A1\uFF1A\u5F00\u5DE5\u540E\uFF08dev_task create\uFF09\u4F1A\u5728\u8FD9\u91CC\u5217\u51FA\u5B9E\u65BD\u4E0E\u5BA1\u67E5\u8BB0\u5F55\u3002") : visible.length === 0 ? (0, import_react8.createElement)("div", { className: "te-empty" }, "\u6CA1\u6709\u5339\u914D\u7684\u4EFB\u52A1\uFF0C\u8BF7\u8C03\u6574\u7B5B\u9009\u3002") : (0, import_react8.createElement)(
6565
6836
  "div",
6566
6837
  { style: { display: "flex", flexDirection: "column", gap: 12 } },
6567
6838
  ...visible.map((task) => (0, import_react8.createElement)(
@@ -6580,6 +6851,7 @@ function TaskLedger({ workspace, remote }) {
6580
6851
  (0, import_react8.createElement)("span", { className: "te-badge" }, `\u5BA1\u6838\uFF1A${task.review_outcome ?? "pending"}`),
6581
6852
  task.updated_at ? (0, import_react8.createElement)("span", { style: metaLine }, "\u66F4\u65B0\u4E8E " + timeText(task.updated_at)) : null
6582
6853
  ),
6854
+ sonarAudit(task),
6583
6855
  (0, import_react8.createElement)(
6584
6856
  "div",
6585
6857
  { style: { display: "flex", flexDirection: "column" } },